83 lines
1.8 KiB
Go
83 lines
1.8 KiB
Go
package core
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
|
|
"git.urbach.dev/cli/q/src/asm"
|
|
"git.urbach.dev/cli/q/src/errors"
|
|
"git.urbach.dev/cli/q/src/eval"
|
|
"git.urbach.dev/cli/q/src/expression"
|
|
"git.urbach.dev/cli/q/src/types"
|
|
)
|
|
|
|
// EvaluateDot evaluates an access with the dot operator.
|
|
func (f *Function) EvaluateDot(expr *expression.Expression) (eval.Value, error) {
|
|
left := expr.Children[0]
|
|
right := expr.Children[1]
|
|
leftText := left.Token.Text(f.File.Bytes)
|
|
rightText := right.Token.Text(f.File.Bytes)
|
|
variable := f.VariableByName(leftText)
|
|
|
|
if variable != nil {
|
|
f.UseVariable(variable)
|
|
pointer := variable.Value.Typ.(*types.Pointer)
|
|
structure := pointer.To.(*types.Struct)
|
|
field := structure.FieldByName(rightText)
|
|
|
|
if field == nil {
|
|
return nil, errors.New(&errors.UnknownStructField{StructName: structure.Name(), FieldName: rightText}, f.File, right.Token.Position)
|
|
}
|
|
|
|
value := &eval.Memory{
|
|
Typ: field.Type,
|
|
Memory: asm.Memory{
|
|
Base: variable.Value.Register,
|
|
Offset: int8(field.Offset),
|
|
OffsetRegister: math.MaxUint8,
|
|
Length: byte(field.Type.Size()),
|
|
},
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
constant, isConst := f.All.Constants[f.Package+"."+leftText+"."+rightText]
|
|
|
|
if isConst {
|
|
number, err := ToNumber(constant.Token, constant.File)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
value := &eval.Number{
|
|
Typ: types.AnyInt,
|
|
Number: number,
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
if leftText != "main" {
|
|
imp, exists := f.File.Imports[leftText]
|
|
|
|
if exists {
|
|
imp.Used = true
|
|
} else {
|
|
_, exists := f.All.Extern[leftText]
|
|
|
|
if !exists {
|
|
return nil, errors.New(&errors.UnknownPackage{Name: leftText}, f.File, left.Token.Position)
|
|
}
|
|
}
|
|
}
|
|
|
|
value := &eval.Label{
|
|
Typ: types.AnyPointer,
|
|
Label: fmt.Sprintf("%s.%s", leftText, rightText),
|
|
}
|
|
|
|
return value, nil
|
|
}
|