From a8fddbb7d33d5a5627c6d866c8150b6d3c73bc2b Mon Sep 17 00:00:00 2001 From: Dale Weiler Date: Sat, 15 Jun 2013 09:48:40 +0000 Subject: [PATCH] Implemented bitwise xor operator. --- lexer.c | 2 +- parser.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++-- tests/xor.qc | 12 ++++++++++++ tests/xor.tmpl | 7 +++++++ 4 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 tests/xor.qc create mode 100644 tests/xor.tmpl diff --git a/lexer.c b/lexer.c index cc71784..7cd7794 100644 --- a/lexer.c +++ b/lexer.c @@ -1309,7 +1309,7 @@ int lex_do(lex_file *lex) ch == '>' || ch == '<' || /* <<, >>, <=, >= */ ch == '=' || ch == '!' || /* <=>, ==, != */ ch == '&' || ch == '|' || /* &&, ||, &=, |= */ - ch == '~' /* ~=, ~ */ + ch == '~' || ch == '^' /* ~=, ~, ^ */ ) { lex_tokench(lex, ch); diff --git a/parser.c b/parser.c index 62c21df..2f88674 100644 --- a/parser.c +++ b/parser.c @@ -1034,8 +1034,57 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) exprs[0], exprs[1]); break; case opid1('^'): - compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor via ^"); - return false; + /* + * ^ can be implemented as: + * (LHS | RHS) & ~(LHS & RHS) + * to implement ~ we need to use -1-X, as you can see the + * whole process ends up becoming: + * (LHS | RHS) & (-1 - (LHS & RHS)) + */ + #define TRY_TYPE(I) \ + if (exprs[0]->vtype != TYPE_FLOAT) { \ + ast_type_to_string(exprs[0], ty1, sizeof(ty1)); \ + compile_error ( \ + ast_ctx(exprs[(I)]), \ + "invalid type for bit-xor in %s: %s", \ + ty1, \ + ((I) == 0) \ + ? "left-hand-side of expression" \ + : "right-hand-side of expression" \ + ); \ + return false; \ + } + TRY_TYPE(0) + TRY_TYPE(1) + #undef TRY_TYPE + + if(CanConstFold(exprs[0], exprs[1])) { + out = (ast_expression*)parser_const_float(parser, (float)((qcint)(ConstF(0)) ^ ((qcint)(ConstF(1))))); + } else { + out = (ast_expression*) + ast_binary_new( + ctx, + INSTR_BITAND, + (ast_expression*)ast_binary_new( + ctx, + INSTR_BITOR, + exprs[0], + exprs[1] + ), + (ast_expression*)ast_binary_new( + ctx, + INSTR_SUB_F, + (ast_expression*)parser_const_float_neg1(parser), + (ast_expression*)ast_binary_new( + ctx, + INSTR_BITAND, + exprs[0], + exprs[1] + ) + ) + ); + } + break; case opid2('<','<'): case opid2('>','>'): diff --git a/tests/xor.qc b/tests/xor.qc new file mode 100644 index 0000000..81fb114 --- /dev/null +++ b/tests/xor.qc @@ -0,0 +1,12 @@ +void main() { + float x = 5; + float y = 3; + float z = x ^ y; // 6 + + float a = 2; + float b = 10; + float c = a ^ b; // 8 + + print(ftos(z), "\n"); + print(ftos(c), "\n"); +} diff --git a/tests/xor.tmpl b/tests/xor.tmpl new file mode 100644 index 0000000..681a982 --- /dev/null +++ b/tests/xor.tmpl @@ -0,0 +1,7 @@ +I: xor.qc +D: test bitwise xor +T: -execute +C: -std=gmqcc +E: $null +M: 6 +M: 8 -- 2.39.2