diff --git a/src/core/BeforeCall.go b/src/core/BeforeCall.go deleted file mode 100644 index 57812f8..0000000 --- a/src/core/BeforeCall.go +++ /dev/null @@ -1,32 +0,0 @@ -package core - -import ( - "git.akyoto.dev/cli/q/src/cpu" - "git.akyoto.dev/cli/q/src/errors" - "git.akyoto.dev/cli/q/src/expression" - "git.akyoto.dev/cli/q/src/token" - "git.akyoto.dev/cli/q/src/types" -) - -// BeforeCall loads the registers with the parameter values and checks that the types match with the function signature. -func (f *Function) BeforeCall(fn *Function, parameters []*expression.Expression, registers []cpu.Register) error { - for i := len(parameters) - 1; i >= 0; i-- { - typ, err := f.ExpressionToRegister(parameters[i], registers[i]) - - if err != nil { - return err - } - - if !types.Is(typ, fn.Input[i].Type) { - _, expectsPointer := fn.Input[i].Type.(*types.Pointer) - - if expectsPointer && parameters[i].Token.Kind == token.Number && parameters[i].Token.Text(f.File.Bytes) == "0" { - continue - } - - return errors.New(&errors.TypeMismatch{Encountered: typ.Name(), Expected: fn.Input[i].Type.Name(), ParameterName: fn.Input[i].Name}, f.File, parameters[i].Token.Position) - } - } - - return nil -} diff --git a/src/core/CallExtern.go b/src/core/CallExtern.go index abb1a7a..1b8fe8f 100644 --- a/src/core/CallExtern.go +++ b/src/core/CallExtern.go @@ -26,7 +26,7 @@ func (f *Function) CallExtern(fn *Function, parameters []*expression.Expression) } registers := x86.WindowsInputRegisters[:len(parameters)] - err := f.BeforeCall(fn, parameters, registers) + err := f.ExpressionsToRegisters(parameters, registers, fn.Input) if err != nil { return nil, err diff --git a/src/core/CompileCall.go b/src/core/CompileCall.go index 2518ab5..86f284b 100644 --- a/src/core/CompileCall.go +++ b/src/core/CompileCall.go @@ -75,7 +75,7 @@ func (f *Function) CompileCall(root *expression.Expression) ([]types.Type, error } registers := f.CPU.Input[:len(parameters)] - err := f.BeforeCall(fn, parameters, registers) + err := f.ExpressionsToRegisters(parameters, registers, fn.Input) if err != nil { return nil, err diff --git a/src/core/CompileReturn.go b/src/core/CompileReturn.go index 87050e8..752669f 100644 --- a/src/core/CompileReturn.go +++ b/src/core/CompileReturn.go @@ -18,6 +18,7 @@ func (f *Function) CompileReturn(node *ast.Return) error { } for i := len(node.Values) - 1; i >= 0; i-- { + f.SaveRegister(f.CPU.Output[i]) typ, err := f.ExpressionToRegister(node.Values[i], f.CPU.Output[i]) if err != nil { diff --git a/src/core/CompileSyscall.go b/src/core/CompileSyscall.go index cadce36..0b3b1d6 100644 --- a/src/core/CompileSyscall.go +++ b/src/core/CompileSyscall.go @@ -8,7 +8,7 @@ import ( func (f *Function) CompileSyscall(root *expression.Expression) error { parameters := root.Children[1:] registers := f.CPU.SyscallInput[:len(parameters)] - err := f.ExpressionsToRegisters(parameters, registers) + err := f.ExpressionsToRegisters(parameters, registers, nil) if err != nil { return err diff --git a/src/core/ExpressionToRegister.go b/src/core/ExpressionToRegister.go index 4dfb2d7..d690f7f 100644 --- a/src/core/ExpressionToRegister.go +++ b/src/core/ExpressionToRegister.go @@ -12,8 +12,6 @@ import ( // ExpressionToRegister puts the result of an expression into the specified register. func (f *Function) ExpressionToRegister(node *expression.Expression, register cpu.Register) (types.Type, error) { - f.SaveRegister(register) - if node.IsFolded { f.RegisterNumber(asm.MOVE, register, node.Value) return types.Int, nil diff --git a/src/core/ExpressionsToRegisters.go b/src/core/ExpressionsToRegisters.go index 4f2dbed..8d1436a 100644 --- a/src/core/ExpressionsToRegisters.go +++ b/src/core/ExpressionsToRegisters.go @@ -2,17 +2,35 @@ package core import ( "git.akyoto.dev/cli/q/src/cpu" + "git.akyoto.dev/cli/q/src/errors" "git.akyoto.dev/cli/q/src/expression" + "git.akyoto.dev/cli/q/src/token" + "git.akyoto.dev/cli/q/src/types" ) -// ExpressionsToRegisters moves multiple expressions into the specified registers. -func (f *Function) ExpressionsToRegisters(expressions []*expression.Expression, registers []cpu.Register) error { +// ExpressionsToRegisters moves multiple expressions into the specified registers and checks that the types match with the function signature. +func (f *Function) ExpressionsToRegisters(expressions []*expression.Expression, registers []cpu.Register, input []*Input) error { for i := len(expressions) - 1; i >= 0; i-- { - _, err := f.ExpressionToRegister(expressions[i], registers[i]) + f.SaveRegister(registers[i]) + typ, err := f.ExpressionToRegister(expressions[i], registers[i]) if err != nil { return err } + + if input == nil { + continue + } + + if !types.Is(typ, input[i].Type) { + _, expectsPointer := input[i].Type.(*types.Pointer) + + if expectsPointer && expressions[i].Token.Kind == token.Number && expressions[i].Token.Text(f.File.Bytes) == "0" { + continue + } + + return errors.New(&errors.TypeMismatch{Encountered: typ.Name(), Expected: input[i].Type.Name(), ParameterName: input[i].Name}, f.File, expressions[i].Token.Position) + } } return nil