Added support for FOR loops in function calls in parameters
authorClifford Wolf <clifford@clifford.at>
Fri, 14 Feb 2014 19:33:22 +0000 (20:33 +0100)
committerClifford Wolf <clifford@clifford.at>
Fri, 14 Feb 2014 19:33:22 +0000 (20:33 +0100)
frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/simplify.cc

index 7e199cd5c14a01772ab4a0ea57aee78b06d75a2f..56e9393b7c7f12bc7cf6ce88731720e7d6f06524 100644 (file)
@@ -136,6 +136,7 @@ std::string AST::type2str(AstNodeType type)
        X(AST_COND)
        X(AST_DEFAULT)
        X(AST_FOR)
+       X(AST_WHILE)
        X(AST_GENVAR)
        X(AST_GENFOR)
        X(AST_GENIF)
index ec4f4f62bd15f66e5bcca7f285250368ab283188..f42bc35fb513e3025210c06b009d1a401357d76d 100644 (file)
@@ -116,6 +116,7 @@ namespace AST
                AST_COND,
                AST_DEFAULT,
                AST_FOR,
+               AST_WHILE,
 
                AST_GENVAR,
                AST_GENFOR,
index 85dc1d3c2e240e09a78109165830776a5c7ecbb3..236843d5d221c9aa79fad6adb58de5abff9208d8 100644 (file)
@@ -1891,10 +1891,51 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
 
                        variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size());
 
+                       delete block->children.front();
                        block->children.erase(block->children.begin());
                        continue;
                }
 
+               if (stmt->type == AST_FOR)
+               {
+                       block->children.insert(block->children.begin(), stmt->children.at(0));
+                       stmt->children.at(3)->children.push_back(stmt->children.at(2));
+                       stmt->children.erase(stmt->children.begin() + 2);
+                       stmt->children.erase(stmt->children.begin());
+                       stmt->type = AST_WHILE;
+                       continue;
+               }
+
+               if (stmt->type == AST_WHILE)
+               {
+                       AstNode *cond = stmt->children.at(0)->clone();
+                       cond->replace_variables(variables, fcall);
+                       while (cond->simplify(true, false, false, 1, -1, false, true)) { }
+
+                       if (cond->type != AST_CONSTANT)
+                               log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
+                                               stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+
+                       if (cond->asBool()) {
+                               block->children.insert(block->children.begin(), stmt->children.at(1)->clone());
+                       } else {
+                               delete block->children.front();
+                               block->children.erase(block->children.begin());
+                       }
+
+                       delete cond;
+                       continue;
+               }
+
+               if (stmt->type == AST_BLOCK)
+               {
+                       block->children.erase(block->children.begin());
+                       block->children.insert(block->children.begin(), stmt->children.begin(), stmt->children.end());
+                       stmt->children.clear();
+                       delete stmt;
+                       continue;
+               }
+
                log_error("Unsupported language construct in constant function at %s:%d (called from %s:%d).\n",
                                stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
                log_abort();