package core import ( "fmt" "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/scope" "git.urbach.dev/cli/q/src/token" "git.urbach.dev/cli/q/src/types" "git.urbach.dev/cli/q/src/x86" ) // CompileAssignDivision compiles an assign statement that has quotient and remainder on the left side and division on the right. func (f *Function) CompileAssignDivision(expr *expression.Expression) error { var ( variables = expr.Children[0] division = expr.Children[1] quotientVariable *scope.Variable remainderVariable *scope.Variable err error ) if expr.Token.Kind == token.Define { quotientVariable, err = f.Define(variables.Children[0]) if err != nil { return err } remainderVariable, err = f.Define(variables.Children[1]) if err != nil { return err } quotientVariable.Type = types.Int remainderVariable.Type = types.Int f.AddVariable(quotientVariable) f.AddVariable(remainderVariable) } else { quotient := variables.Children[0] name := quotient.Token.Text(f.File.Bytes) quotientVariable = f.VariableByName(name) if quotientVariable == nil { return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, quotient.Token.Position) } remainder := variables.Children[1] name = remainder.Token.Text(f.File.Bytes) remainderVariable = f.VariableByName(name) if remainderVariable == nil { return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, remainder.Token.Position) } defer f.UseVariable(quotientVariable) defer f.UseVariable(remainderVariable) } dividendExpr := division.Children[0] dividend, err := f.Evaluate(dividendExpr) if err != nil { return err } if !types.Is(dividend.Type, types.AnyInt) { return errors.New(&errors.TypeMismatch{Encountered: dividend.Type.Name(), Expected: types.AnyInt.Name()}, f.File, dividendExpr.Token.Position) } divisor := division.Children[1] switch dividend.Kind { case eval.Number: f.SaveRegister(x86.RAX) f.RegisterNumber(asm.MOVE, x86.RAX, dividend.Number) err = f.Execute(division.Token, x86.RAX, divisor) case eval.Register: err = f.Execute(division.Token, dividend.Register, divisor) defer f.FreeRegister(dividend.Register) default: panic(fmt.Errorf("%s: not implemented: %d", f.UniqueName, dividend.Kind)) } f.RegisterRegister(asm.MOVE, quotientVariable.Register, x86.RAX) f.RegisterRegister(asm.MOVE, remainderVariable.Register, x86.RDX) return err }