mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Introduce vardecl and for stmts.
This commit is contained in:
parent
c07d24c66d
commit
8cbdd1fc2f
@ -47,6 +47,7 @@
|
||||
MACRO(ContinueStmtGenerator) SEP \
|
||||
MACRO(ContractGenerator) SEP \
|
||||
MACRO(ExpressionStmtGenerator) SEP \
|
||||
MACRO(ForStmtGenerator) SEP \
|
||||
MACRO(FunctionCallGenerator) SEP \
|
||||
MACRO(FunctionGenerator) SEP \
|
||||
MACRO(IfStmtGenerator) SEP \
|
||||
@ -55,4 +56,5 @@
|
||||
MACRO(SourceUnitGenerator) SEP \
|
||||
MACRO(StatementGenerator) SEP \
|
||||
MACRO(TestCaseGenerator) SEP \
|
||||
MACRO(VarDeclStmtGenerator) SEP \
|
||||
MACRO(WhileStmtGenerator) ENDSEP
|
||||
|
||||
@ -416,11 +416,11 @@ string AssignmentStmtGenerator::visit()
|
||||
auto lhs = exprGen.randomLValueExpression();
|
||||
exprGen.resetNestingDepth();
|
||||
if (!lhs.has_value())
|
||||
return "\n";
|
||||
return {};
|
||||
auto rhs = exprGen.rLValueOrLiteral(lhs.value());
|
||||
exprGen.resetNestingDepth();
|
||||
if (!rhs.has_value())
|
||||
return "\n";
|
||||
return {};
|
||||
auto operation = assignOp(lhs.value().first);
|
||||
return indentation() + lhs.value().second + assignOp(operation) + rhs.value().second + ";\n";
|
||||
}
|
||||
@ -434,7 +434,30 @@ string ExpressionStmtGenerator::visit()
|
||||
if (expression.has_value())
|
||||
return indentation() + expression.value().second + ";\n";
|
||||
else
|
||||
return "\n";
|
||||
return {};
|
||||
}
|
||||
|
||||
string VarDeclStmtGenerator::visit()
|
||||
{
|
||||
ExpressionGenerator exprGen{state};
|
||||
auto randomType = TypeProvider{state}.type();
|
||||
pair<SolidityTypePtr, string> randomTypeName = {randomType, {}};
|
||||
auto expression = exprGen.rLValueOrLiteral(randomTypeName);
|
||||
string varName = state->currentFunctionState()->addLocal(randomTypeName.first);
|
||||
string varDeclStmt = indentation() +
|
||||
std::visit(
|
||||
GenericVisitor{[](auto const& _it) { return _it->toString(); }},
|
||||
randomTypeName.first
|
||||
) +
|
||||
" " +
|
||||
varName;
|
||||
if (expression.has_value())
|
||||
varDeclStmt += " = " +
|
||||
expression.value().second +
|
||||
";\n";
|
||||
else
|
||||
varDeclStmt += ";\n";
|
||||
return varDeclStmt;
|
||||
}
|
||||
|
||||
void IfStmtGenerator::setup()
|
||||
@ -538,10 +561,91 @@ string WhileStmtGenerator::visit()
|
||||
whileStmt << indentation()
|
||||
<< "while ("
|
||||
<< expression.value().second
|
||||
<< ")\n";
|
||||
<< ");\n";
|
||||
return whileStmt.str();
|
||||
}
|
||||
|
||||
void ForStmtGenerator::setup()
|
||||
{
|
||||
set<pair<GeneratorPtr, unsigned>> dependsOn = {
|
||||
{mutator->generator<BlockStmtGenerator>(), 1},
|
||||
{mutator->generator<ExpressionStmtGenerator>(), 1},
|
||||
{mutator->generator<VarDeclStmtGenerator>(), 1}
|
||||
};
|
||||
addGenerators(std::move(dependsOn));
|
||||
}
|
||||
|
||||
string ForStmtGenerator::visit()
|
||||
{
|
||||
state->enterLoop();
|
||||
ScopeGuard exitLoop([&]() { state->exitLoop(); });
|
||||
size_t preStmtChoice = uRandDist()->distributionOneToN(3);
|
||||
string simpleStmt;
|
||||
bool forInitIsVarDecl = false;
|
||||
switch (preStmtChoice)
|
||||
{
|
||||
case 1:
|
||||
simpleStmt = mutator->generator<ExpressionStmtGenerator>()->generate();
|
||||
if (simpleStmt.empty())
|
||||
{
|
||||
forInitIsVarDecl = true;
|
||||
simpleStmt = mutator->generator<VarDeclStmtGenerator>()->generate();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
simpleStmt = mutator->generator<VarDeclStmtGenerator>()->generate();
|
||||
forInitIsVarDecl = true;
|
||||
break;
|
||||
case 3:
|
||||
simpleStmt = ";\n";
|
||||
break;
|
||||
}
|
||||
string forCondition;
|
||||
bool hasCondition = uRandDist()->probable(2);
|
||||
if (hasCondition)
|
||||
{
|
||||
ExpressionGenerator exprGen{state};
|
||||
auto boolType = make_shared<BoolType>();
|
||||
pair<SolidityTypePtr, string> boolTypeName = {boolType, {}};
|
||||
auto expression = exprGen.rLValueOrLiteral(boolTypeName);
|
||||
if (expression.has_value())
|
||||
forCondition = expression.value().second + ";\n";
|
||||
else
|
||||
forCondition = ";\n";
|
||||
}
|
||||
else
|
||||
forCondition = ";\n";
|
||||
string postStmt;
|
||||
bool hasPostStmt = uRandDist()->probable(2);
|
||||
if (hasPostStmt)
|
||||
{
|
||||
ExpressionGenerator exprGen{state};
|
||||
auto randomType = TypeProvider{state}.type();
|
||||
pair<SolidityTypePtr, string> randomTypeName = {randomType, {}};
|
||||
auto expression = exprGen.rLValueOrLiteral(randomTypeName);
|
||||
if (expression.has_value())
|
||||
postStmt = expression.value().second;
|
||||
}
|
||||
// Make sure block stmt generator does not output an unchecked block
|
||||
mutator->generator<BlockStmtGenerator>()->unchecked(false);
|
||||
ostringstream forBlock;
|
||||
forBlock << mutator->generator<BlockStmtGenerator>()->generate();
|
||||
if (forBlock.str().empty())
|
||||
forBlock << indentation() << "{ }\n";
|
||||
string forStmt;
|
||||
forStmt = indentation() +
|
||||
"for(" +
|
||||
simpleStmt +
|
||||
forCondition +
|
||||
postStmt +
|
||||
")\n" +
|
||||
forBlock.str();
|
||||
// Manually out of scope variable declaration in for init stmt.
|
||||
if (forInitIsVarDecl)
|
||||
state->currentFunctionState()->scopes.back()->variables.pop_back();
|
||||
return forStmt;
|
||||
}
|
||||
|
||||
void StatementGenerator::setup()
|
||||
{
|
||||
set<pair<GeneratorPtr, unsigned>> dependsOn = {
|
||||
@ -552,7 +656,9 @@ void StatementGenerator::setup()
|
||||
{mutator->generator<IfStmtGenerator>(), 2},
|
||||
{mutator->generator<WhileStmtGenerator>(), 1},
|
||||
{mutator->generator<BreakStmtGenerator>(), 1},
|
||||
{mutator->generator<ContinueStmtGenerator>(), 1}
|
||||
{mutator->generator<ContinueStmtGenerator>(), 1},
|
||||
{mutator->generator<VarDeclStmtGenerator>(), 1},
|
||||
{mutator->generator<ForStmtGenerator>(), 1}
|
||||
};
|
||||
addGenerators(std::move(dependsOn));
|
||||
}
|
||||
@ -1371,8 +1477,7 @@ string FunctionCallGenerator::lhs(vector<pair<SolidityTypePtr, string>>& _functi
|
||||
{
|
||||
auto newVars = _functionReturnTypeNames |
|
||||
ranges::views::transform([&](auto const& _item) -> string {
|
||||
state->currentFunctionState()->addLocal(_item.first);
|
||||
string varName = state->currentFunctionState()->scopes.back()->variables.back().second;
|
||||
string varName = state->currentFunctionState()->addLocal(_item.first);
|
||||
return std::visit(
|
||||
GenericVisitor{[](auto const& _it) { return _it->toString(); }},
|
||||
_item.first
|
||||
@ -1474,7 +1579,7 @@ string FunctionCallGenerator::visit()
|
||||
if (state->insideContract)
|
||||
availableFunctions += state->currentContractState()->functions;
|
||||
if (availableFunctions.empty())
|
||||
return "\n";
|
||||
return {};
|
||||
|
||||
shared_ptr<FunctionState> callee;
|
||||
if (availableFunctions.size() > 1)
|
||||
@ -1489,7 +1594,7 @@ string FunctionCallGenerator::visit()
|
||||
if (callee)
|
||||
return callStmt(callee);
|
||||
else
|
||||
return "\n";
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
@ -466,9 +466,11 @@ struct FunctionState
|
||||
type->addOutput(_output);
|
||||
outputs.emplace_back(std::move(_output), "o" + std::to_string(numOutpus++));
|
||||
}
|
||||
void addLocal(SolidityTypePtr _local)
|
||||
std::string addLocal(SolidityTypePtr _local)
|
||||
{
|
||||
scopes.back()->variables.emplace_back(std::move(_local), "l" + std::to_string(numLocals++));
|
||||
std::string varName = "l" + std::to_string(numLocals++);
|
||||
scopes.back()->variables.emplace_back(std::move(_local), varName);
|
||||
return varName;
|
||||
}
|
||||
std::string params(Params _p);
|
||||
|
||||
@ -1098,6 +1100,19 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class VarDeclStmtGenerator: public GeneratorBase
|
||||
{
|
||||
public:
|
||||
explicit VarDeclStmtGenerator(SolidityGenerator* _mutator):
|
||||
GeneratorBase(std::move(_mutator))
|
||||
{}
|
||||
std::string visit() override;
|
||||
std::string name() override
|
||||
{
|
||||
return "VarDecl statement generator";
|
||||
}
|
||||
};
|
||||
|
||||
class IfStmtGenerator: public GeneratorBase
|
||||
{
|
||||
public:
|
||||
@ -1162,6 +1177,17 @@ public:
|
||||
std::string name() override { return "While statement generator"; }
|
||||
};
|
||||
|
||||
class ForStmtGenerator: public GeneratorBase
|
||||
{
|
||||
public:
|
||||
explicit ForStmtGenerator(SolidityGenerator* _mutator):
|
||||
GeneratorBase(std::move(_mutator))
|
||||
{}
|
||||
void setup() override;
|
||||
std::string visit() override;
|
||||
std::string name() override { return "For statement generator"; }
|
||||
};
|
||||
|
||||
class AssignmentStmtGenerator: public GeneratorBase
|
||||
{
|
||||
public:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user