Something went wrong. Try again.
🌱 A minimal programming language and compiler. git.urbach.dev/cli/q
high-performance programming-language compiler
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116package core
import ( "strings"
"git.urbach.dev/cli/q/src/errors" "git.urbach.dev/cli/q/src/expression" "git.urbach.dev/cli/q/src/ssa" "git.urbach.dev/cli/q/src/types")
// evaluateCall converts a call expression to an SSA value.func (f *Function) evaluateCall(expr *expression.Expression) (ssa.Value, error) { identifier := expr.Children[0]
if identifier.Token.Kind.IsBuiltin() { return f.evaluateBuiltin(expr) }
funcValue, err := f.evaluate(identifier)
if err != nil { return nil, err }
ssaFunc, isFunction := funcValue.(*ssa.Function)
if !isFunction { _, isFunctionPointer := funcValue.Type().(*types.Function)
if isFunctionPointer { return f.evaluateCallPointer(funcValue, expr.Source()) }
return nil, errors.New(&TypeMismatch{Expected: "function", Encountered: funcValue.Type().Name()}, f.File, identifier.Source()) }
values, err := f.evaluateAll(expr.Children[1:])
if err != nil { return nil, err }
args, err := f.decompose(values)
if err != nil { return nil, err }
variants := ssaFunc.FunctionRef.(*Function) fn, err := f.selectFunction(variants, values, identifier)
if err != nil { return nil, err }
if fn == nil { typeNames := make([]string, len(values))
for i := range values { typeNames[i] = values[i].Type().Name() }
rawName, _, _ := strings.Cut(variants.FullName, "[") return nil, errors.New(&NoMatchingFunction{Function: rawName, Types: strings.Join(typeNames, ",")}, f.File, identifier.Source()) }
ssaFunc.FunctionRef = fn ssaFunc.Typ = fn.Type
for i, value := range values { given := value.Type() expected := fn.Input[i].Typ _, givenIsResource := given.(*types.Resource) _, expectedIsResource := expected.(*types.Resource)
if givenIsResource && expectedIsResource { f.Block().Unidentify(value) }
if types.Is(given, expected) { continue }
typeMismatch := &TypeMismatch{ Encountered: given.Name(), Expected: expected.Name(), ParameterName: fn.Input[i].Name, }
return nil, errors.New(typeMismatch, f.File, expr.Children[1+i].Source()) }
if fn.IsExtern() { v := f.Append(&ssa.CallExtern{Call: ssa.Call{ Func: ssaFunc, Arguments: args, Source: expr.Source(), }})
f.Assembler.Libraries.Append(fn.Package(), fn.Name()) return v, nil }
if f == f.Env.Init && fn == f.Env.Main { f.runAll("init") }
v := f.call(ssaFunc, args, expr.Source())
if f == f.Env.Init && fn == f.Env.Main { f.runAll("exit") }
return v, nil}