diff --git a/tools/qfcc/include/algebra.h b/tools/qfcc/include/algebra.h index c87221eaf..ea67fcefc 100644 --- a/tools/qfcc/include/algebra.h +++ b/tools/qfcc/include/algebra.h @@ -82,8 +82,10 @@ typedef struct multivector_s { } multivector_t; struct expr_s; +struct attribute_s; bool is_algebra (const struct type_s *type) __attribute__((pure)); struct type_s *algebra_type (struct type_s *type, struct expr_s *params); +struct type_s *algebra_subtype (struct type_s *type, struct attribute_s *attr); struct type_s *algebra_mvec_type (algebra_t *algebra, pr_uint_t group_mask); struct ex_value_s *algebra_blade_value (algebra_t *alg, const char *name); struct symtab_s *algebra_scope (struct type_s *type, struct symtab_s *curscope); diff --git a/tools/qfcc/source/algebra.c b/tools/qfcc/source/algebra.c index 84da21efa..d03ca4fbe 100644 --- a/tools/qfcc/source/algebra.c +++ b/tools/qfcc/source/algebra.c @@ -37,6 +37,7 @@ #include "QF/va.h" #include "tools/qfcc/include/algebra.h" +#include "tools/qfcc/include/attribute.h" #include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/expr.h" #include "tools/qfcc/include/strpool.h" @@ -412,6 +413,34 @@ algebra_type (type_t *type, expr_t *params) return find_type (t); } +type_t * +algebra_subtype (type_t *type, attribute_t *attr) +{ + if (!is_algebra (type)) { + internal_error (0, "unexpected type"); + } + auto algebra = algebra_get (type); + if (strcmp (attr->name, "group_mask") == 0) { + if (!attr->params || attr->params->next) { + error (0, "incorrect number of parameters to 'group_mask'"); + return type; + } + auto param = attr->params; + if (!is_integral_val (param)) { + error (0, "'group_mask' parameter must be an integer constant"); + return type; + } + pr_uint_t mask = expr_integral (param); + if (!mask || mask > ((1u << algebra->layout.count) - 1)) { + error (0, "invalid group_mask"); + return type; + } + return algebra_mvec_type (algebra, mask); + } + return type; +} + + type_t * algebra_mvec_type (algebra_t *algebra, pr_uint_t group_mask) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 75951cf37..b5b62a583 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -894,7 +894,11 @@ typespec typespec_reserved : TYPE_SPEC - | algebra_specifier + | algebra_specifier %prec LOW + | algebra_specifier '.' attribute + { + $$ = make_spec (algebra_subtype ($1.type, $3), 0, 0, 0); + } | enum_specifier | struct_specifier // NOTE: fields don't parse the way they should. This is not a problem @@ -907,9 +911,18 @@ typespec_reserved } ; - typespec_nonreserved - : TYPE_NAME + : TYPE_NAME %prec LOW + | TYPE_NAME '.' attribute + { + if (!is_algebra ($1.type)) { + error (0, "%s does not have any subtypes", + get_type_string ($1.type)); + $$ = $1; + } else { + $$ = make_spec (algebra_subtype ($1.type, $3), 0, 0, 0); + } + } | OBJECT_NAME protocolrefs { if ($2) { @@ -1015,7 +1028,7 @@ attribute_list ; attribute - : NAME { $$ = new_attribute ($1->name, 0); } + : NAME %prec LOW { $$ = new_attribute ($1->name, 0); } | NAME '(' expr_list ')' { $$ = new_attribute ($1->name, $3); } ; diff --git a/tools/qfcc/test/algtypes.r b/tools/qfcc/test/algtypes.r index d227e006d..4c4f60572 100644 --- a/tools/qfcc/test/algtypes.r +++ b/tools/qfcc/test/algtypes.r @@ -1,3 +1,4 @@ +#include "test-harness.h" int foo[128]; @algebra(float) pgaf1; //@algebra(double) pgad1; @@ -13,16 +14,16 @@ typedef @algebra(float(4,1)) CGA; typedef @algebra(double(2,0,1)) PGA2; PGA2 pga2; -float sin(float x) = #0; - int main (void) { + PGA.group_mask (0x1) plane; @algebra (PGA) { auto p1 = 3*e1 + e2 - e3 + e0; auto p2 = e1 + 3*e2 + e3 - e0; auto v = 4*(e1 + e032 + e123); pgaf1 = p1 + v * p2; + plane = p1; // pgaf1 = (p1 + v)∧p2; // pgaf1 = v • p2; #if 0 @@ -46,5 +47,6 @@ main (void) // pga2 = p + (1 + p)∧l1; pga2 = (l1 • p)*l1; } + printf ("%q\n", plane); return 0; // to survive and prevail :) }