Implements constructor code for state variables.

This commit is contained in:
Christian Parpart
2019-08-05 11:23:01 +02:00
committed by chriseth
parent 742b4271fd
commit 235638b3fc
6 changed files with 78 additions and 12 deletions
+39 -10
View File
@@ -39,6 +39,9 @@
#include <liblangutil/SourceReferenceFormatter.h>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <sstream>
using namespace std;
using namespace dev;
@@ -177,19 +180,45 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
string IRGenerator::constructorCode(ContractDefinition const& _contract)
{
// TODO initialize state variables in base to derived order.
// TODO base constructors
// TODO callValueCheck if there is no constructor.
if (FunctionDefinition const* constructor = _contract.constructor())
// Initialization of state variables in base-to-derived order.
solAssert(!_contract.isLibrary(), "Tried to initialize state variables of library.");
using boost::adaptors::reverse;
ostringstream out;
FunctionDefinition const* constructor = _contract.constructor();
if (constructor && !constructor->isPayable())
out << callValueCheck();
for (ContractDefinition const* contract: reverse(_contract.annotation().linearizedBaseContracts))
{
string out;
if (!constructor->isPayable())
out = callValueCheck();
solUnimplementedAssert(constructor->parameters().empty(), "");
return move(out) + m_context.functionName(*constructor) + "()\n";
out <<
"\n// Begin state variable initialization for contract \"" <<
contract->name() <<
"\" (" <<
contract->stateVariables().size() <<
" variables)\n";
IRGeneratorForStatements generator{m_context, m_utils};
for (VariableDeclaration const* variable: contract->stateVariables())
if (!variable->isConstant())
generator.initializeStateVar(*variable);
out << generator.code();
out << "// End state variable initialization for contract \"" << contract->name() << "\".\n";
}
return {};
if (constructor)
{
solUnimplementedAssert(constructor->parameters().empty(), "");
// TODO base constructors
out << m_context.functionName(*constructor) + "()\n";
}
return out.str();
}
string IRGenerator::deployCode(ContractDefinition const& _contract)
@@ -133,6 +133,21 @@ string IRGeneratorForStatements::code() const
return m_code.str();
}
void IRGeneratorForStatements::initializeStateVar(VariableDeclaration const& _varDecl)
{
solAssert(m_context.isStateVariable(_varDecl), "Must be a state variable.");
solAssert(!_varDecl.isConstant(), "");
if (_varDecl.value())
{
_varDecl.value()->accept(*this);
string value = m_context.newYulVariable();
Type const& varType = *_varDecl.type();
m_code << "let " << value << " := " << expressionAsType(*_varDecl.value(), varType) << "\n";
m_code << IRStorageItem{m_context, _varDecl}.storeValue(value, varType);
}
}
void IRGeneratorForStatements::endVisit(VariableDeclarationStatement const& _varDeclStatement)
{
for (auto const& decl: _varDeclStatement.declarations())
@@ -45,6 +45,9 @@ public:
std::string code() const;
/// Generates code to initialize the given state variable.
void initializeStateVar(VariableDeclaration const& _varDecl);
void endVisit(VariableDeclarationStatement const& _variableDeclaration) override;
bool visit(Assignment const& _assignment) override;
bool visit(TupleExpression const& _tuple) override;