Added more tests

This commit is contained in:
Eduard Urbach 2024-06-22 13:20:11 +02:00
parent 4faa1641c6
commit 2f7319e6a0
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
6 changed files with 84 additions and 22 deletions

View File

@ -20,12 +20,14 @@ func TestErrors(t *testing.T) {
{"ExpectedFunctionParameters.q", errors.ExpectedFunctionParameters},
{"InvalidInstructionIdentifier.q", &errors.InvalidInstruction{Instruction: "abc"}},
{"InvalidInstructionNumber.q", &errors.InvalidInstruction{Instruction: "123"}},
{"InvalidExpression.q", errors.InvalidExpression},
{"MissingAssignValue.q", errors.MissingAssignValue},
{"MissingBlockEnd.q", errors.MissingBlockEnd},
{"MissingBlockStart.q", errors.MissingBlockStart},
{"MissingGroupEnd.q", errors.MissingGroupEnd},
{"MissingGroupStart.q", errors.MissingGroupStart},
{"VariableAlreadyExists.q", &errors.VariableAlreadyExists{Name: "a"}},
{"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}},
}
for _, test := range tests {

View File

@ -156,29 +156,10 @@ func (f *Function) CompileFunctionCall(expr *expression.Expression) error {
parameters := expr.Children[1:]
for i, parameter := range parameters {
switch parameter.Token.Kind {
case token.Identifier:
name := parameter.Token.Text()
variable, exists := f.Variables[name]
err := f.ExpressionToRegister(parameter, f.CPU.Syscall[i])
if !exists {
panic("Unknown identifier " + name)
}
if !variable.IsConst {
panic("Not implemented yet")
}
n, _ := strconv.Atoi(variable.Value.Token.Text())
f.Assembler.MoveRegisterNumber(f.CPU.Syscall[i], uint64(n))
case token.Number:
value := parameter.Token.Text()
n, _ := strconv.Atoi(value)
f.Assembler.MoveRegisterNumber(f.CPU.Syscall[i], uint64(n))
default:
panic("Unknown expression")
if err != nil {
return err
}
}
@ -191,6 +172,59 @@ func (f *Function) CompileFunctionCall(expr *expression.Expression) error {
return nil
}
// ExpressionToRegister moves the result of an expression into the given register.
func (f *Function) ExpressionToRegister(root *expression.Expression, register cpu.Register) error {
if root.IsLeaf() {
return f.TokenToRegister(root.Token, register)
}
return errors.New(errors.NotImplemented, f.File, root.Token.Position)
}
// 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()
variable, exists := f.Variables[name]
if !exists {
return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, t.Position)
}
if !variable.IsConst {
return errors.New(errors.NotImplemented, f.File, t.Position)
}
n, err := strconv.Atoi(variable.Value.Token.Text())
if err != nil {
return err
}
f.Assembler.MoveRegisterNumber(register, uint64(n))
return nil
case token.Number:
value := t.Text()
n, err := strconv.Atoi(value)
if err != nil {
return err
}
f.Assembler.MoveRegisterNumber(register, uint64(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)
}
}
// PrintAsm shows the assembly instructions.
func (f *Function) PrintAsm() {
ansi.Bold.Println(f.Name)

View File

@ -2,5 +2,7 @@ package errors
var (
InvalidStatement = &Base{"Invalid statement"}
InvalidExpression = &Base{"Invalid expression"}
MissingAssignValue = &Base{"Missing assignment value"}
NotImplemented = &Base{"Not implemented"}
)

View File

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

View File

@ -0,0 +1,3 @@
main() {
syscall(+, -, *, /)
}

View File

@ -0,0 +1,3 @@
main() {
syscall(x)
}