Implemented >< (vector cross product operator). Currently support for constants only.
authorDale Weiler <killfieldengine@gmail.com>
Sat, 31 Aug 2013 17:41:25 +0000 (13:41 -0400)
committerDale Weiler <killfieldengine@gmail.com>
Sat, 31 Aug 2013 17:41:25 +0000 (13:41 -0400)
fold.c
lexer.c
lexer.h
parser.c
tests/vec_ops.qc
tests/vec_ops.tmpl

diff --git a/fold.c b/fold.c
index c977805..98e637a 100644 (file)
--- a/fold.c
+++ b/fold.c
@@ -163,6 +163,14 @@ static GMQCC_INLINE bool vec3_pbool(vec3_t a) {
     return (a.x && a.y && a.z);
 }
 
+static GMQCC_INLINE vec3_t vec3_cross(vec3_t a, vec3_t b) {
+    vec3_t out;
+    out.x = a.y * b.z - a.z * b.y;
+    out.y = a.z * b.x - a.x * b.z;
+    out.z = a.x * b.y - a.y * b.x;
+    return out;
+}
+
 static lex_ctx_t fold_ctx(fold_t *fold) {
     lex_ctx_t ctx;
     if (fold->parser->lex)
@@ -641,6 +649,12 @@ static GMQCC_INLINE ast_expression *fold_op_bnot(fold_t *fold, ast_value *a) {
     return NULL;
 }
 
+static GMQCC_INLINE ast_expression *fold_op_cross(fold_t *fold, ast_value *a, ast_value *b) {
+    if (fold_can_2(a, b))
+        return fold_constgen_vector(fold, vec3_cross(fold_immvalue_vector(a), fold_immvalue_vector(b)));
+    return NULL;
+}
+
 ast_expression *fold_op(fold_t *fold, const oper_info *info, ast_expression **opexprs) {
     ast_value      *a = (ast_value*)opexprs[0];
     ast_value      *b = (ast_value*)opexprs[1];
@@ -698,6 +712,7 @@ ast_expression *fold_op(fold_t *fold, const oper_info *info, ast_expression **op
         fold_op_case(2, ('!', '='),    cmp,    (fold, a, b, true));
         fold_op_case(2, ('=', '='),    cmp,    (fold, a, b, false));
         fold_op_case(2, ('~', 'P'),    bnot,   (fold, a));
+        fold_op_case(2, ('>', '<'),    cross,  (fold, a, b));
     }
     #undef fold_op_case
     compile_error(fold_ctx(fold), "internal error: attempted to constant-fold for unsupported operator");
diff --git a/lexer.c b/lexer.c
index af7819d..5177471 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -1306,7 +1306,7 @@ int lex_do(lex_file *lex)
     }
 
     if (ch == '+' || ch == '-' || /* ++, --, +=, -=  and -> as well! */
-        ch == '>' || ch == '<' || /* <<, >>, <=, >=                  */
+        ch == '>' || ch == '<' || /* <<, >>, <=, >=  and >< as well! */
         ch == '=' || ch == '!' || /* <=>, ==, !=                     */
         ch == '&' || ch == '|' || /* &&, ||, &=, |=                  */
         ch == '~' || ch == '^'    /* ~=, ~, ^                        */
@@ -1314,7 +1314,9 @@ int lex_do(lex_file *lex)
         lex_tokench(lex, ch);
 
         nextch = lex_getch(lex);
-        if ((nextch == '=' && ch != '<') || (nextch == ch && ch != '!')) {
+        if ((nextch == '=' && ch != '<') ||
+            (nextch == ch  && ch != '!') ||
+            (nextch == '<' && ch == '>')) {
             lex_tokench(lex, nextch);
         } else if (ch == '<' && nextch == '=') {
             lex_tokench(lex, nextch);
diff --git a/lexer.h b/lexer.h
index 48ab4b6..24e29dd 100644 (file)
--- a/lexer.h
+++ b/lexer.h
@@ -196,6 +196,7 @@ static const oper_info c_operators[] = {
     { "*",   2, opid1('*'),         ASSOC_LEFT,  13, 0,         true},
     { "/",   2, opid1('/'),         ASSOC_LEFT,  13, 0,         true},
     { "%",   2, opid1('%'),         ASSOC_LEFT,  13, 0,         true},
+    { "><",  2, opid2('>','<'),     ASSOC_LEFT,  13, 0,         true},
 
     { "+",   2, opid1('+'),         ASSOC_LEFT,  12, 0,         true},
     { "-",   2, opid1('-'),         ASSOC_LEFT,  12, 0,         true},
index ea9e000..3c29399 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -762,6 +762,22 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             }
             break;
 
+        case opid2('>', '<'):
+            if (NotSameType(TYPE_VECTOR)) {
+                ast_type_to_string(exprs[0], ty1, sizeof(ty1));
+                ast_type_to_string(exprs[1], ty2, sizeof(ty2));
+                compile_error(ctx, "invalid types used in cross product: %s and %s",
+                    ty1, ty2);
+                return false;
+            }
+
+            if (!(out = fold_op(parser->fold, op, exprs))) {
+                compile_error(ctx, "cross product for non-constant vectors unimplemented");
+                return false;
+            }
+
+            break;
+
         case opid3('<','=','>'): /* -1, 0, or 1 */
             if (NotSameType(TYPE_FLOAT)) {
                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
index 509dc3a..29ecbae 100644 (file)
@@ -8,4 +8,5 @@ void main(vector v) {
     print(vtos(v & 16), "\n");
     print(vtos(v | '25 42 51'), "\n");
     print(vtos(v & '25 42 51'), "\n");
+    print(vtos('1 2 3' >< '3 2 1'));
 }
index 7943232..0eaf045 100644 (file)
@@ -1,7 +1,7 @@
 I: vec_ops.qc
 D: some additional vector operations
 T: -execute
-C: -std=fteqcc
+C: -std=gmqcc
 E: -vector "8 16 32"
 M: '8 16 32'
 M: '4 8 16'
@@ -11,3 +11,4 @@ M: '20 24 16'
 M: '0 0 16'
 M: '29 42 51'
 M: '0 8 16'
+M: '-4 8 -4'