mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-25 22:01:33 +00:00
[qfcc] Implement field access for multi-vector expressions
Of course as an r-value (I think), but it makes getting only the desired part of a geometric algebra expression much nicer.
This commit is contained in:
parent
97624b84aa
commit
b35f4c82a4
4 changed files with 70 additions and 11 deletions
|
@ -579,6 +579,8 @@ expr_t *new_zero_expr (struct type_s *type);
|
||||||
*/
|
*/
|
||||||
expr_t *new_name_expr (const char *name);
|
expr_t *new_name_expr (const char *name);
|
||||||
|
|
||||||
|
struct symbol_s *get_name (expr_t *e) __attribute__((pure));
|
||||||
|
|
||||||
/** Create a new string constant expression node.
|
/** Create a new string constant expression node.
|
||||||
|
|
||||||
\param string_val The string constant being represented.
|
\param string_val The string constant being represented.
|
||||||
|
|
|
@ -490,7 +490,10 @@ algebra_mvec_type (algebra_t *algebra, pr_uint_t group_mask)
|
||||||
algebra->mvec_types[group_mask] = new_type ();
|
algebra->mvec_types[group_mask] = new_type ();
|
||||||
*algebra->mvec_types[group_mask] = (type_t) {
|
*algebra->mvec_types[group_mask] = (type_t) {
|
||||||
.type = algebra->type->type,
|
.type = algebra->type->type,
|
||||||
.name = "basis group",
|
.name = save_string (va (0, "algebra(%s(%d,%d,%d):%04x)",
|
||||||
|
algebra->type->name,
|
||||||
|
algebra->plus, algebra->minus,
|
||||||
|
algebra->zero, group_mask)),
|
||||||
.alignment = algebra_alignment (algebra->type, components),
|
.alignment = algebra_alignment (algebra->type, components),
|
||||||
.width = components,
|
.width = components,
|
||||||
.meta = ty_algebra,
|
.meta = ty_algebra,
|
||||||
|
|
|
@ -1463,23 +1463,30 @@ prepend_expr (expr_t *block, expr_t *e)
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
symbol_t *
|
||||||
|
get_name (expr_t *e)
|
||||||
|
{
|
||||||
|
if (e->type == ex_symbol) {
|
||||||
|
return e->e.symbol;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
symbol_t *
|
symbol_t *
|
||||||
get_struct_field (const type_t *t1, expr_t *e1, expr_t *e2)
|
get_struct_field (const type_t *t1, expr_t *e1, expr_t *e2)
|
||||||
{
|
{
|
||||||
symtab_t *strct = 0;
|
symtab_t *strct = t1->t.symtab;
|
||||||
if (is_algebra (t1)) {
|
symbol_t *sym = get_name (e2);
|
||||||
error (e1, "dereferencing pointer to incomplete type");
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
strct = t1->t.symtab;
|
|
||||||
}
|
|
||||||
symbol_t *sym = e2->e.symbol;//FIXME need to check
|
|
||||||
symbol_t *field;
|
symbol_t *field;
|
||||||
|
|
||||||
if (!strct) {
|
if (!strct) {
|
||||||
error (e1, "dereferencing pointer to incomplete type");
|
error (e1, "dereferencing pointer to incomplete type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (!sym) {
|
||||||
|
error (e2, "field reference is not a name");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
field = symtab_lookup (strct, sym->name);
|
field = symtab_lookup (strct, sym->name);
|
||||||
if (!field && !is_entity(t1)) {
|
if (!field && !is_entity(t1)) {
|
||||||
const char *name = t1->name;
|
const char *name = t1->name;
|
||||||
|
@ -2295,7 +2302,7 @@ function_expr (expr_t *fexpr, expr_t *params)
|
||||||
expr_t *
|
expr_t *
|
||||||
branch_expr (int op, expr_t *test, expr_t *label)
|
branch_expr (int op, expr_t *test, expr_t *label)
|
||||||
{
|
{
|
||||||
// need to translated op due to precedence rules dictating the layout
|
// need to translate op due to precedence rules dictating the layout
|
||||||
// of the token ids
|
// of the token ids
|
||||||
static pr_branch_e branch_type [] = {
|
static pr_branch_e branch_type [] = {
|
||||||
pr_branch_eq,
|
pr_branch_eq,
|
||||||
|
|
|
@ -59,6 +59,21 @@ get_group (type_t *type, algebra_t *algebra)
|
||||||
return BITOP_LOG2 (group_mask);
|
return BITOP_LOG2 (group_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static pr_uint_t
|
||||||
|
get_group_mask (type_t *type, algebra_t *algebra)
|
||||||
|
{
|
||||||
|
auto layout = &algebra->layout;
|
||||||
|
if (!is_algebra (type)) {
|
||||||
|
int group = layout->group_map[layout->mask_map[0]][0];
|
||||||
|
return 1u << group;
|
||||||
|
} else {
|
||||||
|
if (type->type == ev_invalid) {
|
||||||
|
return (1 << algebra->layout.count) - 1;
|
||||||
|
}
|
||||||
|
return type->t.multivec->group_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool __attribute__((const))
|
static bool __attribute__((const))
|
||||||
is_neg (const expr_t *e)
|
is_neg (const expr_t *e)
|
||||||
{
|
{
|
||||||
|
@ -2268,9 +2283,41 @@ algebra_field_expr (expr_t *mvec, expr_t *field_name)
|
||||||
return new_offset_alias_expr (field->type, mvec, field->s.offset);
|
return new_offset_alias_expr (field->type, mvec, field->s.offset);
|
||||||
}
|
}
|
||||||
if (mvec->type == ex_multivec) {
|
if (mvec->type == ex_multivec) {
|
||||||
internal_error (mvec, "not implemented");
|
auto field_sym = get_name (field_name);
|
||||||
|
if (!field_sym) {
|
||||||
|
return error (field_name, "multi-vector reference is not a name");
|
||||||
|
}
|
||||||
|
auto multivec = mvec_type->t.multivec;
|
||||||
|
auto mvec_struct = multivec->mvec_sym->type->t.symtab;
|
||||||
|
auto field = symtab_lookup (mvec_struct, field_sym->name);
|
||||||
|
if (!field) {
|
||||||
|
mvec_struct = algebra->mvec_sym->type->t.symtab;
|
||||||
|
field = symtab_lookup (mvec_struct, field_sym->name);
|
||||||
|
if (field) {
|
||||||
|
debug (field_name, "'%s' not in sub-type '%s' of '%s', "
|
||||||
|
"returning zero of type '%s'", field_sym->name,
|
||||||
|
mvec_type->name, algebra->mvec_sym->type->name,
|
||||||
|
mvec_type->name);
|
||||||
|
return new_zero_expr (field->type);
|
||||||
|
}
|
||||||
|
return error (field_name, "'%s' has no member named '%s'",
|
||||||
|
mvec_type->name, field_sym->name);
|
||||||
|
}
|
||||||
|
auto layout = &algebra->layout;
|
||||||
|
expr_t *a[layout->count] = {};
|
||||||
|
mvec_scatter (a, mvec_expr (mvec, algebra), algebra);
|
||||||
|
pr_uint_t group_mask = get_group_mask (field->type, algebra);
|
||||||
|
for (int i = 0; i < layout->count; i++) {
|
||||||
|
if (!(group_mask & (1u << i))) {
|
||||||
|
a[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mvec_gather (a, algebra);
|
||||||
} else {
|
} else {
|
||||||
auto multivec = mvec_type->t.multivec;
|
auto multivec = mvec_type->t.multivec;
|
||||||
|
if (!multivec->mvec_sym) {
|
||||||
|
return error (mvec, "'%s' not a multi-vector", mvec_type->name);
|
||||||
|
}
|
||||||
auto mvec_struct = multivec->mvec_sym->type;
|
auto mvec_struct = multivec->mvec_sym->type;
|
||||||
auto field = get_struct_field (mvec_struct, mvec, field_name);
|
auto field = get_struct_field (mvec_struct, mvec, field_name);
|
||||||
if (!field) {
|
if (!field) {
|
||||||
|
|
Loading…
Reference in a new issue