[qfcc] Use non-invasive lists for most expressions

This covers attribute params, vector, state, and comma expressions. Just
function args to go, I think.
This commit is contained in:
Bill Currie 2023-09-24 15:04:25 +09:00
parent cc67e69923
commit 81b544c362
10 changed files with 194 additions and 87 deletions

View file

@ -38,6 +38,6 @@ typedef struct attribute_s {
} attribute_t; } attribute_t;
struct expr_s; struct expr_s;
attribute_t *new_attribute(const char *name, struct expr_s *value); attribute_t *new_attribute(const char *name, struct expr_s *params);
#endif//attribute_h #endif//attribute_h

View file

@ -382,6 +382,10 @@ ex_listitem_t *new_listitem (expr_t *e);
int list_count (ex_list_t *list) __attribute__((pure)); int list_count (ex_list_t *list) __attribute__((pure));
void list_scatter (ex_list_t *list, expr_t **exprs); void list_scatter (ex_list_t *list, expr_t **exprs);
void list_gather (ex_list_t *dst, expr_t **exprs, int count); void list_gather (ex_list_t *dst, expr_t **exprs, int count);
expr_t *new_list_expr (expr_t *first);
expr_t *list_append_expr (expr_t *list, expr_t *expr);
expr_t *list_prepend_expr (expr_t *list, expr_t *expr);
expr_t *list_prepend_list (expr_t *list, ex_list_t *prepend);
/** Create a new expression node. /** Create a new expression node.
@ -474,14 +478,12 @@ expr_t *new_block_expr (void);
/** Create a new statement block expression node from an expression list /** Create a new statement block expression node from an expression list
The returned block holds the expression list in reverse order. This makes \param list The expression list to convert to an expression block.
it easy to build the list in a parser. \param set_result If true, the block's result will be set to the last
expression in the list.
\param expr_list The expression list to convert to an expression block.
Note that the evaluation order will be reversed.
\return The new block expression (::ex_block_t) node. \return The new block expression (::ex_block_t) node.
*/ */
expr_t *build_block_expr (expr_t *expr_list); expr_t *build_block_expr (expr_t *list, bool set_result);
designator_t *new_designator (expr_t *field, expr_t *index); designator_t *new_designator (expr_t *field, expr_t *index);
element_t *new_element (expr_t *expr, designator_t *designator); element_t *new_element (expr_t *expr, designator_t *designator);

View file

@ -343,10 +343,18 @@ algebra_type (type_t *type, expr_t *params)
error (0, "algebra type must be float or double"); error (0, "algebra type must be float or double");
return type_default; return type_default;
} }
params = reverse_expr_list (params); int param_count = params ? list_count (&params->list) : 0;
auto plus = params; if (param_count > 3) {
auto minus = plus ? plus->next : 0; error (params, "too many arguments in signature");
auto zero = minus ? minus->next : 0; return type_default;
}
expr_t *param_exprs[3] = {};
if (params) {
list_scatter (&params->list, param_exprs);
}
auto plus = param_exprs[0];
auto minus = param_exprs[1];
auto zero = param_exprs[2];
expr_t *err = 0; expr_t *err = 0;
if ((plus && !is_integral_val (err = plus)) if ((plus && !is_integral_val (err = plus))
@ -410,11 +418,11 @@ algebra_subtype (type_t *type, attribute_t *attr)
} }
auto algebra = algebra_get (type); auto algebra = algebra_get (type);
if (strcmp (attr->name, "group_mask") == 0) { if (strcmp (attr->name, "group_mask") == 0) {
if (!attr->params || attr->params->next) { if (!attr->params || attr->params->list.head->next) {
error (0, "incorrect number of parameters to 'group_mask'"); error (0, "incorrect number of parameters to 'group_mask'");
return type; return type;
} }
auto param = attr->params; auto param = attr->params->list.head->expr;
if (!is_integral_val (param)) { if (!is_integral_val (param)) {
error (0, "'group_mask' parameter must be an integer constant"); error (0, "'group_mask' parameter must be an integer constant");
return type; return type;

View file

@ -40,18 +40,23 @@
ALLOC_STATE (attribute_t, attributes); ALLOC_STATE (attribute_t, attributes);
attribute_t *new_attribute(const char *name, expr_t *value) attribute_t *new_attribute(const char *name, expr_t *params)
{ {
for (auto v = value; v; v = v->next) { if (params && params->type != ex_list) {
if (v->type != ex_value) { internal_error (params, "attribute params not a list");
error (value, "not a literal constant"); }
if (params) {
for (auto p = params->list.head; p; p = p->next) {
if (p->expr->type != ex_value) {
error (p->expr, "not a literal constant");
return 0; return 0;
} }
} }
}
attribute_t *attr; attribute_t *attr;
ALLOC (16384, attribute_t, attributes, attr); ALLOC (16384, attribute_t, attributes, attr);
attr->name = save_string (name); attr->name = save_string (name);
attr->params = value ? reverse_expr_list (value) : 0; attr->params = params;
return attr; return attr;
} }

View file

@ -227,18 +227,22 @@ print_block (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
list_scatter (&e->block.list, exprs); list_scatter (&e->block.list, exprs);
exprs[num_exprs] = 0; exprs[num_exprs] = 0;
int colspan = num_exprs ? num_exprs : 1;
dasprintf (dstr, "%*se_%p [shape=none,label=<\n", indent, "", e); dasprintf (dstr, "%*se_%p [shape=none,label=<\n", indent, "", e);
dasprintf (dstr, "%*s<table border=\"0\" cellborder=\"1\" " dasprintf (dstr, "%*s<table border=\"0\" cellborder=\"1\" "
"cellspacing=\"0\">\n", indent + 2, ""); "cellspacing=\"0\">\n", indent + 2, "");
dasprintf (dstr, "%*s<tr><td colspan=\"%d\">&lt;block&gt;(%d)%s</td>" dasprintf (dstr, "%*s<tr><td colspan=\"%d\">&lt;block&gt;(%d)%s</td>"
"</tr>\n", indent + 4, "", num_exprs, e->line, "</tr>\n", indent + 4, "", colspan, e->line,
e->block.is_call ? "c" : ""); e->block.is_call ? "c" : "");
if (e->block.result) if (e->block.result)
dasprintf (dstr, "%*s<tr><td colspan=\"%d\" port=\"result\">=</td>" dasprintf (dstr, "%*s<tr><td colspan=\"%d\" port=\"result\">=</td>"
"</tr>\n", indent + 4, "", num_exprs); "</tr>\n", indent + 4, "", colspan);
if (num_exprs) {
dasprintf (dstr, "%*s<tr>\n", indent + 4, ""); dasprintf (dstr, "%*s<tr>\n", indent + 4, "");
for (int i = 0; i < num_exprs; i++) { for (int i = 0; i < num_exprs; i++) {
dasprintf (dstr, "%*s<td>%d</td>\n", indent + 8, "", exprs[i]->line); dasprintf (dstr, "%*s<td>%d</td>\n", indent + 8, "",
exprs[i]->line);
} }
dasprintf (dstr, "%*s</tr>\n", indent + 4, ""); dasprintf (dstr, "%*s</tr>\n", indent + 4, "");
dasprintf (dstr, "%*s<tr>\n", indent + 4, ""); dasprintf (dstr, "%*s<tr>\n", indent + 4, "");
@ -247,6 +251,7 @@ print_block (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
i, expr_names[exprs[i]->type]); i, expr_names[exprs[i]->type]);
} }
dasprintf (dstr, "%*s</tr>\n", indent + 4, ""); dasprintf (dstr, "%*s</tr>\n", indent + 4, "");
}
dasprintf (dstr, "%*s</table>\n", indent + 2, ""); dasprintf (dstr, "%*s</table>\n", indent + 2, "");
dasprintf (dstr, "%*s>];\n", indent, ""); dasprintf (dstr, "%*s>];\n", indent, "");
@ -262,6 +267,47 @@ print_block (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
} }
} }
static void
print_list (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
{
int indent = level * 2 + 2;
int num_exprs = list_count (&e->list);
expr_t *exprs[num_exprs + 1];
list_scatter (&e->list, exprs);
exprs[num_exprs] = 0;
int colspan = num_exprs ? num_exprs : 1;
dasprintf (dstr, "%*se_%p [shape=none,label=<\n", indent, "", e);
dasprintf (dstr, "%*s<table border=\"0\" cellborder=\"1\" "
"cellspacing=\"0\">\n", indent + 2, "");
dasprintf (dstr, "%*s<tr><td colspan=\"%d\">&lt;list&gt;(%d)</td>"
"</tr>\n", indent + 4, "", colspan, e->line);
if (num_exprs) {
dasprintf (dstr, "%*s<tr>\n", indent + 4, "");
for (int i = 0; i < num_exprs; i++) {
dasprintf (dstr, "%*s<td>%d</td>\n", indent + 8, "",
exprs[i]->line);
}
dasprintf (dstr, "%*s</tr>\n", indent + 4, "");
dasprintf (dstr, "%*s<tr>\n", indent + 4, "");
for (int i = 0; i < num_exprs; i++) {
dasprintf (dstr, "%*s<td port=\"b%d\">%s</td>\n", indent + 8, "",
i, expr_names[exprs[i]->type]);
}
dasprintf (dstr, "%*s</tr>\n", indent + 4, "");
}
dasprintf (dstr, "%*s</table>\n", indent + 2, "");
dasprintf (dstr, "%*s>];\n", indent, "");
for (int i = 0; i < num_exprs; i++) {
_print_expr (dstr, exprs[i], level + 1, id, exprs[i + 1]);
dasprintf (dstr, "%*se_%p:b%d -> e_%p;\n", indent, "", e,
i, exprs[i]);
}
}
static void static void
print_subexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) print_subexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
{ {
@ -676,6 +722,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
[ex_swizzle] = print_swizzle, [ex_swizzle] = print_swizzle,
[ex_extend] = print_extend, [ex_extend] = print_extend,
[ex_multivec] = print_multivec, [ex_multivec] = print_multivec,
[ex_list] = print_list,
}; };
int indent = level * 2 + 2; int indent = level * 2 + 2;

View file

@ -273,6 +273,53 @@ new_listitem (expr_t *e)
return li; return li;
} }
expr_t *
list_append_expr (expr_t *list, expr_t *expr)
{
auto li = new_listitem (expr);
*list->list.tail = li;
list->list.tail = &li->next;
return list;
}
expr_t *
list_prepend_expr (expr_t *list, expr_t *expr)
{
auto li = new_listitem (expr);
li->next = list->list.head;
list->list.head = li;
if (list->list.tail == &list->list.head) {
list->list.tail = &li->next;
}
return list;
}
expr_t *
list_prepend_list (expr_t *list, ex_list_t *prepend)
{
if (!list->list.head) {
list->list.tail = prepend->tail;
}
*prepend->tail = list->list.head;
list->list.head = prepend->head;
return list;
}
expr_t *
new_list_expr (expr_t *first)
{
auto list = new_expr ();
list->type = ex_list;
list->list.head = 0;
list->list.tail = &list->list.head;
if (first) {
list_append_expr (list, first);
}
return list;
}
int int
list_count (ex_list_t *list) list_count (ex_list_t *list)
{ {
@ -638,15 +685,18 @@ new_binary_expr (int op, expr_t *e1, expr_t *e2)
} }
expr_t * expr_t *
build_block_expr (expr_t *expr_list) build_block_expr (expr_t *list, bool set_result)
{ {
if (list->type != ex_list) {
return list;
}
expr_t *b = new_block_expr (); expr_t *b = new_block_expr ();
while (expr_list) { b->block.head = list->list.head;
expr_t *e = expr_list; b->block.tail = list->list.tail;
expr_list = e->next; if (set_result && b->block.tail != &b->block.head) {
e->next = 0; auto last = (ex_listitem_t *) b->block.tail;
append_expr (b, e); b->block.result = last->expr;
} }
return b; return b;
} }
@ -3028,14 +3078,19 @@ build_for_statement (expr_t *init, expr_t *test, expr_t *next,
expr_t * expr_t *
build_state_expr (expr_t *e) build_state_expr (expr_t *e)
{ {
expr_t *frame = 0; int count = e ? list_count (&e->list) : 0;
expr_t *think = 0; if (count < 2) {
expr_t *step = 0; return error (e, "not enough state arguments");
}
if (count > 3) {
return error (e, "too many state arguments");
}
expr_t *state_args[3] = {};
list_scatter (&e->list, state_args);
expr_t *frame = state_args[0];
expr_t *think = state_args[1];
expr_t *step = state_args[2];
e = reverse_expr_list (e);
frame = e;
think = frame->next;
step = think->next;
if (think->type == ex_symbol) if (think->type == ex_symbol)
think = think_expr (think->symbol); think = think_expr (think->symbol);
if (is_int_val (frame)) if (is_int_val (frame))
@ -3045,8 +3100,6 @@ build_state_expr (expr_t *e)
if (extract_type (think) != ev_func) if (extract_type (think) != ev_func)
return error (think, "invalid type for think"); return error (think, "invalid type for think");
if (step) { if (step) {
if (step->next)
return error (step->next, "too many state arguments");
if (is_int_val (step)) if (is_int_val (step))
step = cast_expr (&type_float, step); step = cast_expr (&type_float, step);
if (!type_assignable (&type_float, get_type (step))) if (!type_assignable (&type_float, get_type (step)))

View file

@ -714,12 +714,14 @@ convert_scalar (expr_t *scalar, int op, expr_t *vec)
type_t *vec_type = get_type (vec); type_t *vec_type = get_type (vec);
if (is_constant (scalar)) { if (is_constant (scalar)) {
for (int i = 1; i < type_width (get_type (vec)); i++) { int width = type_width (get_type (vec));
expr_t *s = copy_expr (scalar); expr_t *elements[width];
s->next = scalar; for (int i = 0; i < width; i++) {
scalar = s; elements[i] = scalar;
} }
return new_vector_list (scalar); auto scalar_list = new_list_expr (0);
list_gather (&scalar_list->list, elements, width);
return new_vector_list (scalar_list);
} }
return new_extend_expr (scalar, vec_type, 2, false);//2 = copy return new_extend_expr (scalar, vec_type, 2, false);//2 = copy

View file

@ -40,15 +40,15 @@ expr_t *
new_vector_list (expr_t *expr_list) new_vector_list (expr_t *expr_list)
{ {
type_t *ele_type = type_default; type_t *ele_type = type_default;
int count = list_count (&expr_list->list);
// lists are built in reverse order expr_t *elements[count + 1];
expr_list = reverse_expr_list (expr_list); list_scatter (&expr_list->list, elements);
elements[count] = 0;
int width = 0; int width = 0;
int count = 0; for (int i = 0; i < count; i++) {
for (expr_t *e = expr_list; e; e = e->next) { auto e = elements[i];
count++; auto t = get_type (e);
type_t *t = get_type (e);
if (!t) { if (!t) {
return e; return e;
} }
@ -73,16 +73,13 @@ new_vector_list (expr_t *expr_list)
int all_constant = 1; int all_constant = 1;
int all_implicit = 1; int all_implicit = 1;
expr_t *elements[count + 1]; for (int i = 0; i < count; i++) {
elements[count] = 0; auto e = elements[i];
count = 0;
for (expr_t *e = expr_list; e; e = e->next) {
int cast_width = type_width (get_type (e)); int cast_width = type_width (get_type (e));
type_t *cast_type = vector_type (ele_type, cast_width); type_t *cast_type = vector_type (ele_type, cast_width);
all_implicit = all_implicit && e->implicit; all_implicit = all_implicit && e->implicit;
elements[count] = cast_expr (cast_type, fold_constants (e)); elements[i] = cast_expr (cast_type, fold_constants (e));
all_constant = all_constant && is_constant (elements[count]); all_constant = all_constant && is_constant (elements[i]);
count++;
} }
switch (count) { switch (count) {

View file

@ -198,7 +198,8 @@ int yylex (void);
%type <expr> compound_init element_list %type <expr> compound_init element_list
%type <designator> designator designator_spec %type <designator> designator designator_spec
%type <element> element %type <element> element
%type <expr> ose optional_state_expr texpr vector_expr %type <expr> method_optional_state_expr optional_state_expr
%type <expr> texpr vector_expr
%type <expr> statement statements compound_statement %type <expr> statement statements compound_statement
%type <expr> else bool_label break_label continue_label %type <expr> else bool_label break_label continue_label
%type <expr> unary_expr ident_expr cast_expr expr_list %type <expr> unary_expr ident_expr cast_expr expr_list
@ -972,7 +973,7 @@ save_storage
; ;
function_body function_body
: ose : method_optional_state_expr
{ {
specifier_t spec = default_type ($<spec>0, $<spec>0.sym); specifier_t spec = default_type ($<spec>0, $<spec>0.sym);
symbol_t *sym = funtion_sym_type (spec, spec.sym); symbol_t *sym = funtion_sym_type (spec, spec.sym);
@ -1415,7 +1416,7 @@ compound_init
| '{' '}' { $$ = 0; } | '{' '}' { $$ = 0; }
; ;
ose method_optional_state_expr
: /* emtpy */ { $$ = 0; } : /* emtpy */ { $$ = 0; }
| SHR vector_expr { $$ = build_state_expr ($2); } | SHR vector_expr { $$ = build_state_expr ($2); }
; ;
@ -1565,7 +1566,7 @@ statement
'(' opt_init_semi opt_expr ';' opt_expr ')' statement pop_scope '(' opt_init_semi opt_expr ';' opt_expr ')' statement pop_scope
{ {
if ($6) { if ($6) {
$6 = build_block_expr ($6); $6 = build_block_expr ($6, false);
} }
$$ = build_for_statement ($6, $7, $9, $11, $$ = build_for_statement ($6, $7, $9, $11,
break_label, continue_label); break_label, continue_label);
@ -1727,11 +1728,7 @@ ident_expr
vector_expr vector_expr
: '[' expr ',' expr_list ']' : '[' expr ',' expr_list ']'
{ {
expr_t *t = $4; $$ = list_prepend_expr ($4, $2);
while (t->next)
t = t->next;
t->next = $2;
$$ = $4;
} }
; ;
@ -1783,22 +1780,17 @@ texpr
comma_expr comma_expr
: expr_list : expr_list
{ {
if ($1->next) { if ($1->list.head->next) {
expr_t *res = $1; $$ = build_block_expr ($1, true);
$1 = build_block_expr ($1); } else {
$1->block.result = res; $$ = $1->list.head->expr;
} }
$$ = $1;
} }
; ;
expr_list expr_list
: expr : expr { $$ = new_list_expr ($1); }
| expr_list ',' expr | expr_list ',' expr { $$ = list_append_expr ($1, $3); }
{
$3->next = $1;
$$ = $3;
}
; ;
opt_arg_list opt_arg_list
@ -2216,7 +2208,7 @@ notype_ivar_declarator
; ;
methoddef methoddef
: ci methoddecl ose : ci methoddecl method_optional_state_expr
{ {
method_t *method = $2; method_t *method = $2;

View file

@ -2307,7 +2307,8 @@ statement_single (sblock_t *sblock, expr_t *e)
}; };
if (e->type >= ex_count || !sfuncs[e->type]) { if (e->type >= ex_count || !sfuncs[e->type]) {
internal_error (e, "bad expression type"); internal_error (e, "bad expression type: %s",
e->type < ex_count ? expr_names[e->type] : "?");
} }
sblock = sfuncs[e->type] (sblock, e); sblock = sfuncs[e->type] (sblock, e);
return sblock; return sblock;