]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - parser.c
I added it for a reason, because I was smart. I forgot about it because of life :(
[xonotic/gmqcc.git] / parser.c
index 5f27112097d925c0907e71fcc0fba6bf27144851..7ba3782e3b8d8d445b5667a28b5ddf94fc0b9497 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -1034,8 +1034,50 @@ 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))
+             */
+            if (NotSameType(TYPE_FLOAT)) {
+                compile_error(ctx, "invalid types used in expression: cannot perform bit operations between types %s and %s",
+                              type_name[exprs[0]->vtype],
+                              type_name[exprs[1]->vtype]);
+                return false;
+            }
+
+            if(CanConstFold(exprs[0], exprs[1])) {
+                out = (ast_expression*)parser_const_float(parser, (float)((qcint)(ConstF(0)) ^ ((qcint)(ConstF(1)))));
+            } else {
+                ast_binary *expr = 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]
+                    )
+                );
+                expr->refs = AST_REF_NONE;
+                
+                out = (ast_expression*)
+                    ast_binary_new(
+                        ctx,
+                        INSTR_BITAND,
+                        (ast_expression*)ast_binary_new(
+                            ctx,
+                            INSTR_BITOR,
+                            exprs[0],
+                            exprs[1]
+                        ),
+                        (ast_expression*)expr
+                    );
+            }
+            break;
 
         case opid2('<','<'):
         case opid2('>','>'):
@@ -1162,7 +1204,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             } else {
                 ast_binary *eq = ast_binary_new(ctx, INSTR_EQ_F, exprs[0], exprs[1]);
 
-                eq->refs = (ast_binary_ref)false; /* references nothing */
+                eq->refs = AST_REF_NONE;
 
                     /* if (lt) { */
                 out = (ast_expression*)ast_ternary_new(ctx,
@@ -1918,7 +1960,7 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels)
                  * it in the predef table.  And diagnose it better :)
                  */
                 if (!OPTS_FLAG(FTEPP_PREDEFS) && ftepp_predef_exists(parser_tokval(parser))) {
-                    parseerror(parser, "unexpected ident: %s (use -fftepp-predef to enable pre-defined macros)", parser_tokval(parser));
+                    parseerror(parser, "unexpected identifier: %s (use -fftepp-predef to enable pre-defined macros)", parser_tokval(parser));
                     return false;
                 }
 
@@ -1945,12 +1987,12 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels)
                     correct_free(&corr);
 
                     if (correct) {
-                        parseerror(parser, "unexpected ident: %s (did you mean %s?)", parser_tokval(parser), correct);
+                        parseerror(parser, "unexpected identifier: %s (did you mean %s?)", parser_tokval(parser), correct);
                         mem_d(correct);
                         return false;
                     }
                 }
-                parseerror(parser, "unexpected ident: %s", parser_tokval(parser));
+                parseerror(parser, "unexpected identifier: %s", parser_tokval(parser));
                 return false;
             }
         }
@@ -1997,7 +2039,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
     while (true)
     {
         if (parser->tok == TOKEN_TYPENAME) {
-            parseerror(parser, "unexpected typename");
+            parseerror(parser, "unexpected typename `%s`", parser_tokval(parser));
             goto onerr;
         }
 
@@ -6219,7 +6261,7 @@ static bool parser_compile(parser_t *parser)
         {
             if (!parser_global_statement(parser)) {
                 if (parser->tok == TOKEN_EOF)
-                    parseerror(parser, "unexpected eof");
+                    parseerror(parser, "unexpected end of file");
                 else if (compile_errors)
                     parseerror(parser, "there have been errors, bailing out");
                 lex_close(parser->lex);