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 }