Implemented an abstract syntax tree

This commit is contained in:
Eduard Urbach 2024-06-30 22:54:59 +02:00
parent 3b29d4cdee
commit 8453273d73
Signed by: eduard
GPG key ID: 49226B848C78F6C8
28 changed files with 422 additions and 315 deletions

View file

@ -3,7 +3,6 @@ package build
import (
"strconv"
"git.akyoto.dev/cli/q/src/build/asm"
"git.akyoto.dev/cli/q/src/build/config"
"git.akyoto.dev/cli/q/src/build/cpu"
"git.akyoto.dev/cli/q/src/build/expression"
@ -72,110 +71,3 @@ func (f *Function) ExecuteLeaf(operation token.Token, register cpu.Register, ope
return errors.New(errors.NotImplemented, f.File, operation.Position)
}
// ExpressionToRegister moves the result of an expression into the given register.
func (f *Function) ExpressionToRegister(root *expression.Expression, register cpu.Register) error {
if config.Verbose {
f.Logf("%s to register %s", root, register)
}
operation := root.Token
if root.IsLeaf() {
return f.TokenToRegister(operation, register)
}
if isFunctionCall(root) {
err := f.CompileFunctionCall(root)
if err != nil {
return err
}
if register != f.cpu.Return[0] {
f.assembler.RegisterRegister(asm.MOVE, register, f.cpu.Return[0])
}
return nil
}
left := root.Children[0]
right := root.Children[1]
err := f.ExpressionToRegister(left, register)
if err != nil {
return err
}
f.SaveRegister(register)
return f.Execute(operation, register, right)
}
// ExpressionsToRegisters moves multiple expressions into the specified registers.
func (f *Function) ExpressionsToRegisters(expressions []*expression.Expression, registers []cpu.Register) error {
for _, register := range registers {
f.SaveRegister(register)
}
for i := len(expressions) - 1; i >= 0; i-- {
expression := expressions[i]
register := registers[i]
err := f.ExpressionToRegister(expression, register)
if err != nil {
return err
}
}
return nil
}
// TokenToRegister moves a token into a register.
// It only works with identifiers, numbers and strings.
func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error {
switch t.Kind {
case token.Identifier:
name := t.Text()
constant, exists := f.definitions[name]
if exists {
if config.Verbose {
f.Logf("constant %s = %s", constant.Name, constant.Value)
}
return f.ExpressionToRegister(constant.Value, register)
}
variable, exists := f.variables[name]
if !exists {
return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, t.Position)
}
if register != variable.Register {
f.assembler.RegisterRegister(asm.MOVE, register, variable.Register)
}
f.useVariable(variable)
return nil
case token.Number:
value := t.Text()
n, err := strconv.Atoi(value)
if err != nil {
return err
}
f.assembler.RegisterNumber(asm.MOVE, register, n)
return nil
case token.String:
return errors.New(errors.NotImplemented, f.File, t.Position)
default:
return errors.New(errors.InvalidExpression, f.File, t.Position)
}
}