]> git.rm.cloudns.org Git - xonotic/gmqcc.git/commitdiff
while/for/do now all use process_condition, ast_loop got 2 new parameters for more...
authorWolfgang Bumiller <blub@speed.at>
Thu, 20 Dec 2012 19:22:31 +0000 (20:22 +0100)
committerWolfgang Bumiller <blub@speed.at>
Thu, 20 Dec 2012 19:22:31 +0000 (20:22 +0100)
ast.c
ast.h
parser.c

diff --git a/ast.c b/ast.c
index 79a74c0cc0176fce28f91ddc18cc4021f79b33e3..7fcab1538e4b12fe00db1b4dd034736841cffcbc 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -709,8 +709,8 @@ void ast_ternary_delete(ast_ternary *self)
 
 ast_loop* ast_loop_new(lex_ctx ctx,
                        ast_expression *initexpr,
-                       ast_expression *precond,
-                       ast_expression *postcond,
+                       ast_expression *precond, bool pre_not,
+                       ast_expression *postcond, bool post_not,
                        ast_expression *increment,
                        ast_expression *body)
 {
@@ -723,6 +723,9 @@ ast_loop* ast_loop_new(lex_ctx ctx,
     self->increment = increment;
     self->body      = body;
 
+    self->pre_not   = pre_not;
+    self->post_not  = post_not;
+
     if (initexpr)
         ast_propagate_effects(self, initexpr);
     if (precond)
@@ -2546,6 +2549,11 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
         else if (bpostcond)  ontrue = bpostcond;
         else                 ontrue = bprecond;
         onfalse = bout;
+        if (self->pre_not) {
+            tmpblock = ontrue;
+            ontrue   = onfalse;
+            onfalse  = tmpblock;
+        }
         if (!ir_block_create_if(end_bprecond, ast_ctx(self), precond, ontrue, onfalse))
             return false;
     }
@@ -2581,6 +2589,11 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
         else if (bincrement) ontrue = bincrement;
         else                 ontrue = bpostcond;
         onfalse = bout;
+        if (self->post_not) {
+            tmpblock = ontrue;
+            ontrue   = onfalse;
+            onfalse  = tmpblock;
+        }
         if (!ir_block_create_if(end_bpostcond, ast_ctx(self), postcond, ontrue, onfalse))
             return false;
     }
diff --git a/ast.h b/ast.h
index 95b8962ddab15724979ba111db0e94368117b329..a7d131c1ae3c558807e48b28bff93d5766f031cb 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -449,11 +449,19 @@ struct ast_loop_s
     ast_expression *postcond;
     ast_expression *increment;
     ast_expression *body;
+    /* For now we allow a seperate flag on whether or not the condition
+     * is supposed to be true or false.
+     * That way, the parser can generate a 'while not(!x)' for `while(x)`
+     * if desired, which is useful for the new -f{true,false}-empty-strings
+     * flag.
+     */
+    bool pre_not;
+    bool post_not;
 };
 ast_loop* ast_loop_new(lex_ctx ctx,
                        ast_expression *initexpr,
-                       ast_expression *precond,
-                       ast_expression *postcond,
+                       ast_expression *precond, bool pre_not,
+                       ast_expression *postcond, bool post_not,
                        ast_expression *increment,
                        ast_expression *body);
 void ast_loop_delete(ast_loop*);
index 688c8ef69fe65789026ba40fdd2707afdbe34852..5129962c768c216f8a1e16d15e78b4a8e4026d8c 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -1898,9 +1898,16 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond,
 {
     bool       ifnot = false;
     ast_unary *unary;
+    ast_expression *prev;
 
     if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->expression.vtype == TYPE_STRING) {
+        prev = cond;
         cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond);
+        if (!cond) {
+            ast_unref(prev);
+            parseerror(parser, "internal error: failed to process condition");
+            return NULL;
+        }
         ifnot = !ifnot;
     }
     else if (OPTS_FLAG(CORRECT_LOGIC)) {
@@ -1909,13 +1916,20 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond,
         if (!ast_istype(cond, ast_unary) || unary->op < INSTR_NOT_F || unary->op > INSTR_NOT_FNC)
         {
             /* use the right NOT_ */
+            prev = cond;
             cond = (ast_expression*)ast_unary_new(ast_ctx(cond), type_not_instr[cond->expression.vtype], cond);
+            if (!cond) {
+                ast_unref(prev);
+                parseerror(parser, "internal error: failed to process condition");
+                return NULL;
+            }
             ifnot = !ifnot;
         }
     }
 
     unary = (ast_unary*)cond;
-    while (ast_istype(cond, ast_unary) && unary->op == INSTR_NOT_F && unary->operand->expression.vtype != TYPE_STRING)
+    while (ast_istype(cond, ast_unary) && unary->op == INSTR_NOT_F)
+        /*&& unary->operand->expression.vtype != TYPE_STRING) */
     {
         cond = unary->operand;
         unary->operand = NULL;
@@ -2018,6 +2032,8 @@ static bool parse_while(parser_t *parser, ast_block *block, ast_expression **out
     ast_loop *aloop;
     ast_expression *cond, *ontrue;
 
+    bool ifnot = false;
+
     lex_ctx ctx = parser_ctx(parser);
 
     (void)block; /* not touching */
@@ -2053,7 +2069,12 @@ static bool parse_while(parser_t *parser, ast_block *block, ast_expression **out
         return false;
     }
 
-    aloop = ast_loop_new(ctx, NULL, cond, NULL, NULL, ontrue);
+    cond = process_condition(parser, cond, &ifnot);
+    if (!cond) {
+        ast_delete(ontrue);
+        return false;
+    }
+    aloop = ast_loop_new(ctx, NULL, cond, ifnot, NULL, false, NULL, ontrue);
     *out = (ast_expression*)aloop;
     return true;
 }
@@ -2063,6 +2084,8 @@ static bool parse_dowhile(parser_t *parser, ast_block *block, ast_expression **o
     ast_loop *aloop;
     ast_expression *cond, *ontrue;
 
+    bool ifnot = false;
+
     lex_ctx ctx = parser_ctx(parser);
 
     (void)block; /* not touching */
@@ -2122,7 +2145,12 @@ static bool parse_dowhile(parser_t *parser, ast_block *block, ast_expression **o
         return false;
     }
 
-    aloop = ast_loop_new(ctx, NULL, NULL, cond, NULL, ontrue);
+    cond = process_condition(parser, cond, &ifnot);
+    if (!cond) {
+        ast_delete(ontrue);
+        return false;
+    }
+    aloop = ast_loop_new(ctx, NULL, NULL, false, cond, ifnot, NULL, ontrue);
     *out = (ast_expression*)aloop;
     return true;
 }
@@ -2132,7 +2160,9 @@ static bool parse_for(parser_t *parser, ast_block *block, ast_expression **out)
     ast_loop       *aloop;
     ast_expression *initexpr, *cond, *increment, *ontrue;
     ast_value      *typevar;
-    bool   retval = true;
+
+    bool retval = true;
+    bool ifnot  = false;
 
     lex_ctx ctx = parser_ctx(parser);
 
@@ -2225,7 +2255,10 @@ static bool parse_for(parser_t *parser, ast_block *block, ast_expression **out)
     if (!parse_statement_or_block(parser, &ontrue))
         goto onerr;
 
-    aloop = ast_loop_new(ctx, initexpr, cond, NULL, increment, ontrue);
+    cond = process_condition(parser, cond, &ifnot);
+    if (!cond)
+        goto onerr;
+    aloop = ast_loop_new(ctx, initexpr, cond, ifnot, NULL, false, increment, ontrue);
     *out = (ast_expression*)aloop;
 
     if (!parser_leaveblock(parser))