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(ContinueStmtGenerator) SEP \
|
||||||
MACRO(ContractGenerator) SEP \
|
MACRO(ContractGenerator) SEP \
|
||||||
MACRO(ExpressionStmtGenerator) SEP \
|
MACRO(ExpressionStmtGenerator) SEP \
|
||||||
|
MACRO(ForStmtGenerator) SEP \
|
||||||
MACRO(FunctionCallGenerator) SEP \
|
MACRO(FunctionCallGenerator) SEP \
|
||||||
MACRO(FunctionGenerator) SEP \
|
MACRO(FunctionGenerator) SEP \
|
||||||
MACRO(IfStmtGenerator) SEP \
|
MACRO(IfStmtGenerator) SEP \
|
||||||
@ -55,4 +56,5 @@
|
|||||||
MACRO(SourceUnitGenerator) SEP \
|
MACRO(SourceUnitGenerator) SEP \
|
||||||
MACRO(StatementGenerator) SEP \
|
MACRO(StatementGenerator) SEP \
|
||||||
MACRO(TestCaseGenerator) SEP \
|
MACRO(TestCaseGenerator) SEP \
|
||||||
|
MACRO(VarDeclStmtGenerator) SEP \
|
||||||
MACRO(WhileStmtGenerator) ENDSEP
|
MACRO(WhileStmtGenerator) ENDSEP
|
||||||
|
|||||||
@ -416,11 +416,11 @@ string AssignmentStmtGenerator::visit()
|
|||||||
auto lhs = exprGen.randomLValueExpression();
|
auto lhs = exprGen.randomLValueExpression();
|
||||||
exprGen.resetNestingDepth();
|
exprGen.resetNestingDepth();
|
||||||
if (!lhs.has_value())
|
if (!lhs.has_value())
|
||||||
return "\n";
|
return {};
|
||||||
auto rhs = exprGen.rLValueOrLiteral(lhs.value());
|
auto rhs = exprGen.rLValueOrLiteral(lhs.value());
|
||||||
exprGen.resetNestingDepth();
|
exprGen.resetNestingDepth();
|
||||||
if (!rhs.has_value())
|
if (!rhs.has_value())
|
||||||
return "\n";
|
return {};
|
||||||
auto operation = assignOp(lhs.value().first);
|
auto operation = assignOp(lhs.value().first);
|
||||||
return indentation() + lhs.value().second + assignOp(operation) + rhs.value().second + ";\n";
|
return indentation() + lhs.value().second + assignOp(operation) + rhs.value().second + ";\n";
|
||||||
}
|
}
|
||||||
@ -434,7 +434,30 @@ string ExpressionStmtGenerator::visit()
|
|||||||
if (expression.has_value())
|
if (expression.has_value())
|
||||||
return indentation() + expression.value().second + ";\n";
|
return indentation() + expression.value().second + ";\n";
|
||||||
else
|
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()
|
void IfStmtGenerator::setup()
|
||||||
@ -538,10 +561,91 @@ string WhileStmtGenerator::visit()
|
|||||||
whileStmt << indentation()
|
whileStmt << indentation()
|
||||||
<< "while ("
|
<< "while ("
|
||||||
<< expression.value().second
|
<< expression.value().second
|
||||||
<< ")\n";
|
<< ");\n";
|
||||||
return whileStmt.str();
|
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()
|
void StatementGenerator::setup()
|
||||||
{
|
{
|
||||||
set<pair<GeneratorPtr, unsigned>> dependsOn = {
|
set<pair<GeneratorPtr, unsigned>> dependsOn = {
|
||||||
@ -552,7 +656,9 @@ void StatementGenerator::setup()
|
|||||||
{mutator->generator<IfStmtGenerator>(), 2},
|
{mutator->generator<IfStmtGenerator>(), 2},
|
||||||
{mutator->generator<WhileStmtGenerator>(), 1},
|
{mutator->generator<WhileStmtGenerator>(), 1},
|
||||||
{mutator->generator<BreakStmtGenerator>(), 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));
|
addGenerators(std::move(dependsOn));
|
||||||
}
|
}
|
||||||
@ -1371,8 +1477,7 @@ string FunctionCallGenerator::lhs(vector<pair<SolidityTypePtr, string>>& _functi
|
|||||||
{
|
{
|
||||||
auto newVars = _functionReturnTypeNames |
|
auto newVars = _functionReturnTypeNames |
|
||||||
ranges::views::transform([&](auto const& _item) -> string {
|
ranges::views::transform([&](auto const& _item) -> string {
|
||||||
state->currentFunctionState()->addLocal(_item.first);
|
string varName = state->currentFunctionState()->addLocal(_item.first);
|
||||||
string varName = state->currentFunctionState()->scopes.back()->variables.back().second;
|
|
||||||
return std::visit(
|
return std::visit(
|
||||||
GenericVisitor{[](auto const& _it) { return _it->toString(); }},
|
GenericVisitor{[](auto const& _it) { return _it->toString(); }},
|
||||||
_item.first
|
_item.first
|
||||||
@ -1474,7 +1579,7 @@ string FunctionCallGenerator::visit()
|
|||||||
if (state->insideContract)
|
if (state->insideContract)
|
||||||
availableFunctions += state->currentContractState()->functions;
|
availableFunctions += state->currentContractState()->functions;
|
||||||
if (availableFunctions.empty())
|
if (availableFunctions.empty())
|
||||||
return "\n";
|
return {};
|
||||||
|
|
||||||
shared_ptr<FunctionState> callee;
|
shared_ptr<FunctionState> callee;
|
||||||
if (availableFunctions.size() > 1)
|
if (availableFunctions.size() > 1)
|
||||||
@ -1489,7 +1594,7 @@ string FunctionCallGenerator::visit()
|
|||||||
if (callee)
|
if (callee)
|
||||||
return callStmt(callee);
|
return callStmt(callee);
|
||||||
else
|
else
|
||||||
return "\n";
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
@ -466,9 +466,11 @@ struct FunctionState
|
|||||||
type->addOutput(_output);
|
type->addOutput(_output);
|
||||||
outputs.emplace_back(std::move(_output), "o" + std::to_string(numOutpus++));
|
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);
|
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
|
class IfStmtGenerator: public GeneratorBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -1162,6 +1177,17 @@ public:
|
|||||||
std::string name() override { return "While statement generator"; }
|
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
|
class AssignmentStmtGenerator: public GeneratorBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user