package core import ( "fmt" "git.urbach.dev/cli/q/src/asm" "git.urbach.dev/cli/q/src/ast" "git.urbach.dev/cli/q/src/errors" "git.urbach.dev/cli/q/src/eval" "git.urbach.dev/cli/q/src/token" ) // CompileAssign compiles an assign statement. func (f *Function) CompileAssign(node *ast.Assign) error { left := node.Expression.Children[0] right := node.Expression.Children[1] if left.Token.Kind == token.Separator { if right.Token.Kind == token.Div { return f.CompileAssignDivision(node.Expression) } if right.Token.Kind == token.Call { return f.MultiAssign(left, right) } return errors.New(errors.NotImplemented, f.File, node.Expression.Token.Position) } leftValue, err := f.Evaluate(left) if err != nil { return err } operation := node.Expression.Token switch leftValue := leftValue.(type) { case *eval.Register: f.Execute(operation, leftValue.Register, right) case *eval.Memory: // TODO: Reservation needs to be canceled on defer f.CurrentScope().Reserve(leftValue.Memory.Base) if operation.Kind == token.Assign { rightValue, err := f.Evaluate(right) if err != nil { return err } f.ValueToMemory(rightValue, leftValue.Memory) return nil } tmp := f.NewRegister() f.ValueToRegister(leftValue, tmp) err := f.Execute(operation, tmp, right) if err != nil { return err } f.MemoryRegister(asm.STORE, leftValue.Memory, tmp) f.FreeRegister(tmp) default: panic(fmt.Errorf("%s: not implemented: %v", f.UniqueName, leftValue)) } return nil }