From 64661f54ea4b13657301a975db10aeff6245610f Mon Sep 17 00:00:00 2001 From: Dale Weiler Date: Sat, 31 Aug 2013 13:41:25 -0400 Subject: [PATCH] Implemented >< (vector cross product operator). Currently support for constants only. --- fold.c | 15 +++++++++++++++ lexer.c | 6 ++++-- lexer.h | 1 + parser.c | 16 ++++++++++++++++ tests/vec_ops.qc | 1 + tests/vec_ops.tmpl | 3 ++- 6 files changed, 39 insertions(+), 3 deletions(-) diff --git a/fold.c b/fold.c index c977805..98e637a 100644 --- 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 --- 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 --- 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}, diff --git a/parser.c b/parser.c index ea9e000..3c29399 100644 --- 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)); diff --git a/tests/vec_ops.qc b/tests/vec_ops.qc index 509dc3a..29ecbae 100644 --- a/tests/vec_ops.qc +++ b/tests/vec_ops.qc @@ -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')); } diff --git a/tests/vec_ops.tmpl b/tests/vec_ops.tmpl index 7943232..0eaf045 100644 --- a/tests/vec_ops.tmpl +++ b/tests/vec_ops.tmpl @@ -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' -- 2.39.2