mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 05:01:24 +00:00
[qfcc] Get type attribute working for computed types
It even handles errors :)
This commit is contained in:
parent
041216182e
commit
ed88152f85
9 changed files with 74 additions and 24 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 (¶ms->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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue