From 7a7a68510542f29b597288889f5dbd7340a768fe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jun 2013 15:37:08 +0900 Subject: [PATCH] Add support for actual vector expressions. Currently, they can represent either vectors or quaternions, and the quaternions can be in either [s, v] form or [w, x, y, z] form. Many things will not actual work yet as the vector expression needs to be converted into the appropriate form for assigning the elements to the components of the "vector" type. --- tools/qfcc/include/expr.h | 8 +++++ tools/qfcc/source/dot_expr.c | 9 ++++++ tools/qfcc/source/expr.c | 57 ++++++++++++++++++++++++++++++++++ tools/qfcc/source/qc-parse.y | 2 +- tools/qfcc/source/statements.c | 2 ++ 5 files changed, 77 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index f4dd2d716..5729e316e 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -51,6 +51,7 @@ typedef enum { ex_uexpr, ///< unary expression (::ex_expr_t) ex_symbol, ///< non-temporary variable (::symbol_t) ex_temp, ///< temporary variable (::ex_temp_t) + ex_vector, ///< "vector" expression (::ex_vector_t) ex_nil, ///< umm, nil, null. nuff said (0 of any type) ex_value, ///< constant value (::ex_value_t) @@ -96,6 +97,11 @@ typedef struct { struct type_s *type; ///< The type of the temporary variable. } ex_temp_t; +typedef struct { + struct type_s *type; ///< Type of vector (vector/quaternion) + struct expr_s *list; ///< Linked list of element expressions. +} ex_vector_t; + /** Pointer constant expression. Represent a pointer to an absolute address in data space. @@ -199,6 +205,7 @@ typedef struct expr_s { ex_expr_t expr; ///< binary or unary expression struct symbol_s *symbol; ///< symbol reference expression ex_temp_t temp; ///< temporary variable expression + ex_vector_t vector; ///< vector expression list ex_value_t *value; ///< constant value } e; } expr_t; @@ -396,6 +403,7 @@ float expr_float (expr_t *e); */ expr_t *new_vector_expr (const float *vector_val); const float *expr_vector (expr_t *e); +expr_t *new_vector_list (expr_t *e); /** Create a new entity constant expression node. diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index aaf5b8706..301086dba 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -361,6 +361,14 @@ print_temp (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) e->line); } +static void +print_vector (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + dasprintf (dstr, "%*se_%p [label=\"vector FIXME\"];\n", indent, "", e); +} + static void print_nil (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { @@ -455,6 +463,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) print_uexpr, print_symbol, print_temp, + print_vector, print_nil, print_value, }; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index d87b17ac4..2efa90cd3 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -178,6 +178,8 @@ get_type (expr_t *e) convert_int (e); } return ev_types[e->e.value->type]; + case ex_vector: + return e->e.vector.type; } return 0; } @@ -355,6 +357,18 @@ copy_expr (expr_t *e) n->file = pr.source_file; n->e.temp.expr = copy_expr (e->e.temp.expr); return n; + case ex_vector: + n = new_expr (); + n->e.vector.type = e->e.vector.type; + n->e.vector.list = copy_expr (e->e.vector.list); + n = n->e.vector.list; + t = e->e.vector.list; + while (t->next) { + n->next = copy_expr (t->next); + n = n->next; + t = t->next; + } + return n; } internal_error (e, "invalid expression"); } @@ -546,6 +560,46 @@ new_vector_expr (const float *vector_val) return e; } +expr_t * +new_vector_list (expr_t *e) +{ + expr_t *t; + int count; + type_t *type = &type_vector; + expr_t *vec; + + e = reverse_expr_list (e); // put the elements in the right order + for (t = e, count = 0; t; t = t->next) + count++; + switch (count) { + case 4: + type = &type_quaternion; + case 3: + // quaternion or vector. all expressions must be compatible with + // a float + for (t = e; t; t = t->next) + if (!type_assignable (&type_float, get_type (t))) + return error (t, "invalid type for vector element"); + vec = new_expr (); + vec->type = ex_vector; + vec->e.vector.type = type; + vec->e.vector.list = e; + break; + case 2: + // quaternion. first expression must be compatible with a float, + // the other must be a vector + if (!type_assignable (&type_float, get_type (e)) + || type_assignable (&type_vector, get_type(e->next))) { + return error (t, "invalid types for vector elements"); + } + // s, v + break; + default: + return error (e, "invalid number of elements in vector exprssion"); + } + return vec; +} + expr_t * new_entity_expr (int entity_val) { @@ -1669,6 +1723,7 @@ unary_expr (int op, expr_t *e) case ex_expr: case ex_bool: case ex_temp: + case ex_vector: { expr_t *n = new_unary_expr (op, e); @@ -1733,6 +1788,7 @@ unary_expr (int op, expr_t *e) case ex_expr: case ex_symbol: case ex_temp: + case ex_vector: { expr_t *n = new_unary_expr (op, e); @@ -1793,6 +1849,7 @@ unary_expr (int op, expr_t *e) case ex_bool: case ex_symbol: case ex_temp: + case ex_vector: bitnot_expr: if (options.code.progsversion == PROG_ID_VERSION) { expr_t *n1 = new_integer_expr (-1); diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index a0be3c5d8..bf2ff86f4 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1245,7 +1245,7 @@ unary_expr { $$ = sizeof_expr (0, $3->type); } - | vector_expr { $$ = $1; } + | vector_expr { $$ = new_vector_list ($1); } | obj_expr { $$ = $1; } ; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index de425b0dd..ac4b140f1 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1005,6 +1005,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) expr_uexpr, expr_symbol, expr_temp, + 0, // ex_vector 0, // ex_nil expr_value, }; @@ -1287,6 +1288,7 @@ statement_slist (sblock_t *sblock, expr_t *e) statement_uexpr, statement_nonexec, // ex_symbol statement_nonexec, // ex_temp + statement_nonexec, // ex_vector statement_nonexec, // ex_nil statement_nonexec, // ex_value };