package build import ( "strconv" "git.akyoto.dev/cli/q/src/build/asm" "git.akyoto.dev/cli/q/src/build/cpu" "git.akyoto.dev/cli/q/src/build/token" "git.akyoto.dev/cli/q/src/errors" ) // Calculate performs an operation on a register with the given operand. func (f *Function) Calculate(register cpu.Register, operation token.Token, operand token.Token) error { switch operand.Kind { case token.Number: value := operand.Text() number, err := strconv.Atoi(value) if err != nil { return err } return f.CalculateRegisterNumber(operation, register, number) case token.Identifier: name := operand.Text() variable, exists := f.Variables[name] if !exists { return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, operand.Position) } return f.CalculateRegisterRegister(operation, register, variable.Register) } return errors.New(errors.NotImplemented, f.File, operation.Position) } // CalculateRegisterNumber performs an operation on a register and a number. func (f *Function) CalculateRegisterNumber(operation token.Token, register cpu.Register, number int) error { switch operation.Text() { case "+", "+=": f.Assembler.RegisterNumber(asm.ADD, register, number) case "-", "-=": f.Assembler.RegisterNumber(asm.SUB, register, number) case "*", "*=": f.Assembler.RegisterNumber(asm.MUL, register, number) case "/", "/=": f.Assembler.RegisterNumber(asm.DIV, register, number) default: return errors.New(errors.NotImplemented, f.File, operation.Position) } return nil } // CalculateRegisterRegister performs an operation on two registers. func (f *Function) CalculateRegisterRegister(operation token.Token, destination cpu.Register, source cpu.Register) error { switch operation.Text() { case "+", "+=": f.Assembler.RegisterRegister(asm.ADD, destination, source) case "-", "-=": f.Assembler.RegisterRegister(asm.SUB, destination, source) case "*", "*=": f.Assembler.RegisterRegister(asm.MUL, destination, source) case "/", "/=": f.Assembler.RegisterRegister(asm.DIV, destination, source) default: return errors.New(errors.NotImplemented, f.File, operation.Position) } return nil }