Simplified file structure

This commit is contained in:
2024-08-07 19:39:10 +02:00
parent 1b13539b22
commit 66569446b1
219 changed files with 453 additions and 457 deletions

109
src/core/CompileCall.go Normal file
View File

@ -0,0 +1,109 @@
package core
import (
"strings"
"git.akyoto.dev/cli/q/src/asm"
"git.akyoto.dev/cli/q/src/errors"
"git.akyoto.dev/cli/q/src/expression"
)
// CompileCall executes a function call.
// All call registers must hold the correct parameter values before the function invocation.
// Registers that are in use must be saved if they are modified by the function.
// After the function call, they must be restored in reverse order.
func (f *Function) CompileCall(root *expression.Expression) (*Function, error) {
var (
pkg = f.Package
nameNode = root.Children[0]
fn *Function
name string
fullName string
exists bool
)
if nameNode.IsLeaf() {
name = nameNode.Token.Text(f.File.Bytes)
if name == "syscall" {
return nil, f.CompileSyscall(root)
}
} else {
pkg = nameNode.Children[0].Token.Text(f.File.Bytes)
name = nameNode.Children[1].Token.Text(f.File.Bytes)
}
if pkg != f.File.Package {
if f.File.Imports == nil {
return nil, errors.New(&errors.UnknownPackage{Name: pkg}, f.File, nameNode.Token.Position)
}
imp, exists := f.File.Imports[pkg]
if !exists {
return nil, errors.New(&errors.UnknownPackage{Name: pkg}, f.File, nameNode.Token.Position)
}
imp.Used = true
}
tmp := strings.Builder{}
tmp.WriteString(pkg)
tmp.WriteString(".")
tmp.WriteString(name)
fullName = tmp.String()
fn, exists = f.Functions[fullName]
if !exists {
return nil, errors.New(&errors.UnknownFunction{Name: name}, f.File, nameNode.Token.Position)
}
parameters := root.Children[1:]
registers := f.CPU.Input[:len(parameters)]
for i := len(parameters) - 1; i >= 0; i-- {
typ, err := f.ExpressionToRegister(parameters[i], registers[i])
if err != nil {
return nil, err
}
if typ != fn.Parameters[i].Type {
return nil, errors.New(&errors.TypeMismatch{
Encountered: string(typ),
Expected: string(fn.Parameters[i].Type),
ParameterName: fn.Parameters[i].Name,
}, f.File, parameters[i].Token.Position)
}
}
for _, register := range f.CPU.Output[:len(fn.ReturnTypes)] {
f.SaveRegister(register)
}
for _, register := range f.CPU.General {
if f.RegisterIsUsed(register) {
f.Register(asm.PUSH, register)
}
}
f.Call(fullName)
for _, register := range registers {
if register == f.CPU.Output[0] && root.Parent != nil {
continue
}
f.FreeRegister(register)
}
for i := len(f.CPU.General) - 1; i >= 0; i-- {
register := f.CPU.General[i]
if f.RegisterIsUsed(register) {
f.Register(asm.POP, register)
}
}
return fn, nil
}