Add function I/O params.

This commit is contained in:
Bhargava Shastry 2021-04-28 13:11:28 +02:00
parent 31ec048f76
commit bbd451dd16
2 changed files with 129 additions and 13 deletions

View File

@ -230,8 +230,52 @@ string FunctionGenerator::visit()
if (!m_freeFunction) if (!m_freeFunction)
visibility = "public"; visibility = "public";
auto inputType = TypeGenerator{state}.type();
state->currentFunctionState()->addInput(pair<string, shared_ptr<SolidityType>>("i1", inputType));
string inputParams = inputType->toString() + " i1";
return indentation(state->indentationLevel) + return indentation(state->indentationLevel) +
"function " + name + "() " + visibility + " pure {}\n"; "function " + name + "(" + inputParams + ") " + visibility + " pure {}\n";
}
shared_ptr<SolidityType> TypeGenerator::type()
{
switch (typeCategory())
{
case Type::INTEGER:
{
IntegerType::Bits b = static_cast<IntegerType::Bits>(
state->uRandDist->distributionOneToN(
static_cast<size_t>(IntegerType::Bits::B256)
)
);
// Choose signed/unsigned type with probability of 1/2 = 0.5
bool signedType = state->uRandDist->probable(2);
return dynamic_pointer_cast<SolidityType>(make_shared<IntegerType>(b, signedType));
}
case Type::BOOL:
return dynamic_pointer_cast<SolidityType>(make_shared<BoolType>());
case Type::FIXEDBYTES:
{
FixedBytesType::Bytes w = static_cast<FixedBytesType::Bytes>(
state->uRandDist->distributionOneToN(
static_cast<size_t>(FixedBytesType::Bytes::W32)
)
);
return dynamic_pointer_cast<SolidityType>(make_shared<FixedBytesType>(w));
}
case Type::BYTES:
return dynamic_pointer_cast<SolidityType>(make_shared<BytesType>());
case Type::ADDRESS:
return dynamic_pointer_cast<SolidityType>(make_shared<AddressType>());
case Type::FUNCTION:
return dynamic_pointer_cast<SolidityType>(make_shared<FunctionType>());
case Type::CONTRACT:
if (state->sourceUnitState[state->currentPath()]->contractType())
return state->sourceUnitState[state->currentPath()]->randomContractType();
return dynamic_pointer_cast<SolidityType>(make_shared<BoolType>());
default:
solAssert(false, "");
}
} }
template <typename T> template <typename T>

View File

@ -243,7 +243,7 @@ struct BytesType: SolidityType
{ {
std::string toString() override std::string toString() override
{ {
return "bytes"; return "bytes memory";
} }
}; };
@ -253,7 +253,7 @@ struct ContractType: SolidityType
{} {}
std::string toString() override std::string toString() override
{ {
return "type(" + contractName + ")"; return name();
} }
std::string name() std::string name()
{ {
@ -265,13 +265,23 @@ struct ContractType: SolidityType
struct FunctionType: SolidityType struct FunctionType: SolidityType
{ {
FunctionType() = default; FunctionType() = default;
~FunctionType() ~FunctionType() override
{ {
inputs.clear(); inputs.clear();
outputs.clear(); outputs.clear();
} }
std::string toString() void addInput(std::shared_ptr<SolidityType> _input)
{
inputs.emplace_back(_input);
}
void addOutput(std::shared_ptr<SolidityType> _output)
{
outputs.emplace_back(_output);
}
std::string toString() override
{ {
auto typeString = [](std::vector<std::shared_ptr<SolidityType>>& _types) auto typeString = [](std::vector<std::shared_ptr<SolidityType>>& _types)
{ {
@ -286,20 +296,20 @@ struct FunctionType: SolidityType
return typeStr; return typeStr;
}; };
std::string retString = std::string("function ") + "(" + typeString(inputs) + ")";
if (outputs.empty()) if (outputs.empty())
return std::string("function (") + typeString(inputs) + ") public pure {}"; return retString + " public pure";
else else
return std::string("function (") + return retString + " public pure returns (" + typeString(outputs) + ")";
typeString(inputs) +
") public pure returns (" +
typeString(outputs) +
") {}";
} }
std::vector<std::shared_ptr<SolidityType>> inputs; std::vector<std::shared_ptr<SolidityType>> inputs;
std::vector<std::shared_ptr<SolidityType>> outputs; std::vector<std::shared_ptr<SolidityType>> outputs;
}; };
/// Forward declaration
struct TestState;
struct SourceState struct SourceState
{ {
explicit SourceState(std::shared_ptr<UniformRandomDistribution> _urd): explicit SourceState(std::shared_ptr<UniformRandomDistribution> _urd):
@ -308,7 +318,7 @@ struct SourceState
{} {}
void addFreeFunction(std::string& _functionName) void addFreeFunction(std::string& _functionName)
{ {
exports[std::make_shared<FunctionType>()] = _functionName; exports[std::dynamic_pointer_cast<SolidityType>(std::make_shared<FunctionType>())] = _functionName;
} }
bool freeFunction(std::string const& _functionName) bool freeFunction(std::string const& _functionName)
{ {
@ -331,6 +341,18 @@ struct SourceState
}) | ranges::to<std::vector<std::string>>; }) | ranges::to<std::vector<std::string>>;
return contracts[uRandDist->distributionOneToN(contracts.size()) - 1]; return contracts[uRandDist->distributionOneToN(contracts.size()) - 1];
} }
std::shared_ptr<SolidityType> randomContractType()
{
auto contracts = exports |
ranges::views::filter([](auto& _item) -> bool {
return bool(std::dynamic_pointer_cast<ContractType>(_item.first));
}) |
ranges::views::transform([](auto& _item) -> std::shared_ptr<SolidityType> {
return _item.first;
}) |
ranges::to<std::vector<std::shared_ptr<SolidityType>>>;
return contracts[uRandDist->distributionOneToN(contracts.size()) - 1];
}
void addImportedSourcePath(std::string& _sourcePath) void addImportedSourcePath(std::string& _sourcePath)
{ {
importedSources.emplace(_sourcePath); importedSources.emplace(_sourcePath);
@ -355,7 +377,26 @@ struct SourceState
std::map<std::shared_ptr<SolidityType>, std::string> exports; std::map<std::shared_ptr<SolidityType>, std::string> exports;
}; };
struct FunctionState {}; struct FunctionState
{
FunctionState() = default;
~FunctionState()
{
inputs.clear();
outputs.clear();
}
void addInput(std::pair<std::string, std::shared_ptr<SolidityType>> _input)
{
inputs.emplace(_input);
}
void addOutput(std::pair<std::string, std::shared_ptr<SolidityType>> _output)
{
outputs.emplace(_output);
}
std::map<std::string, std::shared_ptr<SolidityType>> inputs;
std::map<std::string, std::shared_ptr<SolidityType>> outputs;
};
struct TestState struct TestState
{ {
@ -393,6 +434,10 @@ struct TestState
functionState.emplace(_name, std::make_shared<FunctionState>()); functionState.emplace(_name, std::make_shared<FunctionState>());
currentFunction = _name; currentFunction = _name;
} }
std::shared_ptr<FunctionState> currentFunctionState()
{
return functionState[currentFunction];
}
/// 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
@ -502,6 +547,33 @@ struct TestState
std::string const functionPrefix = "f"; std::string const functionPrefix = "f";
}; };
struct TypeGenerator
{
TypeGenerator(std::shared_ptr<TestState> _state): state(std::move(_state))
{}
enum class Type: size_t
{
INTEGER = 1,
BOOL,
FIXEDBYTES,
BYTES,
ADDRESS,
FUNCTION,
CONTRACT,
TYPEMAX
};
std::shared_ptr<SolidityType> type();
Type typeCategory()
{
return static_cast<Type>(state->uRandDist->distributionOneToN(static_cast<size_t>(Type::TYPEMAX) - 1));
}
std::shared_ptr<TestState> state;
};
struct GeneratorBase struct GeneratorBase
{ {
explicit GeneratorBase(std::shared_ptr<SolidityGenerator> _mutator); explicit GeneratorBase(std::shared_ptr<SolidityGenerator> _mutator);