[qfcc] Get type attribute working for computed types

It even handles errors :)
This commit is contained in:
Bill Currie 2025-01-14 01:02:31 +09:00
parent 041216182e
commit ed88152f85
9 changed files with 74 additions and 24 deletions

View file

@ -70,10 +70,13 @@ void setup_type_progs (void);
typedef struct expr_s expr_t; typedef struct expr_s expr_t;
typedef struct gentype_s gentype_t; typedef struct gentype_s gentype_t;
typedef struct rua_ctx_s rua_ctx_t;
typeeval_t *build_type_function (const expr_t *te, int num_types, typeeval_t *build_type_function (const expr_t *te, int num_types,
gentype_t *types); gentype_t *types);
const type_t *evaluate_type (const typeeval_t *typeeval, int num_types, const type_t *evaluate_type (const typeeval_t *typeeval, int num_types,
const type_t **types, const expr_t *expr); const type_t **types, const expr_t *expr,
rua_ctx_t *rua_ctx);
///@} ///@}
#endif//__evaluate_type_h #endif//__evaluate_type_h

View file

@ -1075,7 +1075,8 @@ const expr_t *asx_expr (int op, const expr_t *e1, const expr_t *e2);
const expr_t *unary_expr (int op, const expr_t *e); const expr_t *unary_expr (int op, const expr_t *e);
const expr_t *build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *build_function_call (const expr_t *fexpr, const type_t *ftype,
const expr_t *params); const expr_t *params);
const expr_t *function_expr (const expr_t *e1, const expr_t *e2); const expr_t *function_expr (const expr_t *e1, const expr_t *e2,
rua_ctx_t *ctx);
const expr_t *get_column (const expr_t *e, int i); const expr_t *get_column (const expr_t *e, int i);
const expr_t *constructor_expr (const expr_t *e, const expr_t *params); const expr_t *constructor_expr (const expr_t *e, const expr_t *params);
struct function_s; struct function_s;

View file

@ -218,7 +218,8 @@ function_t *make_function (symbol_t *sym, const char *nice_name,
struct defspace_s *space, struct defspace_s *space,
enum storage_class_e storage); enum storage_class_e storage);
symbol_t *function_symbol (specifier_t spec, rua_ctx_t *ctx); symbol_t *function_symbol (specifier_t spec, rua_ctx_t *ctx);
const expr_t *find_function (const expr_t *fexpr, const expr_t *params); const expr_t *find_function (const expr_t *fexpr, const expr_t *params,
rua_ctx_t *ctx);
function_t *begin_function (specifier_t spec, const char *nicename, function_t *begin_function (specifier_t spec, const char *nicename,
symtab_t *parent, rua_ctx_t *ctx); symtab_t *parent, rua_ctx_t *ctx);
void build_code_function (specifier_t spec, const expr_t *state_expr, void build_code_function (specifier_t spec, const expr_t *state_expr,

View file

@ -67,13 +67,14 @@ evaluate_debug_handler (prdebug_t event, void *param, void *data)
case prd_breakpoint: case prd_breakpoint:
case prd_subenter: case prd_subenter:
case prd_subexit: case prd_subexit:
case prd_runerror:
case prd_watchpoint: case prd_watchpoint:
case prd_begin: case prd_begin:
case prd_terminate: case prd_terminate:
case prd_error: case prd_error:
case prd_none: case prd_none:
break; break;
case prd_runerror:
internal_error (0, "program error in evaluation");
} }
} }

View file

@ -36,6 +36,7 @@
#include "QF/simd/types.h" #include "QF/simd/types.h"
#include "tools/qfcc/include/attribute.h"
#include "tools/qfcc/include/codespace.h" #include "tools/qfcc/include/codespace.h"
#include "tools/qfcc/include/def.h" #include "tools/qfcc/include/def.h"
#include "tools/qfcc/include/defspace.h" #include "tools/qfcc/include/defspace.h"
@ -57,6 +58,7 @@ typedef struct typectx_s {
const type_t **types; const type_t **types;
int num_types; int num_types;
const expr_t *expr; const expr_t *expr;
rua_ctx_t *rua_ctx;
sys_jmpbuf jmpbuf; sys_jmpbuf jmpbuf;
} typectx_t; } typectx_t;
@ -73,6 +75,37 @@ fetch_type (unsigned id, typectx_t *ctx)
return type; return type;
} }
static void
tf_attribute_func (progs_t *pr, void *data)
{
auto ctx = *(typectx_t **) data;
unsigned id = P_UINT (pr, 0);
auto type = fetch_type (id, ctx);
if (!type->attrib) {
error (ctx->expr, "type doesn't support attributes");
Sys_longjmp (ctx->jmpbuf);
}
auto attr_params = &P_STRUCT (pr, pr_int_t, 1);
auto name = PR_GetString (pr, attr_params[0]);
int count = attr_params[1];
attribute_t *attrib = nullptr;
if (count) {
const expr_t *param_exprs[count] = {};
internal_error (ctx->expr, "not implemented");
auto params = new_list_expr (nullptr);
list_gather (&params->list, param_exprs, count);
attrib = new_attribute (name, params);
} else {
attrib = new_attribute (name, nullptr);
}
auto e = type->attrib (type, attrib);
if (is_error (e)) {
Sys_longjmp (ctx->jmpbuf);
}
type = resolve_type (e, ctx->rua_ctx);
R_UINT (pr) = type->id;
}
static void static void
tf_function_func (progs_t *pr, void *data) tf_function_func (progs_t *pr, void *data)
{ {
@ -239,6 +272,7 @@ static typectx_t *type_genfunc;
static bfunction_t type_functions[] = { static bfunction_t type_functions[] = {
{}, // null function {}, // null function
[tf_eval] = { .first_statement = 1 }, [tf_eval] = { .first_statement = 1 },
TF_FUNC(tf_attribute),
TF_FUNC(tf_function), TF_FUNC(tf_function),
TF_FUNC(tf_field), TF_FUNC(tf_field),
TF_FUNC(tf_pointer), TF_FUNC(tf_pointer),
@ -302,12 +336,13 @@ setup_type_progs (void)
const type_t * const type_t *
evaluate_type (const typeeval_t *typeeval, int num_types, const type_t **types, evaluate_type (const typeeval_t *typeeval, int num_types, const type_t **types,
const expr_t *expr) const expr_t *expr, rua_ctx_t *rua_ctx)
{ {
typectx_t ctx = { typectx_t ctx = {
types = types, .types = types,
num_types = num_types, .num_types = num_types,
expr = expr, .expr = expr,
.rua_ctx = rua_ctx,
}; };
int err; int err;
if ((err = Sys_setjmp (ctx.jmpbuf))) { if ((err = Sys_setjmp (ctx.jmpbuf))) {
@ -317,6 +352,8 @@ evaluate_type (const typeeval_t *typeeval, int num_types, const type_t **types,
type_pr.pr_statements = typeeval->code; type_pr.pr_statements = typeeval->code;
type_pr.pr_globals = typeeval->data; type_pr.pr_globals = typeeval->data;
type_pr.globals_size = typeeval->data_size; type_pr.globals_size = typeeval->data_size;
type_pr.pr_strings = (char *) typeeval->strings;
type_pr.pr_stringsize = typeeval->string_size;
type_pr.pr_trace = options.verbosity > 1; type_pr.pr_trace = options.verbosity > 1;
PR_ExecuteProgram (&type_pr, tf_eval); PR_ExecuteProgram (&type_pr, tf_eval);
unsigned id = R_UINT (&type_pr); unsigned id = R_UINT (&type_pr);

View file

@ -447,13 +447,13 @@ build_function_call (const expr_t *fexpr, const type_t *ftype,
} }
const expr_t * const expr_t *
function_expr (const expr_t *fexpr, const expr_t *args) function_expr (const expr_t *fexpr, const expr_t *args, rua_ctx_t *ctx)
{ {
if (fexpr->type == ex_type) { if (fexpr->type == ex_type) {
return constructor_expr (fexpr, args); return constructor_expr (fexpr, args);
} }
fexpr = find_function (fexpr, args); fexpr = find_function (fexpr, args, ctx);
if (is_error (fexpr)) { if (is_error (fexpr)) {
return fexpr; return fexpr;
} }

View file

@ -509,7 +509,7 @@ proc_branch (const expr_t *expr, rua_ctx_t *ctx)
return new_error_expr (); return new_error_expr ();
} }
} }
return function_expr (target, args); return function_expr (target, args, ctx);
} else { } else {
auto branch = new_expr (); auto branch = new_expr ();
branch->type = ex_branch; branch->type = ex_branch;

View file

@ -529,7 +529,7 @@ compute_attribute (int arg_count, const expr_t **args, comp_ctx_t *ctx)
} }
} }
C (OP_STORE_A_1, ctx->args[0], nullptr, type); C (OP_STORE_A_1, ctx->args[0], nullptr, type);
C (OP_STORE_A_1, ctx->args[1], nullptr, attr_params); C (OP_LEA_A, attr_params, nullptr, ctx->args[1]);
C (OP_CALL_B, ctx->funcs[tf_attribute], nullptr, res); C (OP_CALL_B, ctx->funcs[tf_attribute], nullptr, res);
return res; return res;
} }

View file

@ -666,7 +666,7 @@ select_type (gentype_t *gentype, callparm_t param)
static genfunc_t * static genfunc_t *
find_generic_function (genfunc_t **genfuncs, const expr_t *fexpr, find_generic_function (genfunc_t **genfuncs, const expr_t *fexpr,
calltype_t *calltype, bool promote) calltype_t *calltype, bool promote, rua_ctx_t *ctx)
{ {
int num_funcs = 0; int num_funcs = 0;
for (auto gf = genfuncs; *gf; gf++, num_funcs++) continue; for (auto gf = genfuncs; *gf; gf++, num_funcs++) continue;
@ -683,7 +683,11 @@ find_generic_function (genfunc_t **genfuncs, const expr_t *fexpr,
bool ok = true; bool ok = true;
for (int i = 0; ok && i < num_params; i++) { for (int i = 0; ok && i < num_params; i++) {
auto p = &g->params[i]; auto p = &g->params[i];
if (!p->fixed_type) { if (p->compute) {
auto ptype = evaluate_type (p->compute, g->num_types,
types, fexpr, ctx);
ok &= check_type (ptype, call_params[i], costs + j, promote);
} else if (!p->fixed_type) {
costs[j] += 1; costs[j] += 1;
int ind = p->gentype; int ind = p->gentype;
if (!types[ind]) { if (!types[ind]) {
@ -727,7 +731,7 @@ find_generic_function (genfunc_t **genfuncs, const expr_t *fexpr,
static const type_t * static const type_t *
compute_param_type (const genparam_t *param, int param_ind, compute_param_type (const genparam_t *param, int param_ind,
const genfunc_t *genfunc, calltype_t *calltype, const genfunc_t *genfunc, calltype_t *calltype,
const expr_t *fexpr) const expr_t *fexpr, rua_ctx_t *ctx)
{ {
auto call_types = calltype->types; auto call_types = calltype->types;
auto call_params = calltype->params; auto call_params = calltype->params;
@ -736,7 +740,7 @@ compute_param_type (const genparam_t *param, int param_ind,
} }
if (param->compute) { if (param->compute) {
return evaluate_type (param->compute, genfunc->num_types, return evaluate_type (param->compute, genfunc->num_types,
calltype->types, fexpr); calltype->types, fexpr, ctx);
} }
int ind = param->gentype; int ind = param->gentype;
if (!call_types[ind] && param_ind >= 0) { if (!call_types[ind] && param_ind >= 0) {
@ -747,7 +751,8 @@ compute_param_type (const genparam_t *param, int param_ind,
} }
static symbol_t * static symbol_t *
create_generic_sym (genfunc_t *g, const expr_t *fexpr, calltype_t *calltype) create_generic_sym (genfunc_t *g, const expr_t *fexpr, calltype_t *calltype,
rua_ctx_t *ctx)
{ {
int num_params = calltype->num_params; int num_params = calltype->num_params;
const type_t *param_types[num_params]; const type_t *param_types[num_params];
@ -755,10 +760,10 @@ create_generic_sym (genfunc_t *g, const expr_t *fexpr, calltype_t *calltype)
const type_t *return_type; const type_t *return_type;
for (int i = 0; i < num_params; i++) { for (int i = 0; i < num_params; i++) {
auto p = &g->params[i]; auto p = &g->params[i];
param_types[i] = compute_param_type (p, i, g, calltype, fexpr); param_types[i] = compute_param_type (p, i, g, calltype, fexpr, ctx);
param_quals[i] = p->qual; param_quals[i] = p->qual;
} }
return_type = compute_param_type (g->ret_type, -1, g, calltype, fexpr); return_type = compute_param_type (g->ret_type, -1, g, calltype, fexpr, ctx);
if (!return_type) { if (!return_type) {
internal_error (0, "return type not determined"); internal_error (0, "return type not determined");
} }
@ -837,11 +842,12 @@ get_function (const char *name, specifier_t spec, rua_ctx_t *ctx)
|| !fexpr.symbol->metafunc) { || !fexpr.symbol->metafunc) {
internal_error (0, "genfunc oops"); internal_error (0, "genfunc oops");
} }
auto gen = find_generic_function (genfuncs, &fexpr, &calltype, false); auto gen = find_generic_function (genfuncs, &fexpr, &calltype, false,
ctx);
if (gen) { if (gen) {
const type_t *ref_types[gen->num_types] = {}; const type_t *ref_types[gen->num_types] = {};
calltype.types = ref_types; calltype.types = ref_types;
auto sym = create_generic_sym (gen, &fexpr, &calltype); auto sym = create_generic_sym (gen, &fexpr, &calltype, ctx);
if (sym == fexpr.symbol if (sym == fexpr.symbol
|| sym->metafunc == fexpr.symbol->metafunc) { || sym->metafunc == fexpr.symbol->metafunc) {
internal_error (0, "genfunc oops"); internal_error (0, "genfunc oops");
@ -1013,7 +1019,7 @@ new_function (const char *name, const char *nice_name)
} }
const expr_t * const expr_t *
find_function (const expr_t *fexpr, const expr_t *params) find_function (const expr_t *fexpr, const expr_t *params, rua_ctx_t *ctx)
{ {
if (fexpr->type != ex_symbol) { if (fexpr->type != ex_symbol) {
return fexpr; return fexpr;
@ -1045,13 +1051,14 @@ find_function (const expr_t *fexpr, const expr_t *params)
const char *fname = fsym->name; const char *fname = fsym->name;
auto genfuncs = (genfunc_t **) Hash_FindList (generic_functions, fname); auto genfuncs = (genfunc_t **) Hash_FindList (generic_functions, fname);
if (genfuncs) { if (genfuncs) {
auto gen = find_generic_function (genfuncs, fexpr, &calltype, true); auto gen = find_generic_function (genfuncs, fexpr, &calltype, true,
ctx);
if (!gen) { if (!gen) {
return new_error_expr (); return new_error_expr ();
} }
const type_t *ref_types[gen->num_types] = {}; const type_t *ref_types[gen->num_types] = {};
calltype.types = ref_types; calltype.types = ref_types;
auto sym = create_generic_sym (gen, fexpr, &calltype); auto sym = create_generic_sym (gen, fexpr, &calltype, ctx);
if (gen->can_inline) { if (gen->can_inline) {
// the call will be inlined, so a new scope is needed every // the call will be inlined, so a new scope is needed every
// time // time