Enforced consistent naming

This commit is contained in:
Eduard Urbach 2024-06-26 23:24:11 +02:00
parent d1a3ffb1a5
commit 94151773a5
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
10 changed files with 180 additions and 150 deletions

View File

@ -21,12 +21,13 @@ func TestErrors(t *testing.T) {
{"InvalidInstructionIdentifier.q", &errors.InvalidInstruction{Instruction: "abc"}}, {"InvalidInstructionIdentifier.q", &errors.InvalidInstruction{Instruction: "abc"}},
{"InvalidInstructionNumber.q", &errors.InvalidInstruction{Instruction: "123"}}, {"InvalidInstructionNumber.q", &errors.InvalidInstruction{Instruction: "123"}},
{"InvalidExpression.q", errors.InvalidExpression}, {"InvalidExpression.q", errors.InvalidExpression},
{"InvalidOperator.q", &errors.InvalidOperator{Operator: "+++"}},
{"MissingAssignValue.q", errors.MissingAssignValue}, {"MissingAssignValue.q", errors.MissingAssignValue},
{"MissingBlockEnd.q", errors.MissingBlockEnd}, {"MissingBlockEnd.q", errors.MissingBlockEnd},
{"MissingBlockStart.q", errors.MissingBlockStart}, {"MissingBlockStart.q", errors.MissingBlockStart},
{"MissingGroupEnd.q", errors.MissingGroupEnd}, {"MissingGroupEnd.q", errors.MissingGroupEnd},
{"MissingGroupStart.q", errors.MissingGroupStart}, {"MissingGroupStart.q", errors.MissingGroupStart},
{"VariableAlreadyExists.q", &errors.VariableAlreadyExists{Name: "a"}}, {"VariableAlreadyExists.q", &errors.VariableAlreadyExists{Name: "x"}},
{"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}}, {"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}},
{"UnknownIdentifier2.q", &errors.UnknownIdentifier{Name: "x"}}, {"UnknownIdentifier2.q", &errors.UnknownIdentifier{Name: "x"}},
} }

View File

@ -14,15 +14,5 @@ func (f *Function) CompileAssignment(expr *expression.Expression) error {
return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, expr.Children[0].Token.Position) return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, expr.Children[0].Token.Position)
} }
if expr.Token.Text() == "=" {
return f.ExpressionToRegister(expr.Children[1], variable.Register)
}
right := expr.Children[1]
if right.IsLeaf() {
return f.Calculate(variable.Register, expr.Token, right.Token)
}
return f.Execute(expr.Token, variable.Register, expr.Children[1]) return f.Execute(expr.Token, variable.Register, expr.Children[1])
} }

View File

@ -1,81 +0,0 @@
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
}

111
src/build/Execute.go Normal file
View File

@ -0,0 +1,111 @@
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/expression"
"git.akyoto.dev/cli/q/src/build/token"
"git.akyoto.dev/cli/q/src/errors"
)
// Execute executes an operation on a register with a value operand.
func (f *Function) Execute(operation token.Token, register cpu.Register, value *expression.Expression) error {
if value.IsLeaf() {
return f.ExecuteLeaf(operation, register, value.Token)
}
temporary, found := f.CPU.FindFree(f.CPU.General)
if !found {
panic("no free registers")
}
f.CPU.Use(temporary)
defer f.CPU.Free(temporary)
err := f.ExpressionToRegister(value, temporary)
if err != nil {
return err
}
return f.ExecuteRegisterRegister(operation, register, temporary)
}
// ExecuteLeaf performs an operation on a register with the given leaf operand.
func (f *Function) ExecuteLeaf(operation token.Token, register cpu.Register, 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.ExecuteRegisterNumber(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.ExecuteRegisterRegister(operation, register, variable.Register)
}
return errors.New(errors.NotImplemented, f.File, operation.Position)
}
// ExecuteRegisterNumber performs an operation on a register and a number.
func (f *Function) ExecuteRegisterNumber(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)
case "=":
f.Assembler.RegisterNumber(asm.MOVE, register, number)
default:
return errors.New(&errors.InvalidOperator{Operator: operation.Text()}, f.File, operation.Position)
}
return nil
}
// ExecuteRegisterRegister performs an operation on two registers.
func (f *Function) ExecuteRegisterRegister(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)
case "=":
f.Assembler.RegisterRegister(asm.MOVE, destination, source)
default:
return errors.New(&errors.InvalidOperator{Operator: operation.Text()}, f.File, operation.Position)
}
return nil
}

View File

@ -140,29 +140,6 @@ func (f *Function) ExpressionToRegister(root *expression.Expression, register cp
return f.Execute(operation, register, right) return f.Execute(operation, register, right)
} }
// Execute executes an operation on a register with a value operand.
func (f *Function) Execute(operation token.Token, register cpu.Register, value *expression.Expression) error {
if value.IsLeaf() {
return f.Calculate(register, operation, value.Token)
}
temporary, found := f.CPU.FindFree(f.CPU.General)
if !found {
panic("no free registers")
}
f.CPU.Use(temporary)
defer f.CPU.Free(temporary)
err := f.ExpressionToRegister(value, temporary)
if err != nil {
return err
}
return f.CalculateRegisterRegister(operation, register, temporary)
}
// TokenToRegister moves a token into a register. // TokenToRegister moves a token into a register.
// It only works with identifiers, numbers and strings. // It only works with identifiers, numbers and strings.
func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error { func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error {

View File

@ -1,6 +1,10 @@
package expression package expression
import "git.akyoto.dev/cli/q/src/build/token" import (
"math"
"git.akyoto.dev/cli/q/src/build/token"
)
// Operator represents an operator for mathematical expressions. // Operator represents an operator for mathematical expressions.
type Operator struct { type Operator struct {
@ -12,35 +16,35 @@ type Operator struct {
// Operators defines the operators used in the language. // Operators defines the operators used in the language.
// The number corresponds to the operator priority and can not be zero. // The number corresponds to the operator priority and can not be zero.
var Operators = map[string]*Operator{ var Operators = map[string]*Operator{
".": {".", 14, 2}, ".": {".", 13, 2},
"λ": {"λ", 13, 1}, "λ": {"λ", 12, 1},
"!": {"!", 12, 1}, "!": {"!", 11, 1},
"*": {"*", 11, 2}, "*": {"*", 10, 2},
"/": {"/", 11, 2}, "/": {"/", 10, 2},
"%": {"%", 11, 2}, "%": {"%", 10, 2},
"+": {"+", 10, 2}, "+": {"+", 9, 2},
"-": {"-", 10, 2}, "-": {"-", 9, 2},
">>": {">>", 9, 2}, ">>": {">>", 8, 2},
"<<": {"<<", 9, 2}, "<<": {"<<", 8, 2},
">": {">", 8, 2}, ">": {">", 7, 2},
"<": {"<", 8, 2}, "<": {"<", 7, 2},
">=": {">=", 8, 2}, ">=": {">=", 7, 2},
"<=": {"<=", 8, 2}, "<=": {"<=", 7, 2},
"==": {"==", 7, 2}, "==": {"==", 6, 2},
"!=": {"!=", 7, 2}, "!=": {"!=", 6, 2},
"&": {"&", 6, 2}, "&": {"&", 5, 2},
"^": {"^", 5, 2}, "^": {"^", 4, 2},
"|": {"|", 4, 2}, "|": {"|", 3, 2},
"&&": {"&&", 3, 2}, "&&": {"&&", 2, 2},
"||": {"||", 2, 2}, "||": {"||", 1, 2},
"=": {"=", 1, 2}, "=": {"=", math.MinInt, 2},
":=": {":=", 1, 2}, ":=": {":=", math.MinInt, 2},
"+=": {"+=", 1, 2}, "+=": {"+=", math.MinInt, 2},
"-=": {"-=", 1, 2}, "-=": {"-=", math.MinInt, 2},
"*=": {"*=", 1, 2}, "*=": {"*=", math.MinInt, 2},
"/=": {"/=", 1, 2}, "/=": {"/=", math.MinInt, 2},
">>=": {">>=", 1, 2}, ">>=": {">>=", math.MinInt, 2},
"<<=": {"<<=", 1, 2}, "<<=": {"<<=", math.MinInt, 2},
} }
func isComplete(expr *Expression) bool { func isComplete(expr *Expression) bool {
@ -60,9 +64,21 @@ func isComplete(expr *Expression) bool {
} }
func numOperands(symbol string) int { func numOperands(symbol string) int {
return Operators[symbol].Operands operator, exists := Operators[symbol]
if !exists {
return -1
}
return operator.Operands
} }
func precedence(symbol string) int { func precedence(symbol string) int {
return Operators[symbol].Precedence operator, exists := Operators[symbol]
if !exists {
return -1
}
return operator.Precedence
} }

View File

@ -0,0 +1,13 @@
package errors
import "fmt"
// InvalidOperator error is created when an operator is not valid.
type InvalidOperator struct {
Operator string
}
// Error generates the string representation.
func (err *InvalidOperator) Error() string {
return fmt.Sprintf("Invalid operator '%s'", err.Operator)
}

View File

@ -0,0 +1,3 @@
main() {
x := 123 +++ 456
}

View File

@ -1,3 +1,3 @@
main() { main() {
a := x :=
} }

View File

@ -1,4 +1,4 @@
main() { main() {
a := 1 x := 1
a := 2 x := 2
} }