[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 gentype_s gentype_t;
typedef struct rua_ctx_s rua_ctx_t;
typeeval_t *build_type_function (const expr_t *te, int num_types,
gentype_t *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

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 *build_function_call (const expr_t *fexpr, const type_t *ftype,
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 *constructor_expr (const expr_t *e, const expr_t *params);
struct function_s;

View file

@ -218,7 +218,8 @@ function_t *make_function (symbol_t *sym, const char *nice_name,
struct defspace_s *space,
enum storage_class_e storage);
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,
symtab_t *parent, rua_ctx_t *ctx);
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_subenter:
case prd_subexit:
case prd_runerror:
case prd_watchpoint:
case prd_begin:
case prd_terminate:
case prd_error:
case prd_none:
break;
case prd_runerror:
internal_error (0, "program error in evaluation");
}
}

View file

@ -36,6 +36,7 @@
#include "QF/simd/types.h"
#include "tools/qfcc/include/attribute.h"
#include "tools/qfcc/include/codespace.h"
#include "tools/qfcc/include/def.h"
#include "tools/qfcc/include/defspace.h"
@ -57,6 +58,7 @@ typedef struct typectx_s {
const type_t **types;
int num_types;
const expr_t *expr;
rua_ctx_t *rua_ctx;
sys_jmpbuf jmpbuf;
} typectx_t;
@ -73,6 +75,37 @@ fetch_type (unsigned id, typectx_t *ctx)
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
tf_function_func (progs_t *pr, void *data)
{
@ -239,6 +272,7 @@ static typectx_t *type_genfunc;
static bfunction_t type_functions[] = {
{}, // null function
[tf_eval] = { .first_statement = 1 },
TF_FUNC(tf_attribute),
TF_FUNC(tf_function),
TF_FUNC(tf_field),
TF_FUNC(tf_pointer),
@ -302,12 +336,13 @@ setup_type_progs (void)
const type_t *
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 = {
types = types,
num_types = num_types,
expr = expr,
.types = types,
.num_types = num_types,
.expr = expr,
.rua_ctx = rua_ctx,
};
int err;
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_globals = typeeval->data;
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;
PR_ExecuteProgram (&type_pr, tf_eval);
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 *
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) {
return constructor_expr (fexpr, args);
}
fexpr = find_function (fexpr, args);
fexpr = find_function (fexpr, args, ctx);
if (is_error (fexpr)) {
return fexpr;
}

View file

@ -509,7 +509,7 @@ proc_branch (const expr_t *expr, rua_ctx_t *ctx)
return new_error_expr ();
}
}
return function_expr (target, args);
return function_expr (target, args, ctx);
} else {
auto branch = new_expr ();
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[1], nullptr, attr_params);
C (OP_LEA_A, attr_params, nullptr, ctx->args[1]);
C (OP_CALL_B, ctx->funcs[tf_attribute], nullptr, res);
return res;
}

View file

@ -666,7 +666,7 @@ select_type (gentype_t *gentype, callparm_t param)
static genfunc_t *
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;
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;
for (int i = 0; ok && i < num_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;
int ind = p->gentype;
if (!types[ind]) {
@ -727,7 +731,7 @@ find_generic_function (genfunc_t **genfuncs, const expr_t *fexpr,
static const type_t *
compute_param_type (const genparam_t *param, int param_ind,
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_params = calltype->params;
@ -736,7 +740,7 @@ compute_param_type (const genparam_t *param, int param_ind,
}
if (param->compute) {
return evaluate_type (param->compute, genfunc->num_types,
calltype->types, fexpr);
calltype->types, fexpr, ctx);
}
int ind = param->gentype;
if (!call_types[ind] && param_ind >= 0) {
@ -747,7 +751,8 @@ compute_param_type (const genparam_t *param, int param_ind,
}
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;
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;
for (int i = 0; i < num_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;
}
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) {
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) {
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) {
const type_t *ref_types[gen->num_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
|| sym->metafunc == fexpr.symbol->metafunc) {
internal_error (0, "genfunc oops");
@ -1013,7 +1019,7 @@ new_function (const char *name, const char *nice_name)
}
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) {
return fexpr;
@ -1045,13 +1051,14 @@ find_function (const expr_t *fexpr, const expr_t *params)
const char *fname = fsym->name;
auto genfuncs = (genfunc_t **) Hash_FindList (generic_functions, fname);
if (genfuncs) {
auto gen = find_generic_function (genfuncs, fexpr, &calltype, true);
auto gen = find_generic_function (genfuncs, fexpr, &calltype, true,
ctx);
if (!gen) {
return new_error_expr ();
}
const type_t *ref_types[gen->num_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) {
// the call will be inlined, so a new scope is needed every
// time