mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add function
This commit is contained in:
parent
10a416c4a8
commit
6d2c990117
@ -42,6 +42,7 @@
|
|||||||
*/
|
*/
|
||||||
#define GENERATORLIST(MACRO, SEP, ENDSEP) \
|
#define GENERATORLIST(MACRO, SEP, ENDSEP) \
|
||||||
MACRO(ContractGenerator) SEP \
|
MACRO(ContractGenerator) SEP \
|
||||||
|
MACRO(FunctionGenerator) SEP \
|
||||||
MACRO(ImportGenerator) SEP \
|
MACRO(ImportGenerator) SEP \
|
||||||
MACRO(PragmaGenerator) SEP \
|
MACRO(PragmaGenerator) SEP \
|
||||||
MACRO(SourceUnitGenerator) SEP \
|
MACRO(SourceUnitGenerator) SEP \
|
||||||
|
|||||||
@ -135,7 +135,8 @@ void SourceUnitGenerator::setup()
|
|||||||
addGenerators({
|
addGenerators({
|
||||||
{mutator->generator<ImportGenerator>(), s_maxImports},
|
{mutator->generator<ImportGenerator>(), s_maxImports},
|
||||||
{mutator->generator<PragmaGenerator>(), 1},
|
{mutator->generator<PragmaGenerator>(), 1},
|
||||||
{mutator->generator<ContractGenerator>(), 1}
|
{mutator->generator<ContractGenerator>(), 1},
|
||||||
|
{mutator->generator<FunctionGenerator>(), s_maxFreeFunctions}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,11 +186,43 @@ string ImportGenerator::visit()
|
|||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ContractGenerator::setup()
|
||||||
|
{
|
||||||
|
addGenerators({
|
||||||
|
{mutator->generator<FunctionGenerator>(), s_maxFunctions}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
string ContractGenerator::visit()
|
string ContractGenerator::visit()
|
||||||
{
|
{
|
||||||
|
ScopeGuard reset([&]() {
|
||||||
|
mutator->generator<FunctionGenerator>()->scope(true);
|
||||||
|
state->unindent();
|
||||||
|
});
|
||||||
|
auto set = [&]() {
|
||||||
|
state->indent();
|
||||||
|
mutator->generator<FunctionGenerator>()->scope(false);
|
||||||
|
};
|
||||||
|
ostringstream os;
|
||||||
string name = state->newContract();
|
string name = state->newContract();
|
||||||
state->updateContract(name);
|
state->updateContract(name);
|
||||||
return "contract " + name + " {}\n";
|
os << "contract " << name << " {" << endl;
|
||||||
|
set();
|
||||||
|
os << visitChildren();
|
||||||
|
os << "}" << endl;
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string FunctionGenerator::visit()
|
||||||
|
{
|
||||||
|
string visibility;
|
||||||
|
string name = state->newFunction();
|
||||||
|
state->updateFunction(name);
|
||||||
|
if (!m_freeFunction)
|
||||||
|
visibility = "public";
|
||||||
|
|
||||||
|
return indentation(state->indentationLevel) +
|
||||||
|
"function " + name + "() " + visibility + " pure {}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
@ -116,8 +116,17 @@ struct SourceState
|
|||||||
{
|
{
|
||||||
explicit SourceState(std::shared_ptr<UniformRandomDistribution> _urd):
|
explicit SourceState(std::shared_ptr<UniformRandomDistribution> _urd):
|
||||||
uRandDist(std::move(_urd)),
|
uRandDist(std::move(_urd)),
|
||||||
importedSources({})
|
importedSources({}),
|
||||||
|
freeFunctions({})
|
||||||
{}
|
{}
|
||||||
|
void addFreeFunction(std::string& _functionName)
|
||||||
|
{
|
||||||
|
freeFunctions.emplace(_functionName);
|
||||||
|
}
|
||||||
|
bool freeFunction(std::string const& _functionName)
|
||||||
|
{
|
||||||
|
return freeFunctions.count(_functionName);
|
||||||
|
}
|
||||||
void addImportedSourcePath(std::string& _sourcePath)
|
void addImportedSourcePath(std::string& _sourcePath)
|
||||||
{
|
{
|
||||||
importedSources.emplace(_sourcePath);
|
importedSources.emplace(_sourcePath);
|
||||||
@ -134,17 +143,24 @@ struct SourceState
|
|||||||
void print(std::ostream& _os) const;
|
void print(std::ostream& _os) const;
|
||||||
std::shared_ptr<UniformRandomDistribution> uRandDist;
|
std::shared_ptr<UniformRandomDistribution> uRandDist;
|
||||||
std::set<std::string> importedSources;
|
std::set<std::string> importedSources;
|
||||||
|
std::set<std::string> freeFunctions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FunctionState {};
|
||||||
|
|
||||||
struct TestState
|
struct TestState
|
||||||
{
|
{
|
||||||
explicit TestState(std::shared_ptr<UniformRandomDistribution> _urd):
|
explicit TestState(std::shared_ptr<UniformRandomDistribution> _urd):
|
||||||
sourceUnitState({}),
|
sourceUnitState({}),
|
||||||
contractState({}),
|
contractState({}),
|
||||||
currentSourceUnitPath({}),
|
currentSourceUnitPath({}),
|
||||||
|
currentContract({}),
|
||||||
|
currentFunction({}),
|
||||||
uRandDist(std::move(_urd)),
|
uRandDist(std::move(_urd)),
|
||||||
numSourceUnits(0),
|
numSourceUnits(0),
|
||||||
numContracts(0)
|
numContracts(0),
|
||||||
|
numFunctions(0),
|
||||||
|
indentationLevel(0)
|
||||||
{}
|
{}
|
||||||
/// Adds @param _path to @name sourceUnitPaths updates
|
/// Adds @param _path to @name sourceUnitPaths updates
|
||||||
/// @name currentSourceUnitPath.
|
/// @name currentSourceUnitPath.
|
||||||
@ -160,6 +176,11 @@ struct TestState
|
|||||||
contractState.emplace(_name, std::make_shared<ContractState>(uRandDist));
|
contractState.emplace(_name, std::make_shared<ContractState>(uRandDist));
|
||||||
currentContract = _name;
|
currentContract = _name;
|
||||||
}
|
}
|
||||||
|
void addFunction(std::string const& _name)
|
||||||
|
{
|
||||||
|
functionState.emplace(_name, std::make_shared<FunctionState>());
|
||||||
|
currentFunction = _name;
|
||||||
|
}
|
||||||
/// Returns true if @name sourceUnitPaths is empty,
|
/// Returns true if @name sourceUnitPaths is empty,
|
||||||
/// false otherwise.
|
/// false otherwise.
|
||||||
[[nodiscard]] bool empty() const
|
[[nodiscard]] bool empty() const
|
||||||
@ -183,6 +204,10 @@ struct TestState
|
|||||||
{
|
{
|
||||||
return contractPrefix + std::to_string(numContracts);
|
return contractPrefix + std::to_string(numContracts);
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] std::string newFunction() const
|
||||||
|
{
|
||||||
|
return functionPrefix + std::to_string(numFunctions);
|
||||||
|
}
|
||||||
[[nodiscard]] std::string currentPath() const
|
[[nodiscard]] std::string currentPath() const
|
||||||
{
|
{
|
||||||
solAssert(numSourceUnits > 0, "");
|
solAssert(numSourceUnits > 0, "");
|
||||||
@ -202,10 +227,25 @@ struct TestState
|
|||||||
addContract(_name);
|
addContract(_name);
|
||||||
numContracts++;
|
numContracts++;
|
||||||
}
|
}
|
||||||
|
void updateFunction(std::string const& _name)
|
||||||
|
{
|
||||||
|
addFunction(_name);
|
||||||
|
numFunctions++;
|
||||||
|
}
|
||||||
void addSource()
|
void addSource()
|
||||||
{
|
{
|
||||||
updateSourcePath(newPath());
|
updateSourcePath(newPath());
|
||||||
}
|
}
|
||||||
|
/// Increments indentation level globally.
|
||||||
|
void indent()
|
||||||
|
{
|
||||||
|
++indentationLevel;
|
||||||
|
}
|
||||||
|
/// Decrements indentation level globally.
|
||||||
|
void unindent()
|
||||||
|
{
|
||||||
|
--indentationLevel;
|
||||||
|
}
|
||||||
~TestState()
|
~TestState()
|
||||||
{
|
{
|
||||||
sourceUnitState.clear();
|
sourceUnitState.clear();
|
||||||
@ -224,20 +264,30 @@ struct TestState
|
|||||||
std::map<std::string, std::shared_ptr<SourceState>> sourceUnitState;
|
std::map<std::string, std::shared_ptr<SourceState>> sourceUnitState;
|
||||||
/// Map of contract name -> state
|
/// Map of contract name -> state
|
||||||
std::map<std::string, std::shared_ptr<ContractState>> contractState;
|
std::map<std::string, std::shared_ptr<ContractState>> contractState;
|
||||||
|
/// Map of function name -> state
|
||||||
|
std::map<std::string, std::shared_ptr<FunctionState>> functionState;
|
||||||
/// Source path being currently visited.
|
/// Source path being currently visited.
|
||||||
std::string currentSourceUnitPath;
|
std::string currentSourceUnitPath;
|
||||||
/// Current contract
|
/// Current contract
|
||||||
std::string currentContract;
|
std::string currentContract;
|
||||||
|
/// Current function
|
||||||
|
std::string currentFunction;
|
||||||
/// Uniform random distribution.
|
/// Uniform random distribution.
|
||||||
std::shared_ptr<UniformRandomDistribution> uRandDist;
|
std::shared_ptr<UniformRandomDistribution> uRandDist;
|
||||||
/// Number of source units in test input
|
/// Number of source units in test input
|
||||||
size_t numSourceUnits;
|
size_t numSourceUnits;
|
||||||
/// Number of contracts in test input
|
/// Number of contracts in test input
|
||||||
size_t numContracts;
|
size_t numContracts;
|
||||||
|
/// Number of functions in test input
|
||||||
|
size_t numFunctions;
|
||||||
|
/// Indentation level
|
||||||
|
unsigned indentationLevel;
|
||||||
/// Source name prefix
|
/// Source name prefix
|
||||||
std::string const sourceUnitNamePrefix = "su";
|
std::string const sourceUnitNamePrefix = "su";
|
||||||
/// Contract name prefix
|
/// Contract name prefix
|
||||||
std::string const contractPrefix = "C";
|
std::string const contractPrefix = "C";
|
||||||
|
/// Function name prefix
|
||||||
|
std::string const functionPrefix = "f";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GeneratorBase
|
struct GeneratorBase
|
||||||
@ -258,6 +308,12 @@ struct GeneratorBase
|
|||||||
endVisit();
|
endVisit();
|
||||||
return generatedCode;
|
return generatedCode;
|
||||||
}
|
}
|
||||||
|
/// @returns indentation as string. Each indentation level comprises two
|
||||||
|
/// whitespace characters.
|
||||||
|
std::string indentation(unsigned _indentationLevel)
|
||||||
|
{
|
||||||
|
return std::string(_indentationLevel * 2, ' ');
|
||||||
|
}
|
||||||
/// @returns a string representing the generation of
|
/// @returns a string representing the generation of
|
||||||
/// the Solidity grammar element.
|
/// the Solidity grammar element.
|
||||||
virtual std::string visit() = 0;
|
virtual std::string visit() = 0;
|
||||||
@ -341,6 +397,7 @@ public:
|
|||||||
std::string name() override { return "Source unit generator"; }
|
std::string name() override { return "Source unit generator"; }
|
||||||
private:
|
private:
|
||||||
static unsigned constexpr s_maxImports = 2;
|
static unsigned constexpr s_maxImports = 2;
|
||||||
|
static unsigned constexpr s_maxFreeFunctions = 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PragmaGenerator: public GeneratorBase
|
class PragmaGenerator: public GeneratorBase
|
||||||
@ -378,8 +435,30 @@ public:
|
|||||||
explicit ContractGenerator(std::shared_ptr<SolidityGenerator> _mutator):
|
explicit ContractGenerator(std::shared_ptr<SolidityGenerator> _mutator):
|
||||||
GeneratorBase(std::move(_mutator))
|
GeneratorBase(std::move(_mutator))
|
||||||
{}
|
{}
|
||||||
|
void setup() override;
|
||||||
std::string visit() override;
|
std::string visit() override;
|
||||||
std::string name() override { return "Contract generator"; }
|
std::string name() override { return "Contract generator"; }
|
||||||
|
private:
|
||||||
|
static unsigned constexpr s_maxFunctions = 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FunctionGenerator: public GeneratorBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit FunctionGenerator(std::shared_ptr<SolidityGenerator> _mutator):
|
||||||
|
GeneratorBase(std::move(_mutator)),
|
||||||
|
m_freeFunction(true)
|
||||||
|
{}
|
||||||
|
std::string visit() override;
|
||||||
|
std::string name() override { return "Function generator"; }
|
||||||
|
/// Sets @name m_freeFunction to @param _freeFunction.
|
||||||
|
void scope(bool _freeFunction)
|
||||||
|
{
|
||||||
|
m_freeFunction = _freeFunction;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool m_freeFunction;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SolidityGenerator: public std::enable_shared_from_this<SolidityGenerator>
|
class SolidityGenerator: public std::enable_shared_from_this<SolidityGenerator>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user