mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-08 10:21:40 +00:00
[qfcc] Expand @vector and @matrix type expressions
With this, genFType and genDType functions are now treated separately and expanding to all components (single row or column matrices are not supported (at this stage, anyway) for generic parameters).
This commit is contained in:
parent
58bf1ee64e
commit
66866f79b6
3 changed files with 106 additions and 11 deletions
|
@ -858,6 +858,7 @@ expr_t *new_type_expr (const type_t *type);
|
|||
const expr_t *type_function (int op, const expr_t *params);
|
||||
symbol_t *type_parameter (symbol_t *sym, const expr_t *type);
|
||||
const type_t *resolve_type (const expr_t *te);
|
||||
const type_t **expand_type (const expr_t *te);
|
||||
const expr_t *evaluate_type (const expr_t *te);
|
||||
|
||||
/** Convert a name to an expression of the appropriate type.
|
||||
|
|
|
@ -39,6 +39,7 @@ typedef struct {
|
|||
const char *name;
|
||||
const char *(*check_params) (int arg_count, const expr_t **args);
|
||||
const type_t *(*resolve) (int arg_count, const expr_t **args);
|
||||
const type_t **(*expand) (int arg_count, const expr_t **args);
|
||||
const expr_t *(*evaluate) (int arg_count, const expr_t **args);
|
||||
} type_func_t;
|
||||
|
||||
|
@ -323,6 +324,75 @@ resolve_float (int arg_count, const expr_t **args)
|
|||
return type;
|
||||
}
|
||||
|
||||
static const type_t **
|
||||
expand_vector (int arg_count, const expr_t **args)
|
||||
{
|
||||
const type_t *base = resolve_type (args[0]);
|
||||
if (!is_bool (base) && !is_scalar (base)) {
|
||||
error (args[0], "invalid vector component type");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (arg_count == 2) {
|
||||
auto comps_expr = evaluate_int (args[1]);
|
||||
if (is_error (comps_expr)) {
|
||||
return nullptr;
|
||||
}
|
||||
int comps = expr_integral (comps_expr);
|
||||
if (comps < 1 || comps > 4) {
|
||||
error (args[1], "invalid vector component count");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const type_t **types = malloc (sizeof(type_t[2]));
|
||||
types[0] = vector_type (base, comps);
|
||||
types[1] = nullptr;
|
||||
return types;
|
||||
} else {
|
||||
const type_t **types = malloc (sizeof(type_t *[5]));
|
||||
for (int i = 0; i < 4; i++) {
|
||||
types[i] = vector_type (base, i + 1);
|
||||
}
|
||||
types[4] = nullptr;
|
||||
return types;
|
||||
}
|
||||
}
|
||||
|
||||
static const type_t **
|
||||
expand_matrix (int arg_count, const expr_t **args)
|
||||
{
|
||||
const type_t *base = resolve_type (args[0]);
|
||||
if (!is_scalar (base)) {
|
||||
error (args[0], "invalid matrix component type");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// @matrix doesn't include vectors for generic parameters
|
||||
if (arg_count == 3) {
|
||||
auto rows_expr = evaluate_int (args[2]);
|
||||
auto cols_expr = evaluate_int (args[1]);
|
||||
if (is_error (rows_expr) || is_error (cols_expr)) {
|
||||
return nullptr;
|
||||
}
|
||||
int rows = expr_integral (rows_expr);
|
||||
int cols = expr_integral (cols_expr);
|
||||
|
||||
const type_t **types = malloc (sizeof(type_t *[2]));
|
||||
types[0] = matrix_type (base, cols, rows);
|
||||
types[1] = nullptr;
|
||||
return types;
|
||||
} else {
|
||||
const type_t **types = malloc (sizeof(type_t *[3*3 + 1]));
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
types[i*3 + j] = matrix_type (base, i + 2, j + 2);
|
||||
}
|
||||
}
|
||||
types[3*3] = nullptr;
|
||||
return types;
|
||||
}
|
||||
}
|
||||
|
||||
static type_func_t type_funcs[] = {
|
||||
[QC_AT_FUNCTION - QC_GENERIC] = {
|
||||
.name = "@function",
|
||||
|
@ -358,6 +428,7 @@ static type_func_t type_funcs[] = {
|
|||
.name = "@vector",
|
||||
.check_params = single_type_opt_int,
|
||||
.resolve = resolve_vector,
|
||||
.expand = expand_vector,
|
||||
},
|
||||
[QC_AT_ROWS - QC_GENERIC] = {
|
||||
.name = "@rows",
|
||||
|
@ -373,6 +444,7 @@ static type_func_t type_funcs[] = {
|
|||
.name = "@matrix",
|
||||
.check_params = single_type_opt_int_pair,
|
||||
.resolve = resolve_matrix,
|
||||
.expand = expand_matrix,
|
||||
},
|
||||
[QC_AT_INT - QC_GENERIC] = {
|
||||
.name = "@int",
|
||||
|
@ -456,6 +528,37 @@ resolve_type (const expr_t *te)
|
|||
return type_funcs[ind].resolve (arg_count, args);
|
||||
}
|
||||
|
||||
const type_t **
|
||||
expand_type (const expr_t *te)
|
||||
{
|
||||
if (te->type != ex_type) {
|
||||
internal_error (te, "not a type expression");
|
||||
}
|
||||
if (!te->typ.op) {
|
||||
if (!te->typ.type) {
|
||||
internal_error (te, "no type in reference");
|
||||
}
|
||||
//FIXME is this correct?
|
||||
const type_t **types = malloc (sizeof(type_t *[2]));
|
||||
types[0] = te->typ.type;
|
||||
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) {
|
||||
internal_error (te, "invalid type op: %d", op);
|
||||
}
|
||||
if (!type_funcs[ind].expand) {
|
||||
error (te, "cannot expand %s", type_funcs[ind].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);
|
||||
}
|
||||
|
||||
const expr_t *
|
||||
evaluate_type (const expr_t *te)
|
||||
{
|
||||
|
|
|
@ -190,26 +190,17 @@ add_generic_function (genfunc_t *genfunc)
|
|||
}
|
||||
}
|
||||
|
||||
static const type_t *
|
||||
compute_type ()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static gentype_compute_f
|
||||
check_compute_type (const expr_t *expr)
|
||||
{
|
||||
if (expr->type != ex_type) {
|
||||
return nullptr;
|
||||
}
|
||||
return compute_type;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const type_t **
|
||||
valid_type_list (const expr_t *expr)
|
||||
{
|
||||
if (expr->type != ex_list) {
|
||||
return nullptr;
|
||||
return expand_type (expr);
|
||||
}
|
||||
int count = list_count (&expr->list);
|
||||
const expr_t *type_refs[count];
|
||||
|
|
Loading…
Reference in a new issue