[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;
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

View file

@ -382,6 +382,10 @@ ex_listitem_t *new_listitem (expr_t *e);
int list_count (ex_list_t *list) __attribute__((pure));
void list_scatter (ex_list_t *list, expr_t **exprs);
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.
@ -474,14 +478,12 @@ expr_t *new_block_expr (void);
/** Create a new statement block expression node from an expression list
The returned block holds the expression list in reverse order. This makes
it easy to build the list in a parser.
\param expr_list The expression list to convert to an expression block.
Note that the evaluation order will be reversed.
\param list The expression list to convert to an expression block.
\param set_result If true, the block's result will be set to the last
expression in the list.
\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);
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");
return type_default;
}
params = reverse_expr_list (params);
auto plus = params;
auto minus = plus ? plus->next : 0;
auto zero = minus ? minus->next : 0;
int param_count = params ? list_count (&params->list) : 0;
if (param_count > 3) {
error (params, "too many arguments in signature");
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;
if ((plus && !is_integral_val (err = plus))
@ -410,11 +418,11 @@ algebra_subtype (type_t *type, attribute_t *attr)
}
auto algebra = algebra_get (type);
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'");
return type;
}
auto param = attr->params;
auto param = attr->params->list.head->expr;
if (!is_integral_val (param)) {
error (0, "'group_mask' parameter must be an integer constant");
return type;

View file

@ -40,18 +40,23 @@
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 (v->type != ex_value) {
error (value, "not a literal constant");
return 0;
if (params && params->type != ex_list) {
internal_error (params, "attribute params not a list");
}
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;
}
}
}
attribute_t *attr;
ALLOC (16384, attribute_t, attributes, attr);
attr->name = save_string (name);
attr->params = value ? reverse_expr_list (value) : 0;
attr->params = params;
return attr;
}

View file

@ -227,26 +227,31 @@ print_block (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
list_scatter (&e->block.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;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" : "");
if (e->block.result)
dasprintf (dstr, "%*s<tr><td colspan=\"%d\" port=\"result\">=</td>"
"</tr>\n", indent + 4, "", 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);
"</tr>\n", indent + 4, "", colspan);
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</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, "");
@ -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
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_extend] = print_extend,
[ex_multivec] = print_multivec,
[ex_list] = print_list,
};
int indent = level * 2 + 2;

View file

@ -273,6 +273,53 @@ new_listitem (expr_t *e)
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
list_count (ex_list_t *list)
{
@ -638,15 +685,18 @@ new_binary_expr (int op, expr_t *e1, expr_t *e2)
}
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 ();
while (expr_list) {
expr_t *e = expr_list;
expr_list = e->next;
e->next = 0;
append_expr (b, e);
b->block.head = list->list.head;
b->block.tail = list->list.tail;
if (set_result && b->block.tail != &b->block.head) {
auto last = (ex_listitem_t *) b->block.tail;
b->block.result = last->expr;
}
return b;
}
@ -3028,14 +3078,19 @@ build_for_statement (expr_t *init, expr_t *test, expr_t *next,
expr_t *
build_state_expr (expr_t *e)
{
expr_t *frame = 0;
expr_t *think = 0;
expr_t *step = 0;
int count = e ? list_count (&e->list) : 0;
if (count < 2) {
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)
think = think_expr (think->symbol);
if (is_int_val (frame))
@ -3045,8 +3100,6 @@ build_state_expr (expr_t *e)
if (extract_type (think) != ev_func)
return error (think, "invalid type for think");
if (step) {
if (step->next)
return error (step->next, "too many state arguments");
if (is_int_val (step))
step = cast_expr (&type_float, 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);
if (is_constant (scalar)) {
for (int i = 1; i < type_width (get_type (vec)); i++) {
expr_t *s = copy_expr (scalar);
s->next = scalar;
scalar = s;
int width = type_width (get_type (vec));
expr_t *elements[width];
for (int i = 0; i < width; i++) {
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

View file

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

View file

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