mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-07 18:01:30 +00:00
[qfcc] Support type.attribute on any type
The goal is to make it easy to get size/coord/base types from image types without creating a zillion type functions. It was necessary to make it possible for any type to have an attribute function (returns an expression so it can be more useful: types are returned via type expressions). Algebra types were the first victim (which was nice for testing).
This commit is contained in:
parent
ccd42c5c21
commit
320f9e2fe7
10 changed files with 234 additions and 70 deletions
|
@ -86,10 +86,10 @@ typedef struct multivector_s {
|
|||
struct symbol_s *mvec_sym; ///< null if single group
|
||||
} multivector_t;
|
||||
|
||||
struct attribute_s;
|
||||
typedef struct attribute_s attribute_t;
|
||||
bool is_algebra (const type_t *type) __attribute__((pure));
|
||||
const type_t *algebra_type (const type_t *type, const expr_t *params);
|
||||
const type_t *algebra_subtype (const type_t *type, struct attribute_s *attr);
|
||||
const type_t *algebra_subtype (const type_t *type, const attribute_t *attr);
|
||||
const type_t *algebra_mvec_type (algebra_t *algebra, pr_uint_t group_mask);
|
||||
int algebra_count_flips (const algebra_t *alg, pr_uint_t a, pr_uint_t b) __attribute__((pure));
|
||||
struct ex_value_s *algebra_blade_value (algebra_t *alg, const char *name);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
enum {
|
||||
tf_null,
|
||||
tf_eval,
|
||||
tf_attribute,
|
||||
tf_function,
|
||||
tf_field,
|
||||
tf_pointer,
|
||||
|
@ -59,8 +60,10 @@ typedef struct typeeval_s {
|
|||
struct typeeval_s *next;
|
||||
struct dstatement_s *code;
|
||||
struct pr_type_s *data;
|
||||
const char *strings;
|
||||
int code_size;
|
||||
int data_size;
|
||||
int string_size;
|
||||
} typeeval_t;
|
||||
|
||||
void setup_type_progs (void);
|
||||
|
|
|
@ -331,6 +331,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
int op; ///< type "function"
|
||||
const expr_t *params; ///< if dynamic
|
||||
const attribute_t *attrib;
|
||||
const type_t *type;
|
||||
const symbol_t *sym;
|
||||
} ex_type_t;
|
||||
|
|
|
@ -103,6 +103,7 @@ typedef struct type_s {
|
|||
int allocated;
|
||||
struct protocollist_s *protos;
|
||||
const char *encoding; ///< Objective-QC encoding
|
||||
const expr_t *(*attrib) (const type_t *type, const attribute_t *attr);
|
||||
} type_t;
|
||||
|
||||
#define EV_TYPE(type) extern type_t type_##type;
|
||||
|
|
|
@ -342,6 +342,13 @@ is_algebra (const type_t *type)
|
|||
return type->meta == ty_algebra;
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
algebra_attrib (const type_t *type, const attribute_t *attr)
|
||||
{
|
||||
type = algebra_subtype (type, attr);
|
||||
return new_type_expr (type);
|
||||
}
|
||||
|
||||
const type_t *
|
||||
algebra_type (const type_t *type, const expr_t *params)
|
||||
{
|
||||
|
@ -412,12 +419,13 @@ algebra_type (const type_t *type, const expr_t *params)
|
|||
t->type = ev_invalid;
|
||||
t->alignment = (dim > 1 ? 4 : 2) * type->alignment;
|
||||
t->algebra = algebra;
|
||||
t->attrib = algebra_attrib;
|
||||
algebra->algebra_type = t;
|
||||
return find_type (t);
|
||||
}
|
||||
|
||||
const type_t *
|
||||
algebra_subtype (const type_t *type, attribute_t *attr)
|
||||
algebra_subtype (const type_t *type, const attribute_t *attr)
|
||||
{
|
||||
if (!is_algebra (type)) {
|
||||
internal_error (0, "unexpected type");
|
||||
|
@ -532,6 +540,7 @@ algebra_mvec_type (algebra_t *algebra, pr_uint_t group_mask)
|
|||
.algebra = (algebra_t *) mvec,
|
||||
.freeable = true,
|
||||
.allocated = true,
|
||||
.attrib = algebra_attrib,
|
||||
};
|
||||
chain_type (type);
|
||||
if (!(group_mask & (group_mask - 1))) {
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "qfalloca.h"
|
||||
|
||||
#include "tools/qfcc/include/algebra.h"
|
||||
#include "tools/qfcc/include/attribute.h"
|
||||
#include "tools/qfcc/include/expr.h"
|
||||
#include "tools/qfcc/include/method.h"
|
||||
#include "tools/qfcc/include/rua-lang.h"
|
||||
|
@ -106,6 +107,7 @@ get_op_string (int op)
|
|||
case QC_REVERSE: return "@reverse";
|
||||
case QC_DUAL: return "@dual";
|
||||
case QC_UNDUAL: return "@undual";
|
||||
case QC_ATTRIBUTE: return ".attribute";
|
||||
case QC_AT_FUNCTION:return "@function";
|
||||
case QC_AT_FIELD: return "@field";
|
||||
case QC_AT_POINTER: return "@pointer";
|
||||
|
@ -347,6 +349,11 @@ print_type_expr (dstring_t *dstr, const expr_t *e, int level, int id,
|
|||
if (!str) {
|
||||
str = type_get_encoding (e->typ.type);
|
||||
}
|
||||
} else if (e->typ.attrib) {
|
||||
auto attrib = e->typ.attrib;
|
||||
_print_expr (dstr, attrib->params, level + 1, id, nullptr);
|
||||
dasprintf (dstr, "%*se_%p -> e_%p;\n", indent, "", e, attrib->params);
|
||||
str = attrib->name;
|
||||
} else if (e->typ.sym) {
|
||||
str = e->typ.sym->name;
|
||||
}
|
||||
|
|
|
@ -680,6 +680,10 @@ spec_process (specifier_t spec, rua_ctx_t *ctx)
|
|||
spec = default_type (spec, spec.sym);
|
||||
}
|
||||
if (!spec.type_list) {
|
||||
if (spec.type_expr) {
|
||||
spec.type = resolve_type (spec.type_expr, ctx);
|
||||
spec.type_list = nullptr;
|
||||
}
|
||||
return spec;
|
||||
}
|
||||
if (spec.type_list->type != ex_list) {
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "QF/progs.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
#include "tools/qfcc/include/attribute.h"
|
||||
#include "tools/qfcc/include/def.h"
|
||||
#include "tools/qfcc/include/defspace.h"
|
||||
#include "tools/qfcc/include/codespace.h"
|
||||
|
@ -43,6 +44,7 @@
|
|||
#include "tools/qfcc/include/rua-lang.h"
|
||||
#include "tools/qfcc/include/shared.h"
|
||||
#include "tools/qfcc/include/statements.h"
|
||||
#include "tools/qfcc/include/strpool.h"
|
||||
#include "tools/qfcc/include/symtab.h"
|
||||
#include "tools/qfcc/include/type.h"
|
||||
|
||||
|
@ -51,6 +53,7 @@ typedef struct {
|
|||
int num_types;
|
||||
codespace_t *code;
|
||||
defspace_t *data;
|
||||
strpool_t *strings;
|
||||
sys_jmpbuf jmpbuf;
|
||||
def_t *args[3];
|
||||
def_t *funcs[tf_num_functions];
|
||||
|
@ -80,6 +83,15 @@ check_type (const expr_t *arg)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
check_attribute (const expr_t *arg)
|
||||
{
|
||||
if (arg->type != ex_type && !arg->typ.attrib) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __attribute__((pure))
|
||||
check_int (const expr_t *arg)
|
||||
{
|
||||
|
@ -119,6 +131,24 @@ single_type (int arg_count, const expr_t **args)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static const char *
|
||||
single_type_attribute (int arg_count, const expr_t **args)
|
||||
{
|
||||
if (arg_count < 1) {
|
||||
return "too few arguments";
|
||||
}
|
||||
if (arg_count > 2) {
|
||||
return "too many arguments";
|
||||
}
|
||||
if (!check_type (args[0])) {
|
||||
return "first parameter must be a type";
|
||||
}
|
||||
if (!check_attribute (args[1])) {
|
||||
return "second parameter must be a type attribute";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const char *
|
||||
single_type_opt_int (int arg_count, const expr_t **args)
|
||||
{
|
||||
|
@ -158,6 +188,24 @@ single_type_opt_int_pair (int arg_count, const expr_t **args)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
evaluate_attribute (int arg_count, const expr_t **args, rua_ctx_t *ctx)
|
||||
{
|
||||
auto type = resolve_type (args[0], ctx);
|
||||
if (!type) {
|
||||
return error (args[0], "could not resolve type");
|
||||
}
|
||||
if (!type->attrib) {
|
||||
return error (args[0], "type doesn't support attributes");
|
||||
} else {
|
||||
auto e = type->attrib (type, args[1]->typ.attrib);
|
||||
if (!is_error (e)) {
|
||||
e = eval_type (e, ctx);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
evaluate_int (const expr_t *expr, rua_ctx_t *ctx)
|
||||
{
|
||||
|
@ -178,10 +226,9 @@ evaluate_int (const expr_t *expr, rua_ctx_t *ctx)
|
|||
internal_error (expr, "invalid type op");
|
||||
}
|
||||
int op = expr->typ.op;
|
||||
int ind = op - QC_GENERIC;
|
||||
auto type = expr->typ.type;
|
||||
if (!type) {
|
||||
return error (expr, "invalid type passed to %s", type_funcs[ind].name);
|
||||
return error (expr, "invalid type passed to %s", type_funcs[op].name);
|
||||
}
|
||||
if (op == QC_AT_WIDTH) {
|
||||
return new_int_expr (type_width (type), false);
|
||||
|
@ -201,6 +248,25 @@ evaluate_int_op (int arg_count, const expr_t **args, rua_ctx_t *ctx)
|
|||
return evaluate_int (args[0], ctx);
|
||||
}
|
||||
|
||||
static const type_t *
|
||||
resolve_attribute (int arg_count, const expr_t **args, rua_ctx_t *ctx)
|
||||
{
|
||||
auto type = resolve_type (args[0], ctx);
|
||||
if (type) {
|
||||
if (!type->attrib) {
|
||||
error (args[0], "type doesn't support attributes");
|
||||
} else {
|
||||
auto e = type->attrib (type, args[1]->typ.attrib);
|
||||
if (is_error (e)) {
|
||||
type = nullptr;
|
||||
} else {
|
||||
type = resolve_type (e, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static const type_t *
|
||||
resolve_function (int arg_count, const expr_t **args, rua_ctx_t *ctx)
|
||||
{
|
||||
|
@ -418,6 +484,8 @@ expand_matrix (int arg_count, const expr_t **args, rua_ctx_t *ctx)
|
|||
}
|
||||
|
||||
static def_t *compute_tmp (comp_ctx_t *ctx);
|
||||
static def_t *compute_sized_tmp (int size, comp_ctx_t *ctx);
|
||||
static pr_string_t compute_str (const char *, comp_ctx_t *ctx);
|
||||
static def_t *compute_type (const expr_t *arg, comp_ctx_t *ctx);
|
||||
static def_t *compute_val (const expr_t *arg, comp_ctx_t *ctx);
|
||||
|
||||
|
@ -433,6 +501,39 @@ static def_t *compute_val (const expr_t *arg, comp_ctx_t *ctx);
|
|||
}
|
||||
#define C(op, a, b, c) codespace_addcode (ctx->code, I(op, a, b, c), 1)
|
||||
|
||||
static def_t *
|
||||
compute_attribute (int arg_count, const expr_t **args, comp_ctx_t *ctx)
|
||||
{
|
||||
auto type = compute_type (args[0], ctx);
|
||||
auto res = compute_tmp (ctx);
|
||||
auto attrib = args[1]->typ.attrib;
|
||||
int count = attrib->params ? list_count (&attrib->params->list) : 0;
|
||||
// FIXME assumes simple 1-component types
|
||||
auto attr_params = compute_sized_tmp (2 + 2 * count, ctx);
|
||||
def_t ndef = { .offset = attr_params->offset + 0, .space = ctx->data };
|
||||
def_t cdef = { .offset = attr_params->offset + 1, .space = ctx->data };
|
||||
D_STRING (&ndef) = compute_str (attrib->name, ctx);
|
||||
D_INT (&cdef) = count;
|
||||
if (count) {
|
||||
const expr_t *params[count];
|
||||
list_scatter (&attrib->params->list, params);
|
||||
for (int i = 0; i < count; i++) {
|
||||
auto p = compute_type (params[i], ctx);
|
||||
auto s = codespace_newstatement (ctx->code);
|
||||
*s = (dstatement_t) {
|
||||
.op = OP_STORE_A_1,
|
||||
.a = attr_params->offset + 2 + i,
|
||||
.b = 0,
|
||||
.c = DOFFSET(p),
|
||||
};
|
||||
}
|
||||
}
|
||||
C (OP_STORE_A_1, ctx->args[0], nullptr, type);
|
||||
C (OP_STORE_A_1, ctx->args[1], nullptr, attr_params);
|
||||
C (OP_CALL_B, ctx->funcs[tf_attribute], nullptr, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static def_t *
|
||||
compute_function (int arg_count, const expr_t **args, comp_ctx_t *ctx)
|
||||
{
|
||||
|
@ -582,87 +683,94 @@ compute_cols (int arg_count, const expr_t **args, comp_ctx_t *ctx)
|
|||
}
|
||||
|
||||
static type_func_t type_funcs[] = {
|
||||
[QC_AT_FUNCTION - QC_GENERIC] = {
|
||||
[QC_ATTRIBUTE] = {
|
||||
.name = ".attribute",
|
||||
.check_params = single_type_attribute,
|
||||
.resolve = resolve_attribute,
|
||||
.evaluate = evaluate_attribute,
|
||||
.compute = compute_attribute,
|
||||
},
|
||||
[QC_AT_FUNCTION] = {
|
||||
.name = "@function",
|
||||
.check_params = single_type,
|
||||
.resolve = resolve_function,
|
||||
.compute = compute_function,
|
||||
},
|
||||
[QC_AT_FIELD - QC_GENERIC] = {
|
||||
[QC_AT_FIELD] = {
|
||||
.name = "@field",
|
||||
.check_params = single_type,
|
||||
.resolve = resolve_field,
|
||||
.compute = compute_field,
|
||||
},
|
||||
[QC_AT_POINTER - QC_GENERIC] = {
|
||||
[QC_AT_POINTER] = {
|
||||
.name = "@pointer",
|
||||
.check_params = single_type,
|
||||
.resolve = resolve_pointer,
|
||||
.compute = compute_pointer,
|
||||
},
|
||||
[QC_AT_ARRAY - QC_GENERIC] = {
|
||||
[QC_AT_ARRAY] = {
|
||||
.name = "@array",
|
||||
.check_params = single_type_opt_int,
|
||||
.resolve = resolve_array,
|
||||
.compute = compute_type_array,
|
||||
},
|
||||
[QC_AT_BASE - QC_GENERIC] = {
|
||||
[QC_AT_BASE] = {
|
||||
.name = "@base",
|
||||
.check_params = single_type,
|
||||
.resolve = resolve_base,
|
||||
.compute = compute_base,
|
||||
},
|
||||
[QC_AT_WIDTH - QC_GENERIC] = {
|
||||
[QC_AT_WIDTH] = {
|
||||
.name = "@width",
|
||||
.check_params = single_type,
|
||||
.evaluate = evaluate_int_op,
|
||||
.compute = compute_width,
|
||||
},
|
||||
[QC_AT_VECTOR - QC_GENERIC] = {
|
||||
[QC_AT_VECTOR] = {
|
||||
.name = "@vector",
|
||||
.check_params = single_type_opt_int,
|
||||
.resolve = resolve_vector,
|
||||
.expand = expand_vector,
|
||||
.compute = compute_type_vector,
|
||||
},
|
||||
[QC_AT_ROWS - QC_GENERIC] = {
|
||||
[QC_AT_ROWS] = {
|
||||
.name = "@rows",
|
||||
.check_params = single_type,
|
||||
.evaluate = evaluate_int_op,
|
||||
.compute = compute_rows,
|
||||
},
|
||||
[QC_AT_COLS - QC_GENERIC] = {
|
||||
[QC_AT_COLS] = {
|
||||
.name = "@cols",
|
||||
.check_params = single_type,
|
||||
.evaluate = evaluate_int_op,
|
||||
.compute = compute_cols,
|
||||
},
|
||||
[QC_AT_MATRIX - QC_GENERIC] = {
|
||||
[QC_AT_MATRIX] = {
|
||||
.name = "@matrix",
|
||||
.check_params = single_type_opt_int_pair,
|
||||
.resolve = resolve_matrix,
|
||||
.expand = expand_matrix,
|
||||
.compute = compute_matrix,
|
||||
},
|
||||
[QC_AT_INT - QC_GENERIC] = {
|
||||
[QC_AT_INT] = {
|
||||
.name = "@int",
|
||||
.check_params = single_type,
|
||||
.resolve = resolve_int,
|
||||
.compute = compute_int,
|
||||
},
|
||||
[QC_AT_UINT - QC_GENERIC] = {
|
||||
[QC_AT_UINT] = {
|
||||
.name = "@uint",
|
||||
.check_params = single_type,
|
||||
.resolve = resolve_uint,
|
||||
.compute = compute_uint,
|
||||
},
|
||||
[QC_AT_BOOL - QC_GENERIC] = {
|
||||
[QC_AT_BOOL] = {
|
||||
.name = "@bool",
|
||||
.check_params = single_type,
|
||||
.resolve = resolve_bool,
|
||||
.compute = compute_bool,
|
||||
},
|
||||
[QC_AT_FLOAT - QC_GENERIC] = {
|
||||
[QC_AT_FLOAT] = {
|
||||
.name = "@float",
|
||||
.check_params = single_type,
|
||||
.resolve = resolve_float,
|
||||
|
@ -689,14 +797,13 @@ type_function (int op, const expr_t *params)
|
|||
int arg_count = list_count (¶ms->list);
|
||||
const expr_t *args[arg_count];
|
||||
list_scatter (¶ms->list, args);
|
||||
unsigned ind = op - QC_GENERIC;
|
||||
if (ind >= sizeof (type_funcs) / sizeof (type_funcs[0])
|
||||
|| !type_funcs[ind].name) {
|
||||
if ((unsigned) op >= sizeof (type_funcs) / sizeof (type_funcs[0])
|
||||
|| !type_funcs[op].name) {
|
||||
internal_error (params, "invalid type op: %d", op);
|
||||
}
|
||||
const char *msg = type_funcs[ind].check_params (arg_count, args);
|
||||
const char *msg = type_funcs[op].check_params (arg_count, args);
|
||||
if (msg) {
|
||||
return error (params, "%s for %s", msg, type_funcs[ind].name);
|
||||
return error (params, "%s for %s", msg, type_funcs[op].name);
|
||||
}
|
||||
return new_type_function (op, params);
|
||||
}
|
||||
|
@ -735,16 +842,15 @@ resolve_type (const expr_t *te, rua_ctx_t *ctx)
|
|||
//}
|
||||
return te->typ.type;
|
||||
}
|
||||
int op = te->typ.op;
|
||||
unsigned ind = op - QC_GENERIC;
|
||||
if (ind >= sizeof (type_funcs) / sizeof (type_funcs[0])
|
||||
|| !type_funcs[ind].name) {
|
||||
unsigned op = te->typ.op;
|
||||
if (op >= sizeof (type_funcs) / sizeof (type_funcs[0])
|
||||
|| !type_funcs[op].name) {
|
||||
internal_error (te, "invalid type op: %d", op);
|
||||
}
|
||||
int arg_count = list_count (&te->typ.params->list);
|
||||
const expr_t *args[arg_count];
|
||||
list_scatter (&te->typ.params->list, args);
|
||||
return type_funcs[ind].resolve (arg_count, args, ctx);
|
||||
return type_funcs[op].resolve (arg_count, args, ctx);
|
||||
}
|
||||
|
||||
const expr_t *
|
||||
|
@ -759,22 +865,21 @@ process_type (const expr_t *te, rua_ctx_t *ctx)
|
|||
}
|
||||
return new_type_expr (te->typ.type);
|
||||
}
|
||||
int op = te->typ.op;
|
||||
unsigned ind = op - QC_GENERIC;
|
||||
if (ind >= sizeof (type_funcs) / sizeof (type_funcs[0])
|
||||
|| !type_funcs[ind].name) {
|
||||
unsigned op = te->typ.op;
|
||||
if (op >= sizeof (type_funcs) / sizeof (type_funcs[0])
|
||||
|| !type_funcs[op].name) {
|
||||
internal_error (te, "invalid type op: %d", op);
|
||||
}
|
||||
int arg_count = list_count (&te->typ.params->list);
|
||||
const expr_t *args[arg_count];
|
||||
list_scatter (&te->typ.params->list, args);
|
||||
if (type_funcs[ind].resolve) {
|
||||
auto type = type_funcs[ind].resolve (arg_count, args, ctx);
|
||||
if (type_funcs[op].resolve) {
|
||||
auto type = type_funcs[op].resolve (arg_count, args, ctx);
|
||||
return new_type_expr (type);
|
||||
} else if (type_funcs[ind].evaluate) {
|
||||
return type_funcs[ind].evaluate (arg_count, args, ctx);
|
||||
} else if (type_funcs[op].evaluate) {
|
||||
return type_funcs[op].evaluate (arg_count, args, ctx);
|
||||
} else {
|
||||
internal_error (te, "invalid type op: %s", type_funcs[ind].name);
|
||||
internal_error (te, "invalid type op: %s", type_funcs[op].name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -794,19 +899,18 @@ expand_type (const expr_t *te, rua_ctx_t *ctx)
|
|||
types[1] = nullptr;
|
||||
return types;
|
||||
}
|
||||
int op = te->typ.op;
|
||||
unsigned ind = op - QC_GENERIC;
|
||||
if (ind >= sizeof (type_funcs) / sizeof (type_funcs[0])
|
||||
|| !type_funcs[ind].name) {
|
||||
unsigned op = te->typ.op;
|
||||
if (op >= sizeof (type_funcs) / sizeof (type_funcs[0])
|
||||
|| !type_funcs[op].name) {
|
||||
internal_error (te, "invalid type op: %d", op);
|
||||
}
|
||||
if (!type_funcs[ind].expand) {
|
||||
error (te, "cannot expand %s", type_funcs[ind].name);
|
||||
if (!type_funcs[op].expand) {
|
||||
error (te, "cannot expand %s", type_funcs[op].name);
|
||||
}
|
||||
int arg_count = list_count (&te->typ.params->list);
|
||||
const expr_t *args[arg_count];
|
||||
list_scatter (&te->typ.params->list, args);
|
||||
return type_funcs[ind].expand (arg_count, args, ctx);
|
||||
return type_funcs[op].expand (arg_count, args, ctx);
|
||||
}
|
||||
|
||||
const expr_t *
|
||||
|
@ -815,22 +919,35 @@ eval_type (const expr_t *te, rua_ctx_t *ctx)
|
|||
if (te->type != ex_type) {
|
||||
internal_error (te, "not a type expression");
|
||||
}
|
||||
int op = te->typ.op;
|
||||
unsigned ind = op - QC_GENERIC;
|
||||
if (ind >= sizeof (type_funcs) / sizeof (type_funcs[0])
|
||||
|| !type_funcs[ind].name) {
|
||||
unsigned op = te->typ.op;
|
||||
if (op >= sizeof (type_funcs) / sizeof (type_funcs[0])
|
||||
|| !type_funcs[op].name) {
|
||||
internal_error (te, "invalid type op: %d", op);
|
||||
}
|
||||
int arg_count = list_count (&te->typ.params->list);
|
||||
const expr_t *args[arg_count];
|
||||
list_scatter (&te->typ.params->list, args);
|
||||
return type_funcs[ind].evaluate (arg_count, args, ctx);
|
||||
return type_funcs[op].evaluate (arg_count, args, ctx);
|
||||
}
|
||||
|
||||
static def_t *
|
||||
compute_tmp (comp_ctx_t *ctx)
|
||||
{
|
||||
return new_def (0, &type_int, ctx->data, sc_static);
|
||||
return new_def (nullptr, &type_int, ctx->data, sc_static);
|
||||
}
|
||||
|
||||
static def_t *
|
||||
compute_sized_tmp (int size, comp_ctx_t *ctx)
|
||||
{
|
||||
auto def = new_def (nullptr, nullptr, ctx->data, sc_static);
|
||||
def->offset = defspace_alloc_loc (ctx->data, size);
|
||||
return def;
|
||||
}
|
||||
|
||||
static pr_string_t
|
||||
compute_str (const char *str, comp_ctx_t *ctx)
|
||||
{
|
||||
return strpool_addstr (ctx->strings, str);
|
||||
}
|
||||
|
||||
static def_t *
|
||||
|
@ -859,7 +976,6 @@ compute_val (const expr_t *arg, comp_ctx_t *ctx)
|
|||
D_INT (val) = expr_integral (arg);
|
||||
} else if (arg->type == ex_type) {
|
||||
int op = arg->typ.op;
|
||||
int ind = op - QC_GENERIC;
|
||||
if (arg->typ.type) {
|
||||
auto type = arg->typ.type;
|
||||
if (op == QC_AT_WIDTH) {
|
||||
|
@ -890,7 +1006,7 @@ compute_val (const expr_t *arg, comp_ctx_t *ctx)
|
|||
C (OP_STORE_A_1, ctx->args[0], nullptr, type);
|
||||
C (OP_CALL_B, ctx->funcs[op], nullptr, val);
|
||||
} else {
|
||||
error (arg, "invalid type passed to %s", type_funcs[ind].name);
|
||||
error (arg, "invalid type passed to %s", type_funcs[op].name);
|
||||
}
|
||||
}
|
||||
return val;
|
||||
|
@ -930,16 +1046,15 @@ compute_type (const expr_t *arg, comp_ctx_t *ctx)
|
|||
D_INT (val) = arg->typ.type->id;
|
||||
return val;
|
||||
}
|
||||
int op = arg->typ.op;
|
||||
unsigned ind = op - QC_GENERIC;
|
||||
if (ind >= sizeof (type_funcs) / sizeof (type_funcs[0])
|
||||
|| !type_funcs[ind].name) {
|
||||
unsigned op = arg->typ.op;
|
||||
if (op >= sizeof (type_funcs) / sizeof (type_funcs[0])
|
||||
|| !type_funcs[op].name) {
|
||||
internal_error (arg, "invalid type op: %d", op);
|
||||
}
|
||||
int arg_count = list_count (&arg->typ.params->list);
|
||||
const expr_t *args[arg_count];
|
||||
list_scatter (&arg->typ.params->list, args);
|
||||
return type_funcs[ind].compute (arg_count, args, ctx);
|
||||
return type_funcs[op].compute (arg_count, args, ctx);
|
||||
}
|
||||
|
||||
typeeval_t *
|
||||
|
@ -947,11 +1062,13 @@ build_type_function (const expr_t *te, int num_types, gentype_t *types)
|
|||
{
|
||||
auto code = codespace_new ();
|
||||
auto data = defspace_new (ds_backed);
|
||||
auto strings = strpool_new ();
|
||||
comp_ctx_t *ctx = &(comp_ctx_t) {
|
||||
.types = types,
|
||||
.num_types = num_types,
|
||||
.code = code,
|
||||
.data = data,
|
||||
.strings = strings,
|
||||
};
|
||||
compute_tmp (ctx);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
@ -971,13 +1088,17 @@ build_type_function (const expr_t *te, int num_types, gentype_t *types)
|
|||
*func = (typeeval_t) {
|
||||
.code = code->code,
|
||||
.data = data->data,
|
||||
.strings = strings->strings,
|
||||
.code_size = code->size,
|
||||
.data_size = data->size,
|
||||
.string_size = strings->size,
|
||||
};
|
||||
}
|
||||
code->code = nullptr;
|
||||
data->data = nullptr;
|
||||
strings->strings = nullptr;
|
||||
codespace_delete (code);
|
||||
defspace_delete (data);
|
||||
strpool_delete (strings);
|
||||
return func;
|
||||
}
|
||||
|
|
|
@ -284,6 +284,20 @@ type_spec (const type_t *type)
|
|||
return spec;
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
type_attribute (specifier_t spec, const attribute_t *attrib)
|
||||
{
|
||||
auto type_expr = spec.type_expr;
|
||||
if (!type_expr) {
|
||||
type_expr = new_type_expr (spec.type);
|
||||
}
|
||||
auto params = new_list_expr (type_expr);
|
||||
auto attr = new_type_expr (nullptr);
|
||||
attr->typ.attrib = attrib;
|
||||
expr_append_expr (params, attr);
|
||||
return new_type_function (QC_ATTRIBUTE, params);
|
||||
}
|
||||
|
||||
static specifier_t
|
||||
storage_spec (storage_class_t storage)
|
||||
{
|
||||
|
@ -524,17 +538,15 @@ make_param (specifier_t spec, rua_ctx_t *ctx)
|
|||
spec.storage = sc_param;
|
||||
}
|
||||
|
||||
spec = spec_process (spec, ctx);
|
||||
|
||||
param_t *param;
|
||||
if (spec.type_expr) {
|
||||
param = new_generic_param (spec.type_expr, spec.sym->name);
|
||||
} else if (spec.sym) {
|
||||
spec = default_type (spec, spec.sym);
|
||||
spec = spec_process (spec, ctx);
|
||||
spec.type = find_type (append_type (spec.sym->type, spec.type));
|
||||
param = new_param (nullptr, spec.type, spec.sym->name);
|
||||
} else {
|
||||
spec = default_type (spec, spec.sym);
|
||||
spec = spec_process (spec, ctx);
|
||||
param = new_param (nullptr, spec.type, nullptr);
|
||||
}
|
||||
if (spec.is_const) {
|
||||
|
@ -1146,15 +1158,10 @@ typespec_reserved
|
|||
|
||||
typespec_nonreserved
|
||||
: TYPE_NAME %prec LOW
|
||||
| TYPE_NAME '.' attribute
|
||||
| TYPE_NAME[spec] '.' attribute
|
||||
{
|
||||
if (!is_algebra ($1.type)) {
|
||||
error (0, "%s does not have any subtypes",
|
||||
get_type_string ($1.type));
|
||||
$$ = $1;
|
||||
} else {
|
||||
$$ = type_spec (algebra_subtype ($1.type, $3));
|
||||
}
|
||||
auto te = type_attribute ($spec, $attribute);
|
||||
$$ = (specifier_t) { .type_expr = te };
|
||||
}
|
||||
| OBJECT_NAME protocolrefs
|
||||
{
|
||||
|
@ -1356,6 +1363,10 @@ type_ref
|
|||
$$ = new_type_expr ($1.type);
|
||||
}
|
||||
}
|
||||
| TYPE_NAME[spec] '.' attribute
|
||||
{
|
||||
$$ = type_attribute ($spec, $attribute);
|
||||
}
|
||||
;
|
||||
|
||||
type_ref_spec
|
||||
|
@ -2886,6 +2897,12 @@ obj_string
|
|||
|
||||
%%
|
||||
|
||||
static void __attribute__((used))
|
||||
qc_dump_stack(yypstate *yyps)
|
||||
{
|
||||
yy_stack_print (yyps->yyss, yyps->yyssp);
|
||||
}
|
||||
|
||||
// preprocessor directives in ruamoko and quakec
|
||||
static directive_t rua_directives[] = {
|
||||
{"include", PRE_INCLUDE},
|
||||
|
|
|
@ -1040,6 +1040,7 @@ alias_type (const type_t *type, const type_t *alias_chain, const char *name)
|
|||
if (name) {
|
||||
alias->name = save_string (name);
|
||||
}
|
||||
alias->attrib = type->attrib;
|
||||
return alias;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue