mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #6730 from ethereum/generic-for-loop
For loop with generalized init-cond-post
This commit is contained in:
commit
452a1d6aff
@ -616,7 +616,9 @@ void ProtoConverter::visit(FunctionCall const& _x)
|
|||||||
visit(_x.call_zero());
|
visit(_x.call_zero());
|
||||||
break;
|
break;
|
||||||
case FunctionCall::kCallMultidecl:
|
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;
|
break;
|
||||||
case FunctionCall::kCallMultiassign:
|
case FunctionCall::kCallMultiassign:
|
||||||
visit(_x.call_multiassign());
|
visit(_x.call_multiassign());
|
||||||
@ -655,17 +657,38 @@ void ProtoConverter::visit(StoreFunc const& _x)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ProtoConverter::visit(ForStmt 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.
|
// 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++));
|
std::string loopVarName("i_" + std::to_string(m_numNestedForLoops++));
|
||||||
m_output << "for { let " << loopVarName << " := 0 } "
|
m_output << "for { let " << loopVarName << " := 0 } "
|
||||||
<< "lt(" << loopVarName << ", 0x60) "
|
<< "lt(" << loopVarName << ", 0x60) "
|
||||||
<< "{ " << loopVarName << " := add(" << loopVarName << ", 0x20) } ";
|
<< "{ " << loopVarName << " := add(" << loopVarName << ", 0x20) } ";
|
||||||
m_inForScope.push(true);
|
// Store previous for body scope
|
||||||
|
bool wasInForBody = m_inForBodyScope;
|
||||||
|
bool wasInForInit = m_inForInitScope;
|
||||||
|
m_inForBodyScope = true;
|
||||||
|
m_inForInitScope = false;
|
||||||
visit(_x.for_body());
|
visit(_x.for_body());
|
||||||
m_inForScope.pop();
|
// Restore previous for body scope and init
|
||||||
--m_numNestedForLoops;
|
m_inForBodyScope = wasInForBody;
|
||||||
|
m_inForInitScope = wasInForInit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtoConverter::visit(CaseStmt const& _x)
|
void ProtoConverter::visit(CaseStmt const& _x)
|
||||||
@ -765,7 +788,9 @@ void ProtoConverter::visit(Statement const& _x)
|
|||||||
switch (_x.stmt_oneof_case())
|
switch (_x.stmt_oneof_case())
|
||||||
{
|
{
|
||||||
case Statement::kDecl:
|
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;
|
break;
|
||||||
case Statement::kAssignment:
|
case Statement::kAssignment:
|
||||||
visit(_x.assignment());
|
visit(_x.assignment());
|
||||||
@ -782,15 +807,18 @@ void ProtoConverter::visit(Statement const& _x)
|
|||||||
case Statement::kForstmt:
|
case Statement::kForstmt:
|
||||||
visit(_x.forstmt());
|
visit(_x.forstmt());
|
||||||
break;
|
break;
|
||||||
|
case Statement::kBoundedforstmt:
|
||||||
|
visit(_x.boundedforstmt());
|
||||||
|
break;
|
||||||
case Statement::kSwitchstmt:
|
case Statement::kSwitchstmt:
|
||||||
visit(_x.switchstmt());
|
visit(_x.switchstmt());
|
||||||
break;
|
break;
|
||||||
case Statement::kBreakstmt:
|
case Statement::kBreakstmt:
|
||||||
if (m_inForScope.top())
|
if (m_inForBodyScope)
|
||||||
m_output << "break\n";
|
m_output << "break\n";
|
||||||
break;
|
break;
|
||||||
case Statement::kContstmt:
|
case Statement::kContstmt:
|
||||||
if (m_inForScope.top())
|
if (m_inForBodyScope)
|
||||||
m_output << "continue\n";
|
m_output << "continue\n";
|
||||||
break;
|
break;
|
||||||
case Statement::kLogFunc:
|
case Statement::kLogFunc:
|
||||||
|
@ -42,9 +42,10 @@ public:
|
|||||||
{
|
{
|
||||||
m_numLiveVars = 0;
|
m_numLiveVars = 0;
|
||||||
m_numVarsPerScope.push(m_numLiveVars);
|
m_numVarsPerScope.push(m_numLiveVars);
|
||||||
m_numNestedForLoops = 0;
|
|
||||||
m_inForScope.push(false);
|
|
||||||
m_numFunctionSets = 0;
|
m_numFunctionSets = 0;
|
||||||
|
m_inForBodyScope = false;
|
||||||
|
m_inForInitScope = false;
|
||||||
|
m_numNestedForLoops = 0;
|
||||||
}
|
}
|
||||||
ProtoConverter(ProtoConverter const&) = delete;
|
ProtoConverter(ProtoConverter const&) = delete;
|
||||||
ProtoConverter(ProtoConverter&&) = delete;
|
ProtoConverter(ProtoConverter&&) = delete;
|
||||||
@ -69,6 +70,7 @@ private:
|
|||||||
void visit(Statement const&);
|
void visit(Statement const&);
|
||||||
void visit(FunctionDefinition const&);
|
void visit(FunctionDefinition const&);
|
||||||
void visit(ForStmt const&);
|
void visit(ForStmt const&);
|
||||||
|
void visit(BoundedForStmt const&);
|
||||||
void visit(CaseStmt const&);
|
void visit(CaseStmt const&);
|
||||||
void visit(SwitchStmt const&);
|
void visit(SwitchStmt const&);
|
||||||
void visit(TernaryOp const&);
|
void visit(TernaryOp const&);
|
||||||
@ -131,9 +133,6 @@ private:
|
|||||||
std::stack<unsigned> m_numVarsPerScope;
|
std::stack<unsigned> m_numVarsPerScope;
|
||||||
// Number of live variables in function scope
|
// Number of live variables in function scope
|
||||||
unsigned m_numLiveVars;
|
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
|
// Set that is used for deduplicating switch case literals
|
||||||
std::stack<std::set<dev::u256>> m_switchLiteralSetPerScope;
|
std::stack<std::set<dev::u256>> m_switchLiteralSetPerScope;
|
||||||
// Total number of function sets. A function set contains one function of each type defined by
|
// 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.
|
// 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 modInputParams = 5;
|
||||||
static unsigned constexpr modOutputParams = 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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,8 +256,15 @@ message IfStmt {
|
|||||||
required Block if_body = 2;
|
required Block if_body = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message BoundedForStmt {
|
||||||
|
required Block for_body = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message ForStmt {
|
message ForStmt {
|
||||||
required Block for_body = 1;
|
required Block for_body = 1;
|
||||||
|
required Block for_init = 2;
|
||||||
|
required Block for_post = 3;
|
||||||
|
required Expression for_cond = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CaseStmt {
|
message CaseStmt {
|
||||||
@ -324,6 +331,7 @@ message Statement {
|
|||||||
ExtCodeCopy extcode_copy = 12;
|
ExtCodeCopy extcode_copy = 12;
|
||||||
TerminatingStmt terminatestmt = 13;
|
TerminatingStmt terminatestmt = 13;
|
||||||
FunctionCall functioncall = 14;
|
FunctionCall functioncall = 14;
|
||||||
|
BoundedForStmt boundedforstmt = 15;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user