/* * Semantic checking of function calls. * * Copyright © 2025 Samuel Lidén Borell * * SPDX-License-Identifier: EUPL-1.2+ OR LGPL-2.1-or-later */ #include #include "compiler.h" static void check_args(struct ExprCall *call, struct Func *func) { struct CallArg *arg; struct Var *param; arg = call->args; param = func->params; for (;;) { if (!arg && !param) { break; } else if (!arg) { error("Too few arguments to function"); } else if (!param) { error("Too many arguments to function"); } check_type_compat( param->typeref, arg->expr->typeref, TC_ASSIGN); arg = arg->next; param = param->next; } } struct TypeRef funccall_check(struct Expr *e) { struct TypeRef tr; size_t namelen; const char *name; struct Type *type; struct Func *func; HashCode h; assert(e->kind == E_CALL); namelen = e->u.call->ident.namelen; assert(namelen != 0); name = e->u.call->ident.u.name; assert(name != NULL); /* TODO typeidents ( .xx or :xx ?) */ /* TODO methods ( obj.xx ?) */ func = NULL; h = hash_str(name, namelen); for (type = current_type; type != NULL; type = type->outer) { func = (struct Func *)tree_search(type->funcs, h, namelen, name); } if (!func) { func = (struct Func *)tree_search(module->funcs, h, namelen, name); } if (!func) { error(e->u.call->args != NULL ? "No such function" : "No such function or variable"); } check_args(e->u.call, func); if (func->num_returns == 0) { tr.kind = TR_VOID; } else if (func->num_returns == 1) { tr = *func->returns->typeref; } else { /* TODO multiple return values */ assert(0); } return tr; }