For loop with custom init and post blocks and potentially unbounded conditional expression

This commit is contained in:
Bhargava Shastry 2019-03-26 10:52:30 +01:00
parent 7187a3e5ca
commit b5cbb1a3e9
3 changed files with 56 additions and 15 deletions

View File

@ -616,7 +616,9 @@ void ProtoConverter::visit(FunctionCall const& _x)
visit(_x.call_zero());
break;
case FunctionCall::kCallMultidecl:
visit(_x.call_multidecl());
// Hack: Disallow (multi) variable declarations until scope extension is implemented for "for-init"
if (!m_inForInitScope)
visit(_x.call_multidecl());
break;
case FunctionCall::kCallMultiassign:
visit(_x.call_multiassign());
@ -655,17 +657,38 @@ void ProtoConverter::visit(StoreFunc const& _x)
}
void ProtoConverter::visit(ForStmt const& _x)
{
bool wasInForBody = m_inForBodyScope;
bool wasInForInit = m_inForInitScope;
m_inForBodyScope = false;
m_inForInitScope = true;
m_output << "for ";
visit(_x.for_init());
m_inForInitScope = false;
visit(_x.for_cond());
visit(_x.for_post());
m_inForBodyScope = true;
visit(_x.for_body());
m_inForBodyScope = wasInForBody;
m_inForInitScope = wasInForInit;
}
void ProtoConverter::visit(BoundedForStmt const& _x)
{
// Boilerplate for loop that limits the number of iterations to a maximum of 4.
// TODO: Generalize for loop init, condition, and post blocks.
std::string loopVarName("i_" + std::to_string(m_numNestedForLoops++));
m_output << "for { let " << loopVarName << " := 0 } "
<< "lt(" << loopVarName << ", 0x60) "
<< "{ " << loopVarName << " := add(" << loopVarName << ", 0x20) } ";
m_inForScope.push(true);
<< "lt(" << loopVarName << ", 0x60) "
<< "{ " << loopVarName << " := add(" << loopVarName << ", 0x20) } ";
// Store previous for body scope
bool wasInForBody = m_inForBodyScope;
bool wasInForInit = m_inForInitScope;
m_inForBodyScope = true;
m_inForInitScope = false;
visit(_x.for_body());
m_inForScope.pop();
--m_numNestedForLoops;
// Restore previous for body scope and init
m_inForBodyScope = wasInForBody;
m_inForInitScope = wasInForInit;
}
void ProtoConverter::visit(CaseStmt const& _x)
@ -765,7 +788,9 @@ void ProtoConverter::visit(Statement const& _x)
switch (_x.stmt_oneof_case())
{
case Statement::kDecl:
visit(_x.decl());
// Hack: Disallow (multi) variable declarations until scope extension is implemented for "for-init"
if (!m_inForInitScope)
visit(_x.decl());
break;
case Statement::kAssignment:
visit(_x.assignment());
@ -782,15 +807,18 @@ void ProtoConverter::visit(Statement const& _x)
case Statement::kForstmt:
visit(_x.forstmt());
break;
case Statement::kBoundedforstmt:
visit(_x.boundedforstmt());
break;
case Statement::kSwitchstmt:
visit(_x.switchstmt());
break;
case Statement::kBreakstmt:
if (m_inForScope.top())
if (m_inForBodyScope)
m_output << "break\n";
break;
case Statement::kContstmt:
if (m_inForScope.top())
if (m_inForBodyScope)
m_output << "continue\n";
break;
case Statement::kLogFunc:

View File

@ -42,9 +42,10 @@ public:
{
m_numLiveVars = 0;
m_numVarsPerScope.push(m_numLiveVars);
m_numNestedForLoops = 0;
m_inForScope.push(false);
m_numFunctionSets = 0;
m_inForBodyScope = false;
m_inForInitScope = false;
m_numNestedForLoops = 0;
}
ProtoConverter(ProtoConverter const&) = delete;
ProtoConverter(ProtoConverter&&) = delete;
@ -69,6 +70,7 @@ private:
void visit(Statement const&);
void visit(FunctionDefinition const&);
void visit(ForStmt const&);
void visit(BoundedForStmt const&);
void visit(CaseStmt const&);
void visit(SwitchStmt const&);
void visit(TernaryOp const&);
@ -131,9 +133,6 @@ private:
std::stack<unsigned> m_numVarsPerScope;
// Number of live variables in function scope
unsigned m_numLiveVars;
// Number of nested for loops for loop index referencing
unsigned m_numNestedForLoops;
std::stack<bool> m_inForScope;
// Set that is used for deduplicating switch case literals
std::stack<std::set<dev::u256>> m_switchLiteralSetPerScope;
// Total number of function sets. A function set contains one function of each type defined by
@ -146,6 +145,12 @@ private:
// mod input/output parameters impose an upper bound on the number of input/output parameters a function may have.
static unsigned constexpr modInputParams = 5;
static unsigned constexpr modOutputParams = 5;
// predicate to keep track of for body scope
bool m_inForBodyScope;
// Index used for naming loop variable of bounded for loops
unsigned m_numNestedForLoops;
// predicate to keep track of for loop init scope
bool m_inForInitScope;
};
}
}

View File

@ -256,8 +256,15 @@ message IfStmt {
required Block if_body = 2;
}
message BoundedForStmt {
required Block for_body = 1;
}
message ForStmt {
required Block for_body = 1;
required Block for_init = 2;
required Block for_post = 3;
required Expression for_cond = 4;
}
message CaseStmt {
@ -324,6 +331,7 @@ message Statement {
ExtCodeCopy extcode_copy = 12;
TerminatingStmt terminatestmt = 13;
FunctionCall functioncall = 14;
BoundedForStmt boundedforstmt = 15;
}
}