[qfcc] Clean up function search a little

Still some ways to go, but this will help with implementing generic
function calls.
This commit is contained in:
Bill Currie 2024-08-11 11:54:39 +09:00
parent 66866f79b6
commit d0a9e1f54f
2 changed files with 39 additions and 35 deletions

View file

@ -2330,10 +2330,11 @@ function_expr (const expr_t *fexpr, const expr_t *params)
fexpr = find_function (fexpr, params); fexpr = find_function (fexpr, params);
fexpr = convert_name (fexpr); fexpr = convert_name (fexpr);
auto ftype = get_type (fexpr); if (is_error (fexpr)) {
if (fexpr->type == ex_error)
return fexpr; return fexpr;
}
auto ftype = get_type (fexpr);
if (ftype->type != ev_func) { if (ftype->type != ev_func) {
if (fexpr->type == ex_symbol) if (fexpr->type == ex_symbol)
return error (fexpr, "Called object \"%s\" is not a function", return error (fexpr, "Called object \"%s\" is not a function",

View file

@ -338,6 +338,7 @@ parse_generic_function (const char *name, specifier_t spec)
*genfunc->ret_type = make_genparam (&ret_param, genfunc); *genfunc->ret_type = make_genparam (&ret_param, genfunc);
return genfunc; return genfunc;
} }
param_t * param_t *
new_param (const char *selector, const type_t *type, const char *name) new_param (const char *selector, const type_t *type, const char *name)
{ {
@ -605,11 +606,14 @@ func_compare (const void *a, const void *b)
nb = ~nb; nb = ~nb;
if (na != nb) if (na != nb)
return nb - na; return nb - na;
if ((ret = (fb->type->t.func.num_params - fa->type->t.func.num_params))) if ((ret = (tb->t.func.num_params - ta->t.func.num_params)))
return ret; return ret;
for (i = 0; i < na && i < nb; i++) for (i = 0; i < na && i < nb; i++) {
if (ta->t.func.param_types[i] != tb->t.func.param_types[i]) auto diff = tb->t.func.param_types[i] - ta->t.func.param_types[i];
return (long)(tb->t.func.param_types[i] - ta->t.func.param_types[i]); if (diff) {
return diff < 0 ? -1 : 1;
}
}
return 0; return 0;
} }
@ -632,52 +636,51 @@ find_function (const expr_t *fexpr, const expr_t *params)
{ {
int func_count, parm_count, reported = 0; int func_count, parm_count, reported = 0;
overloaded_function_t dummy, *best = 0; overloaded_function_t dummy, *best = 0;
type_t type = {}; void *dummy_p = &dummy;
void **funcs, *dummy_p = &dummy;
if (fexpr->type != ex_symbol) if (fexpr->type != ex_symbol) {
return fexpr; return fexpr;
}
type.type = ev_func; int num_params = params ? list_count (&params->list) : 0;
type.t.func.num_params = params ? list_count (&params->list) : 0; const type_t *arg_types[num_params + 1];
const expr_t *args[type.t.func.num_params + 1]; const expr_t *args[num_params + 1];
if (params) { if (params) {
list_scatter_rev (&params->list, args); list_scatter_rev (&params->list, args);
} }
for (int i = 0; i < num_params; i++) {
for (int i = 0; i < type.t.func.num_params; i++) {
auto e = args[i]; auto e = args[i];
if (e->type == ex_error) { if (e->type == ex_error) {
return e; return e;
} }
arg_types[i] = get_type (e);
} }
const type_t *arg_types[type.t.func.num_params + 1];
type.t.func.param_types = arg_types; type_t call_type = {
for (int i = 0; i < type.t.func.num_params; i++) { .type = ev_func,
auto e = args[i]; .t.func = {
type.t.func.param_types[i] = get_type (e); .num_params = num_params,
} .param_types = arg_types,
funcs = Hash_FindList (function_map, fexpr->symbol->name); },
};
const char *fname = fexpr->symbol->name;
auto funcs = (overloaded_function_t **) Hash_FindList (function_map, fname);
if (!funcs) if (!funcs)
return fexpr; return fexpr;
for (func_count = 0; funcs[func_count]; func_count++) for (func_count = 0; funcs[func_count]; func_count++) continue;
;
if (func_count < 2) { if (func_count < 2) {
auto f = (overloaded_function_t *) funcs[0]; if (func_count && !funcs[0]->overloaded) {
if (func_count && !f->overloaded) {
free (funcs); free (funcs);
return fexpr; return fexpr;
} }
} }
{ call_type.t.func.ret_type = funcs[0]->type->t.func.ret_type;
auto f = (overloaded_function_t *) funcs[0]; dummy.type = find_type (&call_type);
type.t.func.ret_type = f->type->t.func.ret_type;
}
dummy.type = find_type (&type);
qsort (funcs, func_count, sizeof (void *), func_compare); qsort (funcs, func_count, sizeof (void *), func_compare);
dummy.full_name = save_string (va (0, "%s|%s", fexpr->symbol->name, dummy.full_name = save_string (va (0, "%s|%s", fexpr->symbol->name,
encode_params (&type))); encode_params (&call_type)));
dummy_p = bsearch (&dummy_p, funcs, func_count, sizeof (void *), dummy_p = bsearch (&dummy_p, funcs, func_count, sizeof (void *),
func_compare); func_compare);
if (dummy_p) { if (dummy_p) {
@ -691,8 +694,8 @@ find_function (const expr_t *fexpr, const expr_t *params)
for (int i = 0; i < func_count; i++) { for (int i = 0; i < func_count; i++) {
auto f = (overloaded_function_t *) funcs[i]; auto f = (overloaded_function_t *) funcs[i];
parm_count = f->type->t.func.num_params; parm_count = f->type->t.func.num_params;
if ((parm_count >= 0 && parm_count != type.t.func.num_params) if ((parm_count >= 0 && parm_count != call_type.t.func.num_params)
|| (parm_count < 0 && ~parm_count > type.t.func.num_params)) { || (parm_count < 0 && ~parm_count > call_type.t.func.num_params)) {
funcs[i] = 0; funcs[i] = 0;
continue; continue;
} }
@ -701,7 +704,7 @@ find_function (const expr_t *fexpr, const expr_t *params)
int j; int j;
for (j = 0; j < parm_count; j++) { for (j = 0; j < parm_count; j++) {
if (!type_assignable (f->type->t.func.param_types[j], if (!type_assignable (f->type->t.func.param_types[j],
type.t.func.param_types[j])) { call_type.t.func.param_types[j])) {
funcs[i] = 0; funcs[i] = 0;
break; break;
} }