Implemented extern functions
This commit is contained in:
@ -5,7 +5,6 @@ import (
|
||||
|
||||
"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"
|
||||
"git.akyoto.dev/cli/q/src/x86"
|
||||
)
|
||||
@ -48,22 +47,13 @@ func (f *Function) CompileCall(root *expression.Expression) ([]types.Type, error
|
||||
name = nameNode.Token.Text(f.File.Bytes)
|
||||
}
|
||||
|
||||
if pkg == "kernel32" || pkg == "user32" || pkg == "gdi32" || pkg == "comctl32" {
|
||||
parameters := root.Children[1:]
|
||||
registers := x86.WindowsInputRegisters[:len(parameters)]
|
||||
fn, exists = f.Functions[pkg+"."+name]
|
||||
|
||||
for i := len(parameters) - 1; i >= 0; i-- {
|
||||
_, err := f.ExpressionToRegister(parameters[i], registers[i])
|
||||
if !exists {
|
||||
return nil, errors.New(&errors.UnknownFunction{Name: name}, f.File, nameNode.Token.Position)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
f.DLLs = f.DLLs.Append(pkg, name)
|
||||
f.DLLCall(fmt.Sprintf("%s.%s", pkg, name))
|
||||
return nil, nil
|
||||
} else if pkg != f.File.Package {
|
||||
if pkg != f.File.Package && !fn.IsExtern() {
|
||||
if f.File.Imports == nil {
|
||||
return nil, errors.New(&errors.UnknownPackage{Name: pkg}, f.File, pkgNode.Token.Position)
|
||||
}
|
||||
@ -77,36 +67,30 @@ func (f *Function) CompileCall(root *expression.Expression) ([]types.Type, error
|
||||
imp.Used = true
|
||||
}
|
||||
|
||||
fn, exists = f.Functions[pkg+"."+name]
|
||||
|
||||
if !exists {
|
||||
return nil, errors.New(&errors.UnknownFunction{Name: name}, f.File, nameNode.Token.Position)
|
||||
}
|
||||
|
||||
parameters := root.Children[1:]
|
||||
|
||||
if len(parameters) != len(fn.Input) {
|
||||
return nil, errors.New(&errors.ParameterCountMismatch{Function: fn.Name, Count: len(parameters), ExpectedCount: len(fn.Input)}, f.File, nameNode.Token.End())
|
||||
}
|
||||
|
||||
registers := f.CPU.Input[:len(parameters)]
|
||||
|
||||
for i := len(parameters) - 1; i >= 0; i-- {
|
||||
typ, err := f.ExpressionToRegister(parameters[i], registers[i])
|
||||
if fn.IsExtern() {
|
||||
f.DLLs = f.DLLs.Append(pkg, name)
|
||||
registers := x86.WindowsInputRegisters[:len(parameters)]
|
||||
err := f.BeforeCall(fn, parameters, registers)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !types.Is(typ, fn.Input[i].Type) {
|
||||
_, expectsPointer := fn.Input[i].Type.(*types.Pointer)
|
||||
f.DLLCall(fmt.Sprintf("%s.%s", pkg, name))
|
||||
return fn.OutputTypes, nil
|
||||
}
|
||||
|
||||
if expectsPointer && parameters[i].Token.Kind == token.Number && parameters[i].Token.Text(f.File.Bytes) == "0" {
|
||||
continue
|
||||
}
|
||||
registers := f.CPU.Input[:len(parameters)]
|
||||
err := f.BeforeCall(fn, parameters, registers)
|
||||
|
||||
return nil, errors.New(&errors.TypeMismatch{Encountered: typ.Name(), Expected: fn.Input[i].Type.Name(), ParameterName: fn.Input[i].Name}, f.File, parameters[i].Token.Position)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f.CallSafe(fn, registers)
|
||||
|
Reference in New Issue
Block a user