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) \
|
||||
MACRO(AssignmentStmtGenerator) SEP \
|
||||
MACRO(BlockStmtGenerator) SEP \
|
||||
MACRO(BreakStmtGenerator) SEP \
|
||||
MACRO(ContinueStmtGenerator) SEP \
|
||||
MACRO(ContractGenerator) SEP \
|
||||
MACRO(ExpressionStmtGenerator) SEP \
|
||||
MACRO(FunctionCallGenerator) SEP \
|
||||
|
@ -511,6 +511,8 @@ void WhileStmtGenerator::setup()
|
||||
string WhileStmtGenerator::visit()
|
||||
{
|
||||
ostringstream whileStmt;
|
||||
state->enterLoop();
|
||||
ScopeGuard exitLoop([&]() { state->exitLoop(); });
|
||||
ExpressionGenerator exprGen{state};
|
||||
auto boolType = make_shared<BoolType>();
|
||||
pair<SolidityTypePtr, string> boolTypeName = {boolType, {}};
|
||||
@ -538,7 +540,9 @@ void StatementGenerator::setup()
|
||||
{mutator->generator<FunctionCallGenerator>(), 1},
|
||||
{mutator->generator<ExpressionStmtGenerator>(), 1},
|
||||
{mutator->generator<IfStmtGenerator>(), 2},
|
||||
{mutator->generator<WhileStmtGenerator>(), 1}
|
||||
{mutator->generator<WhileStmtGenerator>(), 1},
|
||||
{mutator->generator<BreakStmtGenerator>(), 1},
|
||||
{mutator->generator<ContinueStmtGenerator>(), 1}
|
||||
};
|
||||
addGenerators(std::move(dependsOn));
|
||||
}
|
||||
@ -553,25 +557,21 @@ string StatementGenerator::visit()
|
||||
mutator->generator<BlockStmtGenerator>()->unchecked(true);
|
||||
|
||||
ostringstream os;
|
||||
// Randomise visit order
|
||||
vector<std::pair<GeneratorPtr, unsigned>> randomisedChildren;
|
||||
for (auto const& child: generators)
|
||||
randomisedChildren.push_back(child);
|
||||
shuffle(randomisedChildren.begin(), randomisedChildren.end(), *uRandDist()->randomEngine);
|
||||
for (auto const& child: randomisedChildren)
|
||||
if (uRandDist()->likely(child.second + 1))
|
||||
{
|
||||
os << std::visit(GenericVisitor{
|
||||
[](auto const& _item) { return _item->generate(); }
|
||||
}, child.first);
|
||||
if (holds_alternative<shared_ptr<BlockStmtGenerator>>(child.first) &&
|
||||
generateUncheckedBlock
|
||||
)
|
||||
{
|
||||
get<shared_ptr<BlockStmtGenerator>>(child.first)->unchecked(false);
|
||||
get<shared_ptr<BlockStmtGenerator>>(child.first)->resetInUnchecked();
|
||||
}
|
||||
}
|
||||
// Choose random statement type
|
||||
auto genIterator = generators.begin();
|
||||
auto advanceBy = uRandDist()->distributionOneToN(generators.size()) - 1;
|
||||
std::advance(genIterator, advanceBy);
|
||||
auto child = *genIterator;
|
||||
os << std::visit(GenericVisitor{
|
||||
[](auto const& _item) { return _item->generate(); }
|
||||
}, child.first);
|
||||
if (holds_alternative<shared_ptr<BlockStmtGenerator>>(child.first) &&
|
||||
generateUncheckedBlock
|
||||
)
|
||||
{
|
||||
get<shared_ptr<BlockStmtGenerator>>(child.first)->unchecked(false);
|
||||
get<shared_ptr<BlockStmtGenerator>>(child.first)->resetInUnchecked();
|
||||
}
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
@ -504,6 +504,13 @@ struct ContractState
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct LoopState
|
||||
{
|
||||
explicit LoopState(bool _inLoop, bool _wasLoop): inLoop(_inLoop), wasLoop(_wasLoop) {}
|
||||
bool inLoop;
|
||||
bool wasLoop;
|
||||
};
|
||||
|
||||
struct TestState
|
||||
{
|
||||
explicit TestState(std::shared_ptr<UniformRandomDistribution>& _urd):
|
||||
@ -517,7 +524,8 @@ struct TestState
|
||||
numContracts(0),
|
||||
numFunctions(0),
|
||||
indentationLevel(0),
|
||||
insideContract(false)
|
||||
insideContract(false),
|
||||
loopState(false, false)
|
||||
{}
|
||||
/// Adds @param _path to @name sourceUnitPaths updates
|
||||
/// @name currentSourceUnitPath.
|
||||
@ -642,6 +650,19 @@ struct TestState
|
||||
{
|
||||
insideContract = false;
|
||||
}
|
||||
void enterLoop()
|
||||
{
|
||||
loopState.wasLoop = loopState.inLoop;
|
||||
loopState.inLoop = true;
|
||||
}
|
||||
void exitLoop()
|
||||
{
|
||||
loopState.inLoop = loopState.wasLoop;
|
||||
}
|
||||
bool inLoop()
|
||||
{
|
||||
return loopState.inLoop;
|
||||
}
|
||||
~TestState()
|
||||
{
|
||||
sourceUnitState.clear();
|
||||
@ -681,6 +702,8 @@ struct TestState
|
||||
unsigned indentationLevel;
|
||||
/// Contract scope
|
||||
bool insideContract;
|
||||
/// Loop state
|
||||
LoopState loopState;
|
||||
/// Source name prefix
|
||||
std::string const sourceUnitNamePrefix = "su";
|
||||
/// Contract name prefix
|
||||
@ -1096,6 +1119,38 @@ private:
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user