mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Introduce break/continue statements and fix stmt genarator logic
This commit is contained in:
parent
3d4787bb15
commit
67644c0763
@ -43,6 +43,8 @@
|
|||||||
#define GENERATORLIST(MACRO, SEP, ENDSEP) \
|
#define GENERATORLIST(MACRO, SEP, ENDSEP) \
|
||||||
MACRO(AssignmentStmtGenerator) SEP \
|
MACRO(AssignmentStmtGenerator) SEP \
|
||||||
MACRO(BlockStmtGenerator) SEP \
|
MACRO(BlockStmtGenerator) SEP \
|
||||||
|
MACRO(BreakStmtGenerator) SEP \
|
||||||
|
MACRO(ContinueStmtGenerator) SEP \
|
||||||
MACRO(ContractGenerator) SEP \
|
MACRO(ContractGenerator) SEP \
|
||||||
MACRO(ExpressionStmtGenerator) SEP \
|
MACRO(ExpressionStmtGenerator) SEP \
|
||||||
MACRO(FunctionCallGenerator) SEP \
|
MACRO(FunctionCallGenerator) SEP \
|
||||||
|
|||||||
@ -511,6 +511,8 @@ void WhileStmtGenerator::setup()
|
|||||||
string WhileStmtGenerator::visit()
|
string WhileStmtGenerator::visit()
|
||||||
{
|
{
|
||||||
ostringstream whileStmt;
|
ostringstream whileStmt;
|
||||||
|
state->enterLoop();
|
||||||
|
ScopeGuard exitLoop([&]() { state->exitLoop(); });
|
||||||
ExpressionGenerator exprGen{state};
|
ExpressionGenerator exprGen{state};
|
||||||
auto boolType = make_shared<BoolType>();
|
auto boolType = make_shared<BoolType>();
|
||||||
pair<SolidityTypePtr, string> boolTypeName = {boolType, {}};
|
pair<SolidityTypePtr, string> boolTypeName = {boolType, {}};
|
||||||
@ -538,7 +540,9 @@ void StatementGenerator::setup()
|
|||||||
{mutator->generator<FunctionCallGenerator>(), 1},
|
{mutator->generator<FunctionCallGenerator>(), 1},
|
||||||
{mutator->generator<ExpressionStmtGenerator>(), 1},
|
{mutator->generator<ExpressionStmtGenerator>(), 1},
|
||||||
{mutator->generator<IfStmtGenerator>(), 2},
|
{mutator->generator<IfStmtGenerator>(), 2},
|
||||||
{mutator->generator<WhileStmtGenerator>(), 1}
|
{mutator->generator<WhileStmtGenerator>(), 1},
|
||||||
|
{mutator->generator<BreakStmtGenerator>(), 1},
|
||||||
|
{mutator->generator<ContinueStmtGenerator>(), 1}
|
||||||
};
|
};
|
||||||
addGenerators(std::move(dependsOn));
|
addGenerators(std::move(dependsOn));
|
||||||
}
|
}
|
||||||
@ -553,14 +557,11 @@ string StatementGenerator::visit()
|
|||||||
mutator->generator<BlockStmtGenerator>()->unchecked(true);
|
mutator->generator<BlockStmtGenerator>()->unchecked(true);
|
||||||
|
|
||||||
ostringstream os;
|
ostringstream os;
|
||||||
// Randomise visit order
|
// Choose random statement type
|
||||||
vector<std::pair<GeneratorPtr, unsigned>> randomisedChildren;
|
auto genIterator = generators.begin();
|
||||||
for (auto const& child: generators)
|
auto advanceBy = uRandDist()->distributionOneToN(generators.size()) - 1;
|
||||||
randomisedChildren.push_back(child);
|
std::advance(genIterator, advanceBy);
|
||||||
shuffle(randomisedChildren.begin(), randomisedChildren.end(), *uRandDist()->randomEngine);
|
auto child = *genIterator;
|
||||||
for (auto const& child: randomisedChildren)
|
|
||||||
if (uRandDist()->likely(child.second + 1))
|
|
||||||
{
|
|
||||||
os << std::visit(GenericVisitor{
|
os << std::visit(GenericVisitor{
|
||||||
[](auto const& _item) { return _item->generate(); }
|
[](auto const& _item) { return _item->generate(); }
|
||||||
}, child.first);
|
}, child.first);
|
||||||
@ -571,7 +572,6 @@ string StatementGenerator::visit()
|
|||||||
get<shared_ptr<BlockStmtGenerator>>(child.first)->unchecked(false);
|
get<shared_ptr<BlockStmtGenerator>>(child.first)->unchecked(false);
|
||||||
get<shared_ptr<BlockStmtGenerator>>(child.first)->resetInUnchecked();
|
get<shared_ptr<BlockStmtGenerator>>(child.first)->resetInUnchecked();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -504,6 +504,13 @@ struct ContractState
|
|||||||
std::string name;
|
std::string name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LoopState
|
||||||
|
{
|
||||||
|
explicit LoopState(bool _inLoop, bool _wasLoop): inLoop(_inLoop), wasLoop(_wasLoop) {}
|
||||||
|
bool inLoop;
|
||||||
|
bool wasLoop;
|
||||||
|
};
|
||||||
|
|
||||||
struct TestState
|
struct TestState
|
||||||
{
|
{
|
||||||
explicit TestState(std::shared_ptr<UniformRandomDistribution>& _urd):
|
explicit TestState(std::shared_ptr<UniformRandomDistribution>& _urd):
|
||||||
@ -517,7 +524,8 @@ struct TestState
|
|||||||
numContracts(0),
|
numContracts(0),
|
||||||
numFunctions(0),
|
numFunctions(0),
|
||||||
indentationLevel(0),
|
indentationLevel(0),
|
||||||
insideContract(false)
|
insideContract(false),
|
||||||
|
loopState(false, false)
|
||||||
{}
|
{}
|
||||||
/// Adds @param _path to @name sourceUnitPaths updates
|
/// Adds @param _path to @name sourceUnitPaths updates
|
||||||
/// @name currentSourceUnitPath.
|
/// @name currentSourceUnitPath.
|
||||||
@ -642,6 +650,19 @@ struct TestState
|
|||||||
{
|
{
|
||||||
insideContract = false;
|
insideContract = false;
|
||||||
}
|
}
|
||||||
|
void enterLoop()
|
||||||
|
{
|
||||||
|
loopState.wasLoop = loopState.inLoop;
|
||||||
|
loopState.inLoop = true;
|
||||||
|
}
|
||||||
|
void exitLoop()
|
||||||
|
{
|
||||||
|
loopState.inLoop = loopState.wasLoop;
|
||||||
|
}
|
||||||
|
bool inLoop()
|
||||||
|
{
|
||||||
|
return loopState.inLoop;
|
||||||
|
}
|
||||||
~TestState()
|
~TestState()
|
||||||
{
|
{
|
||||||
sourceUnitState.clear();
|
sourceUnitState.clear();
|
||||||
@ -681,6 +702,8 @@ struct TestState
|
|||||||
unsigned indentationLevel;
|
unsigned indentationLevel;
|
||||||
/// Contract scope
|
/// Contract scope
|
||||||
bool insideContract;
|
bool insideContract;
|
||||||
|
/// Loop state
|
||||||
|
LoopState loopState;
|
||||||
/// Source name prefix
|
/// Source name prefix
|
||||||
std::string const sourceUnitNamePrefix = "su";
|
std::string const sourceUnitNamePrefix = "su";
|
||||||
/// Contract name prefix
|
/// Contract name prefix
|
||||||
@ -1096,6 +1119,38 @@ private:
|
|||||||
static constexpr size_t s_maxConditionalStmts = 5;
|
static constexpr size_t s_maxConditionalStmts = 5;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BreakStmtGenerator: public GeneratorBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit BreakStmtGenerator(SolidityGenerator* _mutator):
|
||||||
|
GeneratorBase(std::move(_mutator))
|
||||||
|
{}
|
||||||
|
std::string visit() override
|
||||||
|
{
|
||||||
|
if (state->inLoop())
|
||||||
|
return indentation() + "break;\n";
|
||||||
|
else
|
||||||
|
return "\n";
|
||||||
|
}
|
||||||
|
std::string name() override { return "Break statement generator"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ContinueStmtGenerator: public GeneratorBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ContinueStmtGenerator(SolidityGenerator* _mutator):
|
||||||
|
GeneratorBase(std::move(_mutator))
|
||||||
|
{}
|
||||||
|
std::string visit() override
|
||||||
|
{
|
||||||
|
if (state->inLoop())
|
||||||
|
return indentation() + "continue;\n";
|
||||||
|
else
|
||||||
|
return "\n";
|
||||||
|
}
|
||||||
|
std::string name() override { return "Continue statement generator"; }
|
||||||
|
};
|
||||||
|
|
||||||
class WhileStmtGenerator: public GeneratorBase
|
class WhileStmtGenerator: public GeneratorBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user