mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #7765 from ethereum/fix-7626
yul proto fuzzer: permit variable declarations inside for-init block
This commit is contained in:
commit
9d9a7ebe25
@ -95,18 +95,32 @@ string ProtoConverter::visit(Literal const& _x)
|
|||||||
void ProtoConverter::consolidateVarDeclsInFunctionDef()
|
void ProtoConverter::consolidateVarDeclsInFunctionDef()
|
||||||
{
|
{
|
||||||
m_currentFuncVars.clear();
|
m_currentFuncVars.clear();
|
||||||
|
yulAssert(!m_funcVars.empty(), "Proto fuzzer: Invalid operation");
|
||||||
|
|
||||||
auto const& scopes = m_funcVars.back();
|
auto const& scopes = m_funcVars.back();
|
||||||
for (auto const& s: scopes)
|
for (auto const& s: scopes)
|
||||||
for (auto const& var: s)
|
for (auto const& var: s)
|
||||||
m_currentFuncVars.push_back(&var);
|
m_currentFuncVars.push_back(&var);
|
||||||
|
yulAssert(!m_funcForLoopInitVars.empty(), "Proto fuzzer: Invalid operation");
|
||||||
|
auto const& forinitscopes = m_funcForLoopInitVars.back();
|
||||||
|
for (auto const& s: forinitscopes)
|
||||||
|
for (auto const& var: s)
|
||||||
|
m_currentFuncVars.push_back(&var);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtoConverter::consolidateGlobalVarDecls()
|
void ProtoConverter::consolidateGlobalVarDecls()
|
||||||
{
|
{
|
||||||
m_currentGlobalVars.clear();
|
m_currentGlobalVars.clear();
|
||||||
|
// Place pointers to all global variables that are in scope
|
||||||
|
// into a single vector
|
||||||
for (auto const& scope: m_globalVars)
|
for (auto const& scope: m_globalVars)
|
||||||
for (auto const& var: scope)
|
for (auto const& var: scope)
|
||||||
m_currentGlobalVars.push_back(&var);
|
m_currentGlobalVars.push_back(&var);
|
||||||
|
// Place pointers to all variables declared in for-init blocks
|
||||||
|
// that are still live into the same vector
|
||||||
|
for (auto const& init: m_globalForLoopInitVars)
|
||||||
|
for (auto const& var: init)
|
||||||
|
m_currentGlobalVars.push_back(&var);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProtoConverter::varDeclAvailable()
|
bool ProtoConverter::varDeclAvailable()
|
||||||
@ -283,10 +297,54 @@ void ProtoConverter::visit(VarDecl const& _x)
|
|||||||
m_output << "let " << varName << " := ";
|
m_output << "let " << varName << " := ";
|
||||||
visit(_x.expr());
|
visit(_x.expr());
|
||||||
m_output << "\n";
|
m_output << "\n";
|
||||||
|
// If we are inside a for-init block, there are two places
|
||||||
|
// where the visited vardecl may have been defined:
|
||||||
|
// - directly inside the for-init block
|
||||||
|
// - inside a block within the for-init block
|
||||||
|
// In the latter case, we don't scope extend.
|
||||||
if (m_inFunctionDef)
|
if (m_inFunctionDef)
|
||||||
m_funcVars.back().back().push_back(varName);
|
{
|
||||||
|
// Variables declared directly in for-init block
|
||||||
|
// are tracked separately because their scope
|
||||||
|
// extends beyond the block they are defined in
|
||||||
|
// to the rest of the for-loop statement.
|
||||||
|
if (m_inForInitScope && m_forInitScopeExtEnabled)
|
||||||
|
{
|
||||||
|
yulAssert(
|
||||||
|
!m_funcForLoopInitVars.empty() && !m_funcForLoopInitVars.back().empty(),
|
||||||
|
"Proto fuzzer: Invalid operation"
|
||||||
|
);
|
||||||
|
m_funcForLoopInitVars.back().back().push_back(varName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yulAssert(
|
||||||
|
!m_funcVars.empty() && !m_funcVars.back().empty(),
|
||||||
|
"Proto fuzzer: Invalid operation"
|
||||||
|
);
|
||||||
|
m_funcVars.back().back().push_back(varName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
else
|
else
|
||||||
m_globalVars.back().push_back(varName);
|
{
|
||||||
|
if (m_inForInitScope && m_forInitScopeExtEnabled)
|
||||||
|
{
|
||||||
|
yulAssert(
|
||||||
|
!m_globalForLoopInitVars.empty(),
|
||||||
|
"Proto fuzzer: Invalid operation"
|
||||||
|
);
|
||||||
|
m_globalForLoopInitVars.back().push_back(varName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yulAssert(
|
||||||
|
!m_globalVars.empty(),
|
||||||
|
"Proto fuzzer: Invalid operation"
|
||||||
|
);
|
||||||
|
m_globalVars.back().push_back(varName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtoConverter::visit(TypedVarDecl const& _x)
|
void ProtoConverter::visit(TypedVarDecl const& _x)
|
||||||
@ -351,10 +409,53 @@ void ProtoConverter::visit(TypedVarDecl const& _x)
|
|||||||
m_output << " : u256\n";
|
m_output << " : u256\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// If we are inside a for-init block, there are two places
|
||||||
|
// where the visited vardecl may have been defined:
|
||||||
|
// - directly inside the for-init block
|
||||||
|
// - inside a block within the for-init block
|
||||||
|
// In the latter case, we don't scope extend.
|
||||||
if (m_inFunctionDef)
|
if (m_inFunctionDef)
|
||||||
m_funcVars.back().back().push_back(varName);
|
{
|
||||||
|
// Variables declared directly in for-init block
|
||||||
|
// are tracked separately because their scope
|
||||||
|
// extends beyond the block they are defined in
|
||||||
|
// to the rest of the for-loop statement.
|
||||||
|
if (m_inForInitScope && m_forInitScopeExtEnabled)
|
||||||
|
{
|
||||||
|
yulAssert(
|
||||||
|
!m_funcForLoopInitVars.empty() && !m_funcForLoopInitVars.back().empty(),
|
||||||
|
"Proto fuzzer: Invalid operation"
|
||||||
|
);
|
||||||
|
m_funcForLoopInitVars.back().back().push_back(varName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yulAssert(
|
||||||
|
!m_funcVars.empty() && !m_funcVars.back().empty(),
|
||||||
|
"Proto fuzzer: Invalid operation"
|
||||||
|
);
|
||||||
|
m_funcVars.back().back().push_back(varName);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
m_globalVars.back().push_back(varName);
|
{
|
||||||
|
if (m_inForInitScope && m_forInitScopeExtEnabled)
|
||||||
|
{
|
||||||
|
yulAssert(
|
||||||
|
!m_globalForLoopInitVars.empty(),
|
||||||
|
"Proto fuzzer: Invalid operation"
|
||||||
|
);
|
||||||
|
m_globalForLoopInitVars.back().push_back(varName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yulAssert(
|
||||||
|
!m_globalVars.empty(),
|
||||||
|
"Proto fuzzer: Invalid operation"
|
||||||
|
);
|
||||||
|
m_globalVars.back().push_back(varName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtoConverter::visit(UnaryOp const& _x)
|
void ProtoConverter::visit(UnaryOp const& _x)
|
||||||
@ -713,30 +814,27 @@ void ProtoConverter::visit(FunctionCall const& _x)
|
|||||||
convertFunctionCall(_x, funcName, numInParams, /*newLine=*/false);
|
convertFunctionCall(_x, funcName, numInParams, /*newLine=*/false);
|
||||||
break;
|
break;
|
||||||
case FunctionCall::MULTIDECL:
|
case FunctionCall::MULTIDECL:
|
||||||
// Hack: Disallow (multi) variable declarations until scope extension
|
{
|
||||||
// is implemented for "for-init"
|
// Ensure that the chosen function returns at most 4 values
|
||||||
if (!m_inForInitScope)
|
yulAssert(
|
||||||
{
|
numOutParams <= 4,
|
||||||
// Ensure that the chosen function returns at most 4 values
|
"Proto fuzzer: Function call with too many output params encountered."
|
||||||
yulAssert(
|
);
|
||||||
numOutParams <= 4,
|
|
||||||
"Proto fuzzer: Function call with too many output params encountered."
|
|
||||||
);
|
|
||||||
|
|
||||||
// Obtain variable name suffix
|
// Obtain variable name suffix
|
||||||
unsigned startIdx = counter();
|
unsigned startIdx = counter();
|
||||||
vector<string> varsVec = createVarDecls(
|
vector<string> varsVec = createVarDecls(
|
||||||
startIdx,
|
startIdx,
|
||||||
startIdx + numOutParams,
|
startIdx + numOutParams,
|
||||||
/*isAssignment=*/true
|
/*isAssignment=*/true
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create RHS of multi var decl
|
// Create RHS of multi var decl
|
||||||
convertFunctionCall(_x, funcName, numInParams);
|
convertFunctionCall(_x, funcName, numInParams);
|
||||||
// Add newly minted vars in the multidecl statement to current scope
|
// Add newly minted vars in the multidecl statement to current scope
|
||||||
addVarsToScope(varsVec);
|
addVarsToScope(varsVec);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case FunctionCall::MULTIASSIGN:
|
case FunctionCall::MULTIASSIGN:
|
||||||
// Ensure that the chosen function returns at most 4 values
|
// Ensure that the chosen function returns at most 4 values
|
||||||
yulAssert(
|
yulAssert(
|
||||||
@ -749,22 +847,22 @@ void ProtoConverter::visit(FunctionCall const& _x)
|
|||||||
// This helps reduce the size of this switch statement.
|
// This helps reduce the size of this switch statement.
|
||||||
switch (numOutParams)
|
switch (numOutParams)
|
||||||
{
|
{
|
||||||
case 4:
|
case 4:
|
||||||
visit(_x.out_param4());
|
visit(_x.out_param4());
|
||||||
m_output << ", ";
|
m_output << ", ";
|
||||||
BOOST_FALLTHROUGH;
|
BOOST_FALLTHROUGH;
|
||||||
case 3:
|
case 3:
|
||||||
visit(_x.out_param3());
|
visit(_x.out_param3());
|
||||||
m_output << ", ";
|
m_output << ", ";
|
||||||
BOOST_FALLTHROUGH;
|
BOOST_FALLTHROUGH;
|
||||||
case 2:
|
case 2:
|
||||||
visit(_x.out_param2());
|
visit(_x.out_param2());
|
||||||
m_output << ", ";
|
m_output << ", ";
|
||||||
visit(_x.out_param1());
|
visit(_x.out_param1());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
yulAssert(false, "Proto fuzzer: Function call with too many or too few input parameters.");
|
yulAssert(false, "Proto fuzzer: Function call with too many or too few input parameters.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
m_output << " := ";
|
m_output << " := ";
|
||||||
|
|
||||||
@ -868,17 +966,33 @@ void ProtoConverter::visit(ForStmt const& _x)
|
|||||||
{
|
{
|
||||||
bool wasInForBody = m_inForBodyScope;
|
bool wasInForBody = m_inForBodyScope;
|
||||||
bool wasInForInit = m_inForInitScope;
|
bool wasInForInit = m_inForInitScope;
|
||||||
|
bool wasForInitScopeExtEnabled = m_forInitScopeExtEnabled;
|
||||||
m_inForBodyScope = false;
|
m_inForBodyScope = false;
|
||||||
m_inForInitScope = true;
|
m_inForInitScope = true;
|
||||||
|
m_forInitScopeExtEnabled = true;
|
||||||
m_output << "for ";
|
m_output << "for ";
|
||||||
visit(_x.for_init());
|
visit(_x.for_init());
|
||||||
m_inForInitScope = false;
|
m_inForInitScope = false;
|
||||||
|
m_forInitScopeExtEnabled = wasForInitScopeExtEnabled;
|
||||||
visit(_x.for_cond());
|
visit(_x.for_cond());
|
||||||
visit(_x.for_post());
|
visit(_x.for_post());
|
||||||
m_inForBodyScope = true;
|
m_inForBodyScope = true;
|
||||||
visit(_x.for_body());
|
visit(_x.for_body());
|
||||||
m_inForBodyScope = wasInForBody;
|
m_inForBodyScope = wasInForBody;
|
||||||
m_inForInitScope = wasInForInit;
|
m_inForInitScope = wasInForInit;
|
||||||
|
if (m_inFunctionDef)
|
||||||
|
{
|
||||||
|
yulAssert(
|
||||||
|
!m_funcForLoopInitVars.empty() && !m_funcForLoopInitVars.back().empty(),
|
||||||
|
"Proto fuzzer: Invalid data structure");
|
||||||
|
// Remove variables in for-init
|
||||||
|
m_funcForLoopInitVars.back().pop_back();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yulAssert(!m_globalForLoopInitVars.empty(), "Proto fuzzer: Invalid data structure");
|
||||||
|
m_globalForLoopInitVars.pop_back();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtoConverter::visit(BoundedForStmt const& _x)
|
void ProtoConverter::visit(BoundedForStmt const& _x)
|
||||||
@ -1065,9 +1179,7 @@ void ProtoConverter::visit(Statement const& _x)
|
|||||||
switch (_x.stmt_oneof_case())
|
switch (_x.stmt_oneof_case())
|
||||||
{
|
{
|
||||||
case Statement::kDecl:
|
case Statement::kDecl:
|
||||||
// Hack: Disallow (multi) variable declarations until scope extension is implemented for "for-init"
|
visit(_x.decl());
|
||||||
if (!m_inForInitScope)
|
|
||||||
visit(_x.decl());
|
|
||||||
break;
|
break;
|
||||||
case Statement::kAssignment:
|
case Statement::kAssignment:
|
||||||
// Create an assignment statement only if there is at least one variable
|
// Create an assignment statement only if there is at least one variable
|
||||||
@ -1138,16 +1250,36 @@ void ProtoConverter::visit(Statement const& _x)
|
|||||||
void ProtoConverter::openBlockScope()
|
void ProtoConverter::openBlockScope()
|
||||||
{
|
{
|
||||||
m_scopeFuncs.push_back({});
|
m_scopeFuncs.push_back({});
|
||||||
|
|
||||||
// Create new block scope inside current function scope
|
// Create new block scope inside current function scope
|
||||||
if (m_inFunctionDef)
|
if (m_inFunctionDef)
|
||||||
|
{
|
||||||
|
yulAssert(
|
||||||
|
!m_funcVars.empty(),
|
||||||
|
"Proto fuzzer: Invalid data structure"
|
||||||
|
);
|
||||||
m_funcVars.back().push_back(vector<string>{});
|
m_funcVars.back().push_back(vector<string>{});
|
||||||
|
if (m_inForInitScope && m_forInitScopeExtEnabled)
|
||||||
|
{
|
||||||
|
yulAssert(
|
||||||
|
!m_funcForLoopInitVars.empty(),
|
||||||
|
"Proto fuzzer: Invalid data structure"
|
||||||
|
);
|
||||||
|
m_funcForLoopInitVars.back().push_back(vector<string>{});
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
m_globalVars.push_back(vector<string>{});
|
{
|
||||||
|
m_globalVars.push_back({});
|
||||||
|
if (m_inForInitScope && m_forInitScopeExtEnabled)
|
||||||
|
m_globalForLoopInitVars.push_back(vector<string>{});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtoConverter::openFunctionScope(vector<string> const& _funcParams)
|
void ProtoConverter::openFunctionScope(vector<string> const& _funcParams)
|
||||||
{
|
{
|
||||||
m_funcVars.push_back(vector<vector<string>>({_funcParams}));
|
m_funcVars.push_back(vector<vector<string>>({_funcParams}));
|
||||||
|
m_funcForLoopInitVars.push_back(vector<vector<string>>({}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtoConverter::updateFunctionMaps(string const& _var)
|
void ProtoConverter::updateFunctionMaps(string const& _var)
|
||||||
@ -1166,6 +1298,8 @@ void ProtoConverter::updateFunctionMaps(string const& _var)
|
|||||||
|
|
||||||
void ProtoConverter::closeBlockScope()
|
void ProtoConverter::closeBlockScope()
|
||||||
{
|
{
|
||||||
|
// Remove functions declared in the block that is going
|
||||||
|
// out of scope from the global function map.
|
||||||
for (auto const& f: m_scopeFuncs.back())
|
for (auto const& f: m_scopeFuncs.back())
|
||||||
{
|
{
|
||||||
unsigned numFuncsRemoved = m_functions.size();
|
unsigned numFuncsRemoved = m_functions.size();
|
||||||
@ -1177,35 +1311,95 @@ void ProtoConverter::closeBlockScope()
|
|||||||
);
|
);
|
||||||
updateFunctionMaps(f);
|
updateFunctionMaps(f);
|
||||||
}
|
}
|
||||||
|
// Pop back the vector of scoped functions.
|
||||||
if (!m_scopeFuncs.empty())
|
if (!m_scopeFuncs.empty())
|
||||||
m_scopeFuncs.pop_back();
|
m_scopeFuncs.pop_back();
|
||||||
if (!m_inFunctionDef)
|
|
||||||
|
// If block belongs to function body, then remove
|
||||||
|
// local variables in function body that are going out of scope.
|
||||||
|
if (m_inFunctionDef)
|
||||||
{
|
{
|
||||||
if (!m_globalVars.empty())
|
yulAssert(!m_funcVars.empty(), "Proto fuzzer: Invalid data structure");
|
||||||
m_globalVars.pop_back();
|
if (!m_funcVars.back().empty())
|
||||||
|
m_funcVars.back().pop_back();
|
||||||
}
|
}
|
||||||
|
// Remove variables declared in vanilla block from current
|
||||||
|
// global scope.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Variables that have been declared in a
|
yulAssert(!m_globalVars.empty(), "Proto fuzzer: Invalid data structure");
|
||||||
// function block, go out of scope
|
m_globalVars.pop_back();
|
||||||
if (!m_funcVars.empty())
|
|
||||||
if (!m_funcVars.back().empty())
|
|
||||||
m_funcVars.back().pop_back();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtoConverter::closeFunctionScope()
|
void ProtoConverter::closeFunctionScope()
|
||||||
{
|
{
|
||||||
if (!m_funcVars.empty())
|
yulAssert(!m_funcVars.empty(), "Proto fuzzer: Invalid data structure");
|
||||||
m_funcVars.pop_back();
|
m_funcVars.pop_back();
|
||||||
|
yulAssert(!m_funcForLoopInitVars.empty(), "Proto fuzzer: Invalid data structure");
|
||||||
|
m_funcForLoopInitVars.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtoConverter::addVarsToScope(vector<string> const& _vars)
|
void ProtoConverter::addVarsToScope(vector<string> const& _vars)
|
||||||
{
|
{
|
||||||
|
// If we are in function definition, add the new vars to current function scope
|
||||||
if (m_inFunctionDef)
|
if (m_inFunctionDef)
|
||||||
m_funcVars.back().back().insert(m_funcVars.back().back().end(), _vars.begin(), _vars.end());
|
{
|
||||||
|
// If we are directly in for-init block, add the newly created vars to the
|
||||||
|
// stack of for-init variables.
|
||||||
|
if (m_inForInitScope && m_forInitScopeExtEnabled)
|
||||||
|
{
|
||||||
|
yulAssert(
|
||||||
|
!m_funcForLoopInitVars.empty() && !m_funcForLoopInitVars.back().empty(),
|
||||||
|
"Proto fuzzer: Invalid data structure"
|
||||||
|
);
|
||||||
|
m_funcForLoopInitVars.back().back().insert(
|
||||||
|
m_funcForLoopInitVars.back().back().end(),
|
||||||
|
_vars.begin(),
|
||||||
|
_vars.end()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yulAssert(
|
||||||
|
!m_funcVars.empty() && !m_funcVars.back().empty(),
|
||||||
|
"Proto fuzzer: Invalid data structure"
|
||||||
|
);
|
||||||
|
m_funcVars.back().back().insert(
|
||||||
|
m_funcVars.back().back().end(),
|
||||||
|
_vars.begin(),
|
||||||
|
_vars.end()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we are in a vanilla block, add the new vars to current global scope
|
||||||
else
|
else
|
||||||
m_globalVars.back().insert(m_globalVars.back().end(), _vars.begin(), _vars.end());
|
{
|
||||||
|
if (m_inForInitScope && m_forInitScopeExtEnabled)
|
||||||
|
{
|
||||||
|
yulAssert(
|
||||||
|
!m_globalForLoopInitVars.empty(),
|
||||||
|
"Proto fuzzer: Invalid data structure"
|
||||||
|
);
|
||||||
|
m_globalForLoopInitVars.back().insert(
|
||||||
|
m_globalForLoopInitVars.back().end(),
|
||||||
|
_vars.begin(),
|
||||||
|
_vars.end()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yulAssert(
|
||||||
|
!m_globalVars.empty(),
|
||||||
|
"Proto fuzzer: Invalid data structure"
|
||||||
|
);
|
||||||
|
m_globalVars.back().insert(
|
||||||
|
m_globalVars.back().end(),
|
||||||
|
_vars.begin(),
|
||||||
|
_vars.end()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtoConverter::visit(Block const& _x)
|
void ProtoConverter::visit(Block const& _x)
|
||||||
@ -1222,8 +1416,20 @@ void ProtoConverter::visit(Block const& _x)
|
|||||||
if (_x.statements_size() > 0)
|
if (_x.statements_size() > 0)
|
||||||
{
|
{
|
||||||
m_output << "{\n";
|
m_output << "{\n";
|
||||||
|
bool wasForInitScopeExtEnabled = m_forInitScopeExtEnabled;
|
||||||
for (auto const& st: _x.statements())
|
for (auto const& st: _x.statements())
|
||||||
|
{
|
||||||
|
// If statement is block or introduces one and we are in for-init block
|
||||||
|
// then temporarily disable scope extension if it is not already disabled.
|
||||||
|
if (
|
||||||
|
(st.has_blockstmt() || st.has_switchstmt() || st.has_ifstmt()) &&
|
||||||
|
m_inForInitScope &&
|
||||||
|
m_forInitScopeExtEnabled
|
||||||
|
)
|
||||||
|
m_forInitScopeExtEnabled = false;
|
||||||
visit(st);
|
visit(st);
|
||||||
|
m_forInitScopeExtEnabled = wasForInitScopeExtEnabled;
|
||||||
|
}
|
||||||
m_output << "}\n";
|
m_output << "}\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -48,6 +48,7 @@ public:
|
|||||||
m_inFunctionDef = false;
|
m_inFunctionDef = false;
|
||||||
m_objectId = 0;
|
m_objectId = 0;
|
||||||
m_isObject = false;
|
m_isObject = false;
|
||||||
|
m_forInitScopeExtEnabled = true;
|
||||||
}
|
}
|
||||||
ProtoConverter(ProtoConverter const&) = delete;
|
ProtoConverter(ProtoConverter const&) = delete;
|
||||||
ProtoConverter(ProtoConverter&&) = delete;
|
ProtoConverter(ProtoConverter&&) = delete;
|
||||||
@ -314,9 +315,13 @@ private:
|
|||||||
std::vector<std::string const*> m_currentGlobalVars;
|
std::vector<std::string const*> m_currentGlobalVars;
|
||||||
/// Functions in current scope
|
/// Functions in current scope
|
||||||
std::vector<std::vector<std::string>> m_scopeFuncs;
|
std::vector<std::vector<std::string>> m_scopeFuncs;
|
||||||
/// Variables
|
/// Global variables
|
||||||
std::vector<std::vector<std::string>> m_globalVars;
|
std::vector<std::vector<std::string>> m_globalVars;
|
||||||
/// Functions
|
/// Variables declared in for loop init block that is in global scope
|
||||||
|
std::vector<std::vector<std::string>> m_globalForLoopInitVars;
|
||||||
|
/// Variables declared in for loop init block that is in function scope
|
||||||
|
std::vector<std::vector<std::vector<std::string>>> m_funcForLoopInitVars;
|
||||||
|
/// Vector of function names
|
||||||
std::vector<std::string> m_functions;
|
std::vector<std::string> m_functions;
|
||||||
/// Maps FunctionDef object to its name
|
/// Maps FunctionDef object to its name
|
||||||
std::map<FunctionDef const*, std::string> m_functionDefMap;
|
std::map<FunctionDef const*, std::string> m_functionDefMap;
|
||||||
@ -331,7 +336,7 @@ private:
|
|||||||
static unsigned constexpr s_modOutputParams = 5;
|
static unsigned constexpr s_modOutputParams = 5;
|
||||||
/// Hard-coded identifier for a Yul object's data block
|
/// Hard-coded identifier for a Yul object's data block
|
||||||
static auto constexpr s_dataIdentifier = "datablock";
|
static auto constexpr s_dataIdentifier = "datablock";
|
||||||
/// Predicate to keep track of for body scope. If true, break/continue
|
/// Predicate to keep track of for body scope. If false, break/continue
|
||||||
/// statements can not be created.
|
/// statements can not be created.
|
||||||
bool m_inForBodyScope;
|
bool m_inForBodyScope;
|
||||||
// Index used for naming loop variable of bounded for loops
|
// Index used for naming loop variable of bounded for loops
|
||||||
@ -350,5 +355,8 @@ private:
|
|||||||
/// Flag to track whether program is an object (true) or a statement block
|
/// Flag to track whether program is an object (true) or a statement block
|
||||||
/// (false: default value)
|
/// (false: default value)
|
||||||
bool m_isObject;
|
bool m_isObject;
|
||||||
|
/// Flag to track whether scope extension of variables defined in for-init
|
||||||
|
/// block is enabled.
|
||||||
|
bool m_forInitScopeExtEnabled;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user