mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 13:11:00 +00:00
[qfcc] Save the type evaluation code
I don't yet know whether the generated code is correct, but the little functions that compute a generic type gets stored in the function's params/return type.
This commit is contained in:
parent
b59a8fb66a
commit
55a5782a95
3 changed files with 50 additions and 41 deletions
|
@ -44,13 +44,18 @@
|
||||||
// The maximum size of a temp def, return value, or parameter value
|
// The maximum size of a temp def, return value, or parameter value
|
||||||
#define MAX_DEF_SIZE 32
|
#define MAX_DEF_SIZE 32
|
||||||
|
|
||||||
typedef struct function_s function_t;
|
typedef enum param_qual_e {
|
||||||
|
pq_const,
|
||||||
|
pq_in,
|
||||||
|
pq_out,
|
||||||
|
pq_inout,
|
||||||
|
} param_qual_t;
|
||||||
|
|
||||||
typedef const type_t *(*gentype_compute_f) ();
|
typedef struct function_s function_t;
|
||||||
|
typedef struct typeeval_s typeeval_t;
|
||||||
|
|
||||||
typedef struct gentype_s {
|
typedef struct gentype_s {
|
||||||
const char *name;
|
const char *name;
|
||||||
gentype_compute_f compute;
|
|
||||||
// earlier types have priority over later types. null if compute valid
|
// earlier types have priority over later types. null if compute valid
|
||||||
const type_t **valid_types;
|
const type_t **valid_types;
|
||||||
} gentype_t;
|
} gentype_t;
|
||||||
|
@ -58,7 +63,9 @@ typedef struct gentype_s {
|
||||||
typedef struct genparam_s {
|
typedef struct genparam_s {
|
||||||
const char *name;
|
const char *name;
|
||||||
const type_t *fixed_type;
|
const type_t *fixed_type;
|
||||||
|
typeeval_t *compute;
|
||||||
int gentype; // index into function's list of types
|
int gentype; // index into function's list of types
|
||||||
|
param_qual_t qual;
|
||||||
} genparam_t;
|
} genparam_t;
|
||||||
|
|
||||||
typedef struct genfunc_s {
|
typedef struct genfunc_s {
|
||||||
|
@ -163,13 +170,6 @@ typedef struct metafunc_s {
|
||||||
|
|
||||||
extern function_t *current_func;
|
extern function_t *current_func;
|
||||||
|
|
||||||
typedef enum param_qual_e {
|
|
||||||
pq_const,
|
|
||||||
pq_in,
|
|
||||||
pq_out,
|
|
||||||
pq_inout,
|
|
||||||
} param_qual_t;
|
|
||||||
|
|
||||||
/** Representation of a function parameter.
|
/** Representation of a function parameter.
|
||||||
\note The first two fields match the first two fields of keywordarg_t
|
\note The first two fields match the first two fields of keywordarg_t
|
||||||
in method.h
|
in method.h
|
||||||
|
|
|
@ -912,19 +912,18 @@ build_type_function (const expr_t *te, int num_types, gentype_t *types)
|
||||||
}
|
}
|
||||||
C (OP_NOP, nullptr, nullptr, nullptr);
|
C (OP_NOP, nullptr, nullptr, nullptr);
|
||||||
def_t *res = nullptr;
|
def_t *res = nullptr;
|
||||||
|
typeeval_t *func = nullptr;
|
||||||
if (!Sys_setjmp (ctx->jmpbuf)) {
|
if (!Sys_setjmp (ctx->jmpbuf)) {
|
||||||
res = compute_type (te, ctx);
|
res = compute_type (te, ctx);
|
||||||
} else {
|
|
||||||
res = compute_tmp (ctx);
|
|
||||||
}
|
|
||||||
C (OP_RETURN, res, nullptr, 0);
|
C (OP_RETURN, res, nullptr, 0);
|
||||||
typeeval_t *func = malloc (sizeof (typeeval_t));
|
func = malloc (sizeof (typeeval_t));
|
||||||
*func = (typeeval_t) {
|
*func = (typeeval_t) {
|
||||||
.code = code->code,
|
.code = code->code,
|
||||||
.data = data->data,
|
.data = data->data,
|
||||||
.code_size = code->size,
|
.code_size = code->size,
|
||||||
.data_size = data->size,
|
.data_size = data->size,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
code->code = nullptr;
|
code->code = nullptr;
|
||||||
data->data = nullptr;
|
data->data = nullptr;
|
||||||
codespace_delete (code);
|
codespace_delete (code);
|
||||||
|
|
|
@ -111,6 +111,15 @@ check_generic_param (genparam_t *param, genfunc_t *genfunc)
|
||||||
internal_error (0, "invalid type index %d on %s for %s",
|
internal_error (0, "invalid type index %d on %s for %s",
|
||||||
param->gentype, param->name, genfunc->name);
|
param->gentype, param->name, genfunc->name);
|
||||||
}
|
}
|
||||||
|
if (param->compute) {
|
||||||
|
internal_error (0, "fixed and computed types on %s for %s",
|
||||||
|
param->name, genfunc->name);
|
||||||
|
}
|
||||||
|
} else if (param->compute) {
|
||||||
|
if (param->gentype != -1) {
|
||||||
|
internal_error (0, "invalid type index %d on %s for %s",
|
||||||
|
param->gentype, param->name, genfunc->name);
|
||||||
|
}
|
||||||
} else if (param->gentype < 0 || param->gentype >= genfunc->num_types) {
|
} else if (param->gentype < 0 || param->gentype >= genfunc->num_types) {
|
||||||
internal_error (0, "invalid type index %d on %s for %s",
|
internal_error (0, "invalid type index %d on %s for %s",
|
||||||
param->gentype, param->name, genfunc->name);
|
param->gentype, param->name, genfunc->name);
|
||||||
|
@ -126,10 +135,6 @@ cmp_genparams (genfunc_t *g1, genparam_t *p1, genfunc_t *g2, genparam_t *p2)
|
||||||
// fixed_type for both p1 and p2 is null
|
// fixed_type for both p1 and p2 is null
|
||||||
auto t1 = g1->types[p1->gentype];
|
auto t1 = g1->types[p1->gentype];
|
||||||
auto t2 = g2->types[p2->gentype];
|
auto t2 = g2->types[p2->gentype];
|
||||||
if (t1.compute || t2.compute) {
|
|
||||||
// FIXME probably not right
|
|
||||||
return t1.compute == t2.compute;
|
|
||||||
}
|
|
||||||
auto vt1 = t1.valid_types;
|
auto vt1 = t1.valid_types;
|
||||||
auto vt2 = t2.valid_types;
|
auto vt2 = t2.valid_types;
|
||||||
for (; *vt1 && *vt2 && *vt1 == *vt2; vt1++, vt2++) continue;
|
for (; *vt1 && *vt2 && *vt1 == *vt2; vt1++, vt2++) continue;
|
||||||
|
@ -143,9 +148,8 @@ add_generic_function (genfunc_t *genfunc)
|
||||||
|
|
||||||
for (int i = 0; i < genfunc->num_types; i++) {
|
for (int i = 0; i < genfunc->num_types; i++) {
|
||||||
auto gentype = &genfunc->types[i];
|
auto gentype = &genfunc->types[i];
|
||||||
if (gentype->compute && gentype->valid_types) {
|
if (!gentype->valid_types) {
|
||||||
internal_error (0, "both compute and valid_types set in "
|
internal_error (0, "no valid_types set in generic type");
|
||||||
"generic type");
|
|
||||||
}
|
}
|
||||||
for (auto type = gentype->valid_types; type && *type; type++) {
|
for (auto type = gentype->valid_types; type && *type; type++) {
|
||||||
if (is_void (*type)) {
|
if (is_void (*type)) {
|
||||||
|
@ -202,12 +206,6 @@ add_generic_function (genfunc_t *genfunc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gentype_compute_f
|
|
||||||
check_compute_type (const expr_t *expr)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const type_t **
|
static const type_t **
|
||||||
valid_type_list (const expr_t *expr)
|
valid_type_list (const expr_t *expr)
|
||||||
{
|
{
|
||||||
|
@ -242,13 +240,9 @@ make_gentype (const expr_t *expr)
|
||||||
auto sym = expr->symbol;
|
auto sym = expr->symbol;
|
||||||
gentype_t gentype = {
|
gentype_t gentype = {
|
||||||
.name = save_string (sym->name),
|
.name = save_string (sym->name),
|
||||||
.compute = check_compute_type (sym->expr),
|
|
||||||
.valid_types = valid_type_list (sym->expr),
|
.valid_types = valid_type_list (sym->expr),
|
||||||
};
|
};
|
||||||
if (gentype.compute && gentype.valid_types) {
|
if (!gentype.valid_types) {
|
||||||
internal_error (expr, "both computed type and type list");
|
|
||||||
}
|
|
||||||
if (!gentype.compute && !gentype.valid_types) {
|
|
||||||
internal_error (expr, "empty generic type");
|
internal_error (expr, "empty generic type");
|
||||||
}
|
}
|
||||||
return gentype;
|
return gentype;
|
||||||
|
@ -273,10 +267,18 @@ find_gentype (const expr_t *expr, genfunc_t *genfunc)
|
||||||
static genparam_t
|
static genparam_t
|
||||||
make_genparam (param_t *param, genfunc_t *genfunc)
|
make_genparam (param_t *param, genfunc_t *genfunc)
|
||||||
{
|
{
|
||||||
|
int gentype = find_gentype (param->type_expr, genfunc);
|
||||||
|
typeeval_t *compute = nullptr;
|
||||||
|
if (gentype < 0 && param->type_expr) {
|
||||||
|
compute = build_type_function (param->type_expr,
|
||||||
|
genfunc->num_types, genfunc->types);
|
||||||
|
}
|
||||||
genparam_t genparam = {
|
genparam_t genparam = {
|
||||||
.name = save_string (param->name),
|
.name = save_string (param->name),
|
||||||
.fixed_type = param->type,
|
.fixed_type = param->type,
|
||||||
.gentype = find_gentype (param->type_expr, genfunc),
|
.compute = compute,
|
||||||
|
.gentype = gentype,
|
||||||
|
.qual = param->qual,
|
||||||
};
|
};
|
||||||
return genparam;
|
return genparam;
|
||||||
}
|
}
|
||||||
|
@ -302,7 +304,8 @@ parse_generic_function (const char *name, specifier_t spec)
|
||||||
for (auto s = generic_tab->symbols; s; s = s->next) {
|
for (auto s = generic_tab->symbols; s; s = s->next) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto q = &ret_param; q; q = q->next) {
|
for (auto q = &ret_param; q; q = q->next) {
|
||||||
// FIXME check complex expressions
|
// skip complex expressions because they will be either fixed
|
||||||
|
// or rely on earlier parameters
|
||||||
if (!q->type_expr || q->type_expr->type != ex_symbol) {
|
if (!q->type_expr || q->type_expr->type != ex_symbol) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -338,7 +341,7 @@ parse_generic_function (const char *name, specifier_t spec)
|
||||||
num_gentype = 0;
|
num_gentype = 0;
|
||||||
for (auto s = generic_tab->symbols; s; s = s->next) {
|
for (auto s = generic_tab->symbols; s; s = s->next) {
|
||||||
for (auto q = &ret_param; q; q = q->next) {
|
for (auto q = &ret_param; q; q = q->next) {
|
||||||
// FIXME check complex expressions
|
// see complex expressions comment above
|
||||||
if (!q->type_expr || q->type_expr->type != ex_symbol) {
|
if (!q->type_expr || q->type_expr->type != ex_symbol) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -350,6 +353,7 @@ parse_generic_function (const char *name, specifier_t spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
num_params = 0;
|
num_params = 0;
|
||||||
|
// skip return type so it can be done last to support complex expressions
|
||||||
for (auto p = ret_param.next; p; p = p->next) {
|
for (auto p = ret_param.next; p; p = p->next) {
|
||||||
genfunc->params[num_params++] = make_genparam (p, genfunc);
|
genfunc->params[num_params++] = make_genparam (p, genfunc);
|
||||||
}
|
}
|
||||||
|
@ -754,6 +758,7 @@ find_generic_function (const expr_t *fexpr, genfunc_t **genfuncs,
|
||||||
auto g = genfuncs[best_ind];
|
auto g = genfuncs[best_ind];
|
||||||
const type_t *types[g->num_types] = {};
|
const type_t *types[g->num_types] = {};
|
||||||
const type_t *param_types[num_params];
|
const type_t *param_types[num_params];
|
||||||
|
param_qual_t param_quals[num_params];
|
||||||
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];
|
||||||
|
@ -766,6 +771,7 @@ find_generic_function (const expr_t *fexpr, genfunc_t **genfuncs,
|
||||||
} else {
|
} else {
|
||||||
param_types[i] = p->fixed_type;
|
param_types[i] = p->fixed_type;
|
||||||
}
|
}
|
||||||
|
param_quals[i] = p->qual;
|
||||||
}
|
}
|
||||||
if (!g->ret_type->fixed_type) {
|
if (!g->ret_type->fixed_type) {
|
||||||
int ind = g->ret_type->gentype;
|
int ind = g->ret_type->gentype;
|
||||||
|
@ -791,6 +797,7 @@ find_generic_function (const expr_t *fexpr, genfunc_t **genfuncs,
|
||||||
.ret_type = return_type,
|
.ret_type = return_type,
|
||||||
.num_params = num_params,
|
.num_params = num_params,
|
||||||
.param_types = param_types,
|
.param_types = param_types,
|
||||||
|
.param_quals = param_quals,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
auto type = find_type (&ftype);
|
auto type = find_type (&ftype);
|
||||||
|
@ -823,6 +830,7 @@ find_function (const expr_t *fexpr, const expr_t *params)
|
||||||
|
|
||||||
int num_params = params ? list_count (¶ms->list) : 0;
|
int num_params = params ? list_count (¶ms->list) : 0;
|
||||||
const type_t *arg_types[num_params + 1];
|
const type_t *arg_types[num_params + 1];
|
||||||
|
param_qual_t arg_quals[num_params + 1];
|
||||||
const expr_t *args[num_params + 1];
|
const expr_t *args[num_params + 1];
|
||||||
if (params) {
|
if (params) {
|
||||||
list_scatter_rev (¶ms->list, args);
|
list_scatter_rev (¶ms->list, args);
|
||||||
|
@ -833,6 +841,7 @@ find_function (const expr_t *fexpr, const expr_t *params)
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
arg_types[i] = get_type (e);
|
arg_types[i] = get_type (e);
|
||||||
|
arg_quals[i] = pq_in;
|
||||||
}
|
}
|
||||||
|
|
||||||
type_t call_type = {
|
type_t call_type = {
|
||||||
|
@ -840,6 +849,7 @@ find_function (const expr_t *fexpr, const expr_t *params)
|
||||||
.func = {
|
.func = {
|
||||||
.num_params = num_params,
|
.num_params = num_params,
|
||||||
.param_types = arg_types,
|
.param_types = arg_types,
|
||||||
|
.param_quals = arg_quals,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue