Simplified return code
This commit is contained in:
parent
3fb05c382a
commit
b7b4dad1a5
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,29 +16,12 @@ 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
|
||||
}
|
||||
}
|
||||
|
||||
typ, err := f.ExpressionToRegister(node.Values[i], f.CPU.Output[i])
|
||||
err := f.ExpressionsToRegisters(node.Values, f.CPU.Output, f.Output, false)
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
f.Return()
|
||||
return nil
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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-- {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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}
|
||||
}
|
@ -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}
|
||||
}
|
24
src/core/Parameter.go
Normal file
24
src/core/Parameter.go
Normal file
@ -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
|
||||
}
|
@ -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")
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
})
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user