[qfcc] Give direct access to algebra subtypes

Currently via only the group mask (which is really horrible to work
with: requires too much knowledge of implementation details, but does
the job for testing), but it got some basics working.
This commit is contained in:
Bill Currie 2023-08-25 22:06:44 +09:00
parent d2e134cc22
commit 60ce4ba8fb
4 changed files with 52 additions and 6 deletions

View file

@ -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);

View file

@ -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)
{

View file

@ -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); }
;

View file

@ -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 = vp2;
#if 0
@ -46,5 +47,6 @@ main (void)
// pga2 = p + (1 + p)l1;
pga2 = (l1p)*l1;
}
printf ("%q\n", plane);
return 0; // to survive and prevail :)
}