From b7b4dad1a51bcf3481c78497f33880f4d3bdd178 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Wed, 12 Feb 2025 17:34:48 +0100 Subject: [PATCH] Simplified return code --- src/core/CallExtern.go | 2 +- src/core/CompileCall.go | 2 +- src/core/CompileReturn.go | 24 +++--------------------- src/core/CompileSyscall.go | 2 +- src/core/ExpressionsToRegisters.go | 26 ++++++++++++++++++++------ src/core/Function.go | 4 ++-- src/core/Input.go | 16 ---------------- src/core/Output.go | 15 --------------- src/core/Parameter.go | 24 ++++++++++++++++++++++++ src/core/PrintInstructions.go | 2 +- src/core/ResolveTypes.go | 22 +++++++++++----------- src/scanner/scanFunctionSignature.go | 4 ++-- 12 files changed, 66 insertions(+), 77 deletions(-) delete mode 100644 src/core/Input.go delete mode 100644 src/core/Output.go create mode 100644 src/core/Parameter.go diff --git a/src/core/CallExtern.go b/src/core/CallExtern.go index 1b8fe8f..57d3118 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.ExpressionsToRegisters(parameters, registers, fn.Input) + err := f.ExpressionsToRegisters(parameters, registers, fn.Input, true) if err != nil { return nil, err diff --git a/src/core/CompileCall.go b/src/core/CompileCall.go index 86f284b..4973ce2 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.ExpressionsToRegisters(parameters, registers, fn.Input) + err := f.ExpressionsToRegisters(parameters, registers, fn.Input, true) if err != nil { return nil, err diff --git a/src/core/CompileReturn.go b/src/core/CompileReturn.go index fb93354..cb2ffe6 100644 --- a/src/core/CompileReturn.go +++ b/src/core/CompileReturn.go @@ -3,7 +3,6 @@ package core import ( "git.akyoto.dev/cli/q/src/ast" "git.akyoto.dev/cli/q/src/errors" - "git.akyoto.dev/cli/q/src/types" ) // CompileReturn compiles a return instruction. @@ -17,27 +16,10 @@ func (f *Function) CompileReturn(node *ast.Return) error { return errors.New(&errors.ReturnCountMismatch{Count: len(node.Values), ExpectedCount: len(f.Output)}, f.File, node.Values[0].Token.Position) } - for i := len(node.Values) - 1; i >= 0; i-- { - for j := range i { - if f.UsesRegister(node.Values[j], f.CPU.Output[i]) { - f.SaveRegister(f.CPU.Output[i]) - break - } - } + err := f.ExpressionsToRegisters(node.Values, f.CPU.Output, f.Output, false) - typ, err := f.ExpressionToRegister(node.Values[i], f.CPU.Output[i]) - - if err != nil { - return err - } - - if !types.Is(typ, f.Output[i].Type) { - if f.Package == "mem" && f.Name == "alloc" { - continue - } - - return errors.New(&errors.TypeMismatch{Encountered: typ.Name(), Expected: f.Output[i].Type.Name(), ParameterName: "", IsReturn: true}, f.File, node.Values[i].Token.Position) - } + if err != nil { + return err } f.Return() diff --git a/src/core/CompileSyscall.go b/src/core/CompileSyscall.go index 0b3b1d6..a4edf16 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, nil) + err := f.ExpressionsToRegisters(parameters, registers, nil, true) if err != nil { return err diff --git a/src/core/ExpressionsToRegisters.go b/src/core/ExpressionsToRegisters.go index 8d1436a..f6a21f3 100644 --- a/src/core/ExpressionsToRegisters.go +++ b/src/core/ExpressionsToRegisters.go @@ -9,27 +9,41 @@ import ( ) // 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 { +func (f *Function) ExpressionsToRegisters(expressions []*expression.Expression, registers []cpu.Register, params []*Parameter, alwaysSave bool) error { for i := len(expressions) - 1; i >= 0; i-- { - f.SaveRegister(registers[i]) + if alwaysSave { + f.SaveRegister(registers[i]) + } else { + for j := i - 1; j >= 0; j-- { + if f.UsesRegister(expressions[j], registers[i]) { + f.SaveRegister(registers[i]) + break + } + } + } + typ, err := f.ExpressionToRegister(expressions[i], registers[i]) if err != nil { return err } - if input == nil { + if params == nil { continue } - if !types.Is(typ, input[i].Type) { - _, expectsPointer := input[i].Type.(*types.Pointer) + if !types.Is(typ, params[i].Type()) { + _, expectsPointer := params[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) + if f.Package == "mem" && f.Name == "alloc" { + continue + } + + return errors.New(&errors.TypeMismatch{Encountered: typ.Name(), Expected: params[i].Type().Name(), ParameterName: params[i].Name()}, f.File, expressions[i].Token.Position) } } diff --git a/src/core/Function.go b/src/core/Function.go index d0a6098..5565dea 100644 --- a/src/core/Function.go +++ b/src/core/Function.go @@ -16,8 +16,8 @@ type Function struct { UniqueName string File *fs.File Body token.List - Input []*Input - Output []*Output + Input []*Parameter + Output []*Parameter OutputTypes []types.Type Functions map[string]*Function Structs map[string]*types.Struct diff --git a/src/core/Input.go b/src/core/Input.go deleted file mode 100644 index 2b9aee2..0000000 --- a/src/core/Input.go +++ /dev/null @@ -1,16 +0,0 @@ -package core - -import ( - "git.akyoto.dev/cli/q/src/token" - "git.akyoto.dev/cli/q/src/types" -) - -type Input struct { - Name string - Type types.Type - tokens token.List -} - -func NewInput(tokens token.List) *Input { - return &Input{tokens: tokens} -} diff --git a/src/core/Output.go b/src/core/Output.go deleted file mode 100644 index 3b1b434..0000000 --- a/src/core/Output.go +++ /dev/null @@ -1,15 +0,0 @@ -package core - -import ( - "git.akyoto.dev/cli/q/src/token" - "git.akyoto.dev/cli/q/src/types" -) - -type Output struct { - Type types.Type - tokens token.List -} - -func NewOutput(tokens token.List) *Output { - return &Output{tokens: tokens} -} diff --git a/src/core/Parameter.go b/src/core/Parameter.go new file mode 100644 index 0000000..1375a09 --- /dev/null +++ b/src/core/Parameter.go @@ -0,0 +1,24 @@ +package core + +import ( + "git.akyoto.dev/cli/q/src/token" + "git.akyoto.dev/cli/q/src/types" +) + +type Parameter struct { + name string + typ types.Type + tokens token.List +} + +func NewParameter(tokens token.List) *Parameter { + return &Parameter{tokens: tokens} +} + +func (p *Parameter) Name() string { + return p.name +} + +func (p *Parameter) Type() types.Type { + return p.typ +} diff --git a/src/core/PrintInstructions.go b/src/core/PrintInstructions.go index 3a1acf5..00fcf7c 100644 --- a/src/core/PrintInstructions.go +++ b/src/core/PrintInstructions.go @@ -14,7 +14,7 @@ func (f *Function) PrintInstructions() { if len(f.Input) > 0 { for i, input := range f.Input { - ansi.Dim.Printf("│ %-44s%-32s", input.Name, f.CPU.Input[i]) + ansi.Dim.Printf("│ %-44s%-32s", input.name, f.CPU.Input[i]) ansi.Dim.Print(" │\n") } diff --git a/src/core/ResolveTypes.go b/src/core/ResolveTypes.go index 79ce233..b885d15 100644 --- a/src/core/ResolveTypes.go +++ b/src/core/ResolveTypes.go @@ -11,11 +11,11 @@ import ( // ResolveTypes parses the input and output types. func (f *Function) ResolveTypes() error { for i, param := range f.Input { - param.Name = param.tokens[0].Text(f.File.Bytes) + param.name = param.tokens[0].Text(f.File.Bytes) typeName := param.tokens[1:].Text(f.File.Bytes) - param.Type = types.ByName(typeName, f.Package, f.Structs) + param.typ = types.ByName(typeName, f.Package, f.Structs) - if param.Type == nil { + if param.typ == nil { return errors.New(&errors.UnknownType{Name: typeName}, f.File, param.tokens[1].Position) } @@ -23,15 +23,15 @@ func (f *Function) ResolveTypes() error { continue } - uses := token.Count(f.Body, f.File.Bytes, token.Identifier, param.Name) + uses := token.Count(f.Body, f.File.Bytes, token.Identifier, param.name) - if uses == 0 && param.Name != "_" { - return errors.New(&errors.UnusedVariable{Name: param.Name}, f.File, param.tokens[0].Position) + if uses == 0 && param.name != "_" { + return errors.New(&errors.UnusedVariable{Name: param.name}, f.File, param.tokens[0].Position) } f.AddVariable(&scope.Variable{ - Name: param.Name, - Type: param.Type, + Name: param.name, + Type: param.typ, Register: x86.InputRegisters[i], Alive: uses, }) @@ -39,13 +39,13 @@ func (f *Function) ResolveTypes() error { for _, param := range f.Output { typeName := param.tokens.Text(f.File.Bytes) - param.Type = types.ByName(typeName, f.Package, f.Structs) + param.typ = types.ByName(typeName, f.Package, f.Structs) - if param.Type == nil { + if param.typ == nil { return errors.New(&errors.UnknownType{Name: typeName}, f.File, param.tokens[0].Position) } - f.OutputTypes = append(f.OutputTypes, param.Type) + f.OutputTypes = append(f.OutputTypes, param.typ) } return nil diff --git a/src/scanner/scanFunctionSignature.go b/src/scanner/scanFunctionSignature.go index f060214..501e252 100644 --- a/src/scanner/scanFunctionSignature.go +++ b/src/scanner/scanFunctionSignature.go @@ -97,7 +97,7 @@ func scanFunctionSignature(file *fs.File, tokens token.List, i int, delimiter to outputTokens := tokens[typeStart:typeEnd] err := outputTokens.Split(func(tokens token.List) error { - function.Output = append(function.Output, core.NewOutput(tokens)) + function.Output = append(function.Output, core.NewParameter(tokens)) return nil }) @@ -117,7 +117,7 @@ func scanFunctionSignature(file *fs.File, tokens token.List, i int, delimiter to return errors.New(errors.MissingType, file, tokens[0].End()) } - function.Input = append(function.Input, core.NewInput(tokens)) + function.Input = append(function.Input, core.NewParameter(tokens)) return nil })