Added more tests

This commit is contained in:
2024-07-07 17:13:22 +02:00
parent 23b4e6442d
commit 9f341a6146
7 changed files with 157 additions and 13 deletions

View File

@ -2,6 +2,7 @@ package core
import (
"git.akyoto.dev/cli/q/src/build/asm"
"git.akyoto.dev/cli/q/src/build/errors"
"git.akyoto.dev/cli/q/src/build/expression"
)
@ -11,9 +12,18 @@ import (
// After the function call, they must be restored in reverse order.
func (f *Function) CompileCall(root *expression.Expression) error {
funcName := root.Children[0].Token.Text()
isSyscall := funcName == "syscall"
if !isSyscall {
_, exists := f.functions[funcName]
if !exists {
return errors.New(&errors.UnknownFunction{Name: funcName}, f.File, root.Children[0].Token.Position)
}
}
parameters := root.Children[1:]
registers := f.cpu.Input[:len(parameters)]
isSyscall := funcName == "syscall"
if isSyscall {
registers = f.cpu.Syscall[:len(parameters)]

View File

@ -9,25 +9,15 @@ import (
// CompileIf compiles a branch instruction.
func (f *Function) CompileIf(branch *ast.If) error {
condition := branch.Condition
tmp := f.cpu.MustFindFree(f.cpu.General)
err := f.ExpressionToRegister(condition.Children[0], tmp)
err := f.Evaluate(branch.Condition)
if err != nil {
return err
}
f.cpu.Use(tmp)
err = f.Execute(condition.Token, tmp, condition.Children[1])
if err != nil {
return err
}
f.cpu.Free(tmp)
endLabel := fmt.Sprintf("%s_end_if_%d", f.Name, f.count.branch)
switch condition.Token.Text() {
switch branch.Condition.Token.Text() {
case "==":
f.assembler.Label(asm.JNE, endLabel)
case "!=":

View File

@ -0,0 +1,41 @@
package core
import (
"git.akyoto.dev/cli/q/src/build/ast"
"git.akyoto.dev/cli/q/src/build/expression"
"git.akyoto.dev/cli/q/src/build/token"
)
// Evaluate evaluates an expression.
func (f *Function) Evaluate(value *expression.Expression) error {
left := value.Children[0]
right := value.Children[1]
if left.IsLeaf() && left.Token.Kind == token.Identifier {
variable := f.variables[left.Token.Text()]
register := variable.Register
defer f.useVariable(variable)
return f.Execute(value.Token, register, right)
}
if ast.IsFunctionCall(left) && right.IsLeaf() {
err := f.CompileCall(left)
if err != nil {
return err
}
return f.Execute(value.Token, f.cpu.Output[0], right)
}
tmp := f.cpu.MustFindFree(f.cpu.General)
err := f.ExpressionToRegister(left, tmp)
if err != nil {
return err
}
f.cpu.Use(tmp)
defer f.cpu.Free(tmp)
return f.Execute(value.Token, tmp, right)
}

View File

@ -0,0 +1,18 @@
package errors
import "fmt"
// UnknownFunction represents unknown function errors.
type UnknownFunction struct {
Name string
CorrectName string
}
// Error generates the string representation.
func (err *UnknownFunction) Error() string {
if err.CorrectName != "" {
return fmt.Sprintf("Unknown function '%s', did you mean '%s'?", err.Name, err.CorrectName)
}
return fmt.Sprintf("Unknown function '%s'", err.Name)
}