Something went wrong. Try again.
🌱 A minimal programming language and compiler. git.urbach.dev/cli/q
high-performance programming-language compiler
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596package core
import ( "git.urbach.dev/cli/q/src/errors" "git.urbach.dev/cli/q/src/expression" "git.urbach.dev/cli/q/src/fs" "git.urbach.dev/cli/q/src/ssa" "git.urbach.dev/cli/q/src/token")
// evaluateDot converts a dot expression to an SSA value.func (f *Function) evaluateDot(expr *expression.Expression) (ssa.Value, error) { if len(expr.Children) != 2 { return nil, errors.NewAt(MissingFieldName, f.File, expr.Source().End()) }
left := expr.Children[0]
if left.Token.Kind == token.Invalid { return nil, errors.NewAt(MissingObject, f.File, left.Source().Start()) }
right := expr.Children[1]
if left.Token.Kind == token.Identifier && left.Token.StringFrom(f.File.Bytes) == "_cpu" { return f.evaluateCPU(right) }
reset := len(f.Block().Instructions) leftValue, err := f.evaluate(left)
if err != nil { return nil, err }
pkgValue, isPackage := leftValue.(*ssa.Package)
if isPackage { pkg := f.Env.Package(pkgValue.Name, f.File)
if pkg == nil { return nil, errors.New(&UnknownIdentifier{Name: pkgValue.Name}, f.File, left.Source()) }
if right.Token.Kind != token.Identifier { return nil, errors.New(ExpectedPackageMember, f.File, right.Source()) }
rightText := right.Token.StringFrom(f.File.Bytes) return f.evaluatePackageMember(pkg, rightText, expr) }
enumValue, isEnum := leftValue.(*ssa.Enum)
if isEnum { if right.Token.Kind != token.Identifier { return nil, errors.New(ExpectedEnumMember, f.File, right.Source()) }
rightText := right.Token.StringFrom(f.File.Bytes) constExpr, exists := enumValue.Typ.Member(rightText)
if !exists { return nil, errors.New(&UnknownEnumMember{EnumName: enumValue.Typ.Name(), MemberName: rightText}, f.File, right.Source()) }
tmp := f.File f.File = enumValue.Typ.File().(*fs.File) value, err := f.evaluateRight(constExpr.(*expression.Expression)) f.File = tmp
if err != nil { return nil, err }
return value, nil }
if expr.Parent != nil && expr.Parent.Token.Kind == token.Call && expr.Parent.Children[0] == expr { f.Block().Instructions = f.Block().Instructions[:reset] return f.evaluateMethod(leftValue, left, right, expr) }
if right.Token.Kind != token.Identifier { return nil, errors.New(ExpectedStructField, f.File, right.Source()) }
switch leftValue := leftValue.(type) { case *ssa.Struct: return f.fieldFromStruct(leftValue, left, right) case *ssa.Call: return f.fieldFromCall(leftValue, left, right, expr) default: return f.fieldFromMemory(leftValue, left, right, expr) }}