[qfcc] Put definition for generic functions in genfunc

It is then copied to the metafunc when finding the actual function to
call. Fixes the last definition defining all instances.
This commit is contained in:
Bill Currie 2024-12-05 16:08:39 +09:00
parent a5366bf7f9
commit ec436ee65e
2 changed files with 25 additions and 10 deletions

View file

@ -76,7 +76,7 @@ typedef struct genfunc_s {
int num_params;
genparam_t *params;
genparam_t *ret_type;
// only automatic (#0) builtins supported for now
const expr_t *expr; ///< inline or intrinsic
} genfunc_t;
typedef enum {
@ -191,7 +191,7 @@ typedef struct expr_s expr_t;
typedef struct symbol_s symbol_t;
typedef struct symtab_s symtab_t;
void add_generic_function (genfunc_t *genfunc);
genfunc_t *add_generic_function (genfunc_t *genfunc);
param_t *new_param (const char *selector, const type_t *type, const char *name);
param_t *new_generic_param (const expr_t *type_expr, const char *name);

View file

@ -136,7 +136,7 @@ cmp_genparams (genfunc_t *g1, genparam_t *p1, genfunc_t *g2, genparam_t *p2)
return *vt1 == *vt2;
}
void
genfunc_t *
add_generic_function (genfunc_t *genfunc)
{
auto name = genfunc->name;
@ -169,9 +169,10 @@ add_generic_function (genfunc_t *genfunc)
check_generic_param (genfunc->ret_type, genfunc);
bool is_new = true;
genfunc_t *old = nullptr;
auto old_list = (genfunc_t **) Hash_FindList (generic_functions, name);
for (auto o = old_list; is_new && o && *o; o++) {
auto old = *o;
old = *o;
if (old->num_params == genfunc->num_params) {
is_new = false;
for (int i = 0; i < genfunc->num_params; i++) {
@ -184,7 +185,7 @@ add_generic_function (genfunc_t *genfunc)
if (!is_new && !cmp_genparams (genfunc, genfunc->ret_type,
old, old->ret_type)) {
error (0, "can't overload on return types");
return;
return nullptr;
}
}
}
@ -198,7 +199,9 @@ add_generic_function (genfunc_t *genfunc)
}
free (genfunc->types);
FREE (genfuncs, genfunc);
genfunc = old;
}
return genfunc;
}
static const type_t **
@ -742,6 +745,7 @@ create_generic_sym (genfunc_t *g, const expr_t *fexpr, calltype_t *calltype)
sym->params = params;
sym->metafunc = new_metafunc ();
*sym->metafunc = *fsym->metafunc;
sym->metafunc->expr = g->expr;
symtab_addsymbol (fsym->table, sym);
}
return sym;
@ -1252,15 +1256,26 @@ void
build_intrinsic_function (specifier_t spec, const expr_t *intrinsic)
{
auto sym = function_symbol (spec);
if (sym->metafunc->expr || sym->metafunc->func) {
error (intrinsic, "%s already defined", sym->name);
return;
}
if (sym->type->func.num_params < 0) {
error (intrinsic, "intrinsic functions cannot be variadic");
return;
}
sym->metafunc->expr = intrinsic;
if (sym->metafunc->meta_type == mf_generic) {
//FIXME find a better way to find the specific genfunc
auto genfunc = parse_generic_function (sym->name, spec);
genfunc = add_generic_function (genfunc);
if (genfunc->expr) {
error (intrinsic, "%s already defined", sym->name);
return;
}
genfunc->expr = intrinsic;
} else {
if (sym->metafunc->expr || sym->metafunc->func) {
error (intrinsic, "%s already defined", sym->name);
return;
}
sym->metafunc->expr = intrinsic;
}
}
void