[qfcc] Return a metafunc for generic functions

One step closer to getting this idea to work.
This commit is contained in:
Bill Currie 2024-08-20 12:43:17 +09:00
parent 67c380e98d
commit d9e2108b91

View file

@ -89,14 +89,14 @@ gen_func_get_key (const void *_f, void *unused)
} }
static const char * static const char *
ol_func_get_key (const void *_f, void *unused) metafunc_get_full_name (const void *_f, void *unused)
{ {
metafunc_t *f = (metafunc_t *) _f; metafunc_t *f = (metafunc_t *) _f;
return f->full_name; return f->full_name;
} }
static const char * static const char *
func_map_get_key (const void *_f, void *unused) metafunc_get_name (const void *_f, void *unused)
{ {
metafunc_t *f = (metafunc_t *) _f; metafunc_t *f = (metafunc_t *) _f;
return f->name; return f->name;
@ -507,20 +507,31 @@ check_params (param_t *params)
static metafunc_t * static metafunc_t *
get_function (const char *name, const type_t *type, specifier_t spec) get_function (const char *name, const type_t *type, specifier_t spec)
{ {
auto genfunc = parse_generic_function (name, spec); metafunc_t *func = Hash_Find (function_map, name);
auto genfunc = parse_generic_function (name, spec);
//FIXME want to be able to provide specific overloads for generic functions //FIXME want to be able to provide specific overloads for generic functions
//but need to figure out details, so disallow for now. //but need to figure out details, so disallow for now.
if (genfunc) { if (genfunc) {
if (Hash_Find (function_map, name)) { if (func && func->meta_type != mf_generic) {
error (0, "can't mix generic and overload"); error (0, "can't mix generic and simple or overload");
return nullptr; return nullptr;
} }
add_generic_function (genfunc); add_generic_function (genfunc);
return nullptr;// FIXME
ALLOC (1024, metafunc_t, metafuncs, func);
*func = (metafunc_t) {
.name = save_string (name),
.full_name = name,
.loc = pr.loc,
.meta_type = mf_generic,
};
Hash_Add (metafuncs, func);
Hash_Add (function_map, func);
return func;
} }
if (Hash_Find (generic_functions, name)) { if (func && func->meta_type == mf_generic) {
error (0, "can't mix generic and overload"); error (0, "can't mix generic and simple or overload");
return nullptr; return nullptr;
} }
@ -529,7 +540,6 @@ get_function (const char *name, const type_t *type, specifier_t spec)
full_name = save_string (va (0, "%s|%s", name, encode_params (type))); full_name = save_string (va (0, "%s|%s", name, encode_params (type)));
metafunc_t *func;
// check if the exact function signature already exists, in which case // check if the exact function signature already exists, in which case
// simply return it. // simply return it.
func = Hash_Find (metafuncs, full_name); func = Hash_Find (metafuncs, full_name);
@ -899,12 +909,14 @@ check_function (symbol_t *fsym)
param_t *params = fsym->params; param_t *params = fsym->params;
param_t *p; param_t *p;
int i; int i;
auto ret_type = fsym->type->func.ret_type;
if (!type_size (fsym->type->func.ret_type)) { if (!ret_type || !type_size (ret_type)) {
error (0, "return type is an incomplete type"); error (0, "return type is an incomplete type");
//fsym->type->func.type = &type_void;//FIXME better type? return;
//fsym->type->t.func.type = &type_void;//FIXME better type?
} }
if (value_too_large (fsym->type->func.ret_type)) { if (value_too_large (ret_type)) {
error (0, "return value too large to be passed by value (%d)", error (0, "return value too large to be passed by value (%d)",
type_size (&type_param)); type_size (&type_param));
//fsym->type->func.type = &type_void;//FIXME better type? //fsym->type->func.type = &type_void;//FIXME better type?
@ -1089,8 +1101,6 @@ function_t *
begin_function (symbol_t *sym, const char *nicename, symtab_t *parent, begin_function (symbol_t *sym, const char *nicename, symtab_t *parent,
int far, storage_class_t storage) int far, storage_class_t storage)
{ {
defspace_t *space;
if (sym->sy_type != sy_func) { if (sym->sy_type != sy_func) {
error (0, "%s is not a function", sym->name); error (0, "%s is not a function", sym->name);
sym = new_symbol_type (sym->name, &type_func); sym = new_symbol_type (sym->name, &type_func);
@ -1101,9 +1111,9 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent,
sym = new_symbol_type (sym->name, sym->type); sym = new_symbol_type (sym->name, sym->type);
sym = function_symbol (sym, (specifier_t) { .is_overload = true }); sym = function_symbol (sym, (specifier_t) { .is_overload = true });
} }
space = sym->table->space;
if (far) defspace_t *space = far ? pr.far_data : sym->table->space;
space = pr.far_data;
make_function (sym, nicename, space, storage); make_function (sym, nicename, space, storage);
if (!sym->func->def->external) { if (!sym->func->def->external) {
sym->func->def->initialized = 1; sym->func->def->initialized = 1;
@ -1263,7 +1273,6 @@ build_builtin_function (symbol_t *sym, const expr_t *bi_val, int far,
storage_class_t storage) storage_class_t storage)
{ {
int bi; int bi;
defspace_t *space;
if (sym->sy_type != sy_func) { if (sym->sy_type != sy_func) {
error (bi_val, "%s is not a function", sym->name); error (bi_val, "%s is not a function", sym->name);
@ -1277,10 +1286,10 @@ build_builtin_function (symbol_t *sym, const expr_t *bi_val, int far,
error (bi_val, "invalid constant for = #"); error (bi_val, "invalid constant for = #");
return 0; return 0;
} }
space = sym->table->space;
if (far) defspace_t *space = far ? pr.far_data : sym->table->space;
space = pr.far_data;
make_function (sym, 0, space, storage); make_function (sym, 0, space, storage);
if (sym->func->def->external) if (sym->func->def->external)
return 0; return 0;
@ -1333,7 +1342,7 @@ clear_functions (void)
Hash_FlushTable (function_map); Hash_FlushTable (function_map);
} else { } else {
generic_functions = Hash_NewTable (1021, gen_func_get_key, 0, 0, 0); generic_functions = Hash_NewTable (1021, gen_func_get_key, 0, 0, 0);
metafuncs = Hash_NewTable (1021, ol_func_get_key, 0, 0, 0); metafuncs = Hash_NewTable (1021, metafunc_get_full_name, 0, 0, 0);
function_map = Hash_NewTable (1021, func_map_get_key, 0, 0, 0); function_map = Hash_NewTable (1021, metafunc_get_name, 0, 0, 0);
} }
} }