mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-24 20:51:35 +00:00
[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:
parent
cc67e69923
commit
81b544c362
10 changed files with 194 additions and 87 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 (¶ms->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 (¶ms->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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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\"><block>(%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\"><list>(%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;
|
||||
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue