#include #include "func.h" #include "node.h" #include "ply.h" #include "sym.h" #include "type.h" static int func_validate_expr(const struct func *func, struct node *n, int strict) { struct tfield *f; struct node *arg; int fargs, nargs = 0; for (f = func->type->func.args, arg = n->expr.args; f && f->type && arg; f++, arg = arg->next, nargs++) { if ((!strict && (f->type->ttype == T_VOID)) || (!strict && !arg->sym->type) || (!strict && (arg->sym->type->ttype == T_VOID)) || type_compatible(arg->sym->type, f->type)) continue; _e("%#N: %O argument is of type '%T', expected '%T'.\n", n, nargs, arg->sym->type, f->type); } if ((!f || !f->type) && !arg) return 0; nargs = node_nargs(n); fargs = type_nargs(func->type); if (f && f->type) { _e("%#N: too few arguments to %N; expected%s %d, got %d.\n", n, n, func->type->func.vargs? " at least" : "", fargs, nargs); return -EINVAL; } if (func->type->func.vargs) return 0; _e("%#N: too many arguments to %N; expected %d, got %d.\n", n, n, fargs, nargs); return -EINVAL; } int func_static_validate(const struct func *func, struct node *n) { int err = 0; if (!func->type) goto check_callback; switch (n->ntype) { case N_EXPR: if (func->type->ttype != T_FUNC) { _e("%#N: %N is not callable.\n", n, n); return -EINVAL; } err = func_validate_expr(func, n, 0); break; case N_IDENT: if (func->type->ttype == T_FUNC) { _e("%#N: %N is a function.\n", n, n); return -EINVAL; } break; default: /* num, str. nothing to validate. */ break; } check_callback: if (!err && func->static_validate) err = func->static_validate(func, n); return err; } struct type *func_return_type(const struct func *func) { if (!func->type) return NULL; if (func->type->ttype == T_FUNC) return func->type->func.type; return func->type; }