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)]
|
registers := x86.WindowsInputRegisters[:len(parameters)]
|
||||||
err := f.ExpressionsToRegisters(parameters, registers, fn.Input)
|
err := f.ExpressionsToRegisters(parameters, registers, fn.Input, true)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -75,7 +75,7 @@ func (f *Function) CompileCall(root *expression.Expression) ([]types.Type, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
registers := f.CPU.Input[:len(parameters)]
|
registers := f.CPU.Input[:len(parameters)]
|
||||||
err := f.ExpressionsToRegisters(parameters, registers, fn.Input)
|
err := f.ExpressionsToRegisters(parameters, registers, fn.Input, true)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -3,7 +3,6 @@ package core
|
|||||||
import (
|
import (
|
||||||
"git.akyoto.dev/cli/q/src/ast"
|
"git.akyoto.dev/cli/q/src/ast"
|
||||||
"git.akyoto.dev/cli/q/src/errors"
|
"git.akyoto.dev/cli/q/src/errors"
|
||||||
"git.akyoto.dev/cli/q/src/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CompileReturn compiles a return instruction.
|
// 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)
|
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-- {
|
err := f.ExpressionsToRegisters(node.Values, f.CPU.Output, f.Output, false)
|
||||||
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])
|
if err != nil {
|
||||||
|
return err
|
||||||
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()
|
f.Return()
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
func (f *Function) CompileSyscall(root *expression.Expression) error {
|
func (f *Function) CompileSyscall(root *expression.Expression) error {
|
||||||
parameters := root.Children[1:]
|
parameters := root.Children[1:]
|
||||||
registers := f.CPU.SyscallInput[:len(parameters)]
|
registers := f.CPU.SyscallInput[:len(parameters)]
|
||||||
err := f.ExpressionsToRegisters(parameters, registers, nil)
|
err := f.ExpressionsToRegisters(parameters, registers, nil, true)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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.
|
// 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-- {
|
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])
|
typ, err := f.ExpressionToRegister(expressions[i], registers[i])
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if input == nil {
|
if params == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !types.Is(typ, input[i].Type) {
|
if !types.Is(typ, params[i].Type()) {
|
||||||
_, expectsPointer := input[i].Type.(*types.Pointer)
|
_, expectsPointer := params[i].Type().(*types.Pointer)
|
||||||
|
|
||||||
if expectsPointer && expressions[i].Token.Kind == token.Number && expressions[i].Token.Text(f.File.Bytes) == "0" {
|
if expectsPointer && expressions[i].Token.Kind == token.Number && expressions[i].Token.Text(f.File.Bytes) == "0" {
|
||||||
continue
|
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
|
UniqueName string
|
||||||
File *fs.File
|
File *fs.File
|
||||||
Body token.List
|
Body token.List
|
||||||
Input []*Input
|
Input []*Parameter
|
||||||
Output []*Output
|
Output []*Parameter
|
||||||
OutputTypes []types.Type
|
OutputTypes []types.Type
|
||||||
Functions map[string]*Function
|
Functions map[string]*Function
|
||||||
Structs map[string]*types.Struct
|
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 {
|
if len(f.Input) > 0 {
|
||||||
for i, input := range f.Input {
|
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")
|
ansi.Dim.Print(" │\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,11 +11,11 @@ import (
|
|||||||
// ResolveTypes parses the input and output types.
|
// ResolveTypes parses the input and output types.
|
||||||
func (f *Function) ResolveTypes() error {
|
func (f *Function) ResolveTypes() error {
|
||||||
for i, param := range f.Input {
|
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)
|
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)
|
return errors.New(&errors.UnknownType{Name: typeName}, f.File, param.tokens[1].Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,15 +23,15 @@ func (f *Function) ResolveTypes() error {
|
|||||||
continue
|
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 != "_" {
|
if uses == 0 && param.name != "_" {
|
||||||
return errors.New(&errors.UnusedVariable{Name: param.Name}, f.File, param.tokens[0].Position)
|
return errors.New(&errors.UnusedVariable{Name: param.name}, f.File, param.tokens[0].Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
f.AddVariable(&scope.Variable{
|
f.AddVariable(&scope.Variable{
|
||||||
Name: param.Name,
|
Name: param.name,
|
||||||
Type: param.Type,
|
Type: param.typ,
|
||||||
Register: x86.InputRegisters[i],
|
Register: x86.InputRegisters[i],
|
||||||
Alive: uses,
|
Alive: uses,
|
||||||
})
|
})
|
||||||
@ -39,13 +39,13 @@ func (f *Function) ResolveTypes() error {
|
|||||||
|
|
||||||
for _, param := range f.Output {
|
for _, param := range f.Output {
|
||||||
typeName := param.tokens.Text(f.File.Bytes)
|
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)
|
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
|
return nil
|
||||||
|
@ -97,7 +97,7 @@ func scanFunctionSignature(file *fs.File, tokens token.List, i int, delimiter to
|
|||||||
outputTokens := tokens[typeStart:typeEnd]
|
outputTokens := tokens[typeStart:typeEnd]
|
||||||
|
|
||||||
err := outputTokens.Split(func(tokens token.List) error {
|
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
|
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())
|
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
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user