aboutsummaryrefslogtreecommitdiffstats
path: root/Compiler.cpp
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2015-01-20 06:08:48 +0800
committerChristian <c@ethdev.com>2015-01-20 06:35:04 +0800
commitddf5e20d100535c10315d0ae73ba4ed753ef3397 (patch)
tree2d2e5bc26cacc78c98677f4fa3e3b3f9df7835db /Compiler.cpp
parentaf92f98d86ba1e15e3f41ac49bb9639be1ab4e41 (diff)
downloaddexon-solidity-ddf5e20d100535c10315d0ae73ba4ed753ef3397.tar
dexon-solidity-ddf5e20d100535c10315d0ae73ba4ed753ef3397.tar.gz
dexon-solidity-ddf5e20d100535c10315d0ae73ba4ed753ef3397.tar.bz2
dexon-solidity-ddf5e20d100535c10315d0ae73ba4ed753ef3397.tar.lz
dexon-solidity-ddf5e20d100535c10315d0ae73ba4ed753ef3397.tar.xz
dexon-solidity-ddf5e20d100535c10315d0ae73ba4ed753ef3397.tar.zst
dexon-solidity-ddf5e20d100535c10315d0ae73ba4ed753ef3397.zip
Call constructors of base classes.
Diffstat (limited to 'Compiler.cpp')
-rw-r--r--Compiler.cpp71
1 files changed, 60 insertions, 11 deletions
diff --git a/Compiler.cpp b/Compiler.cpp
index aa3022aa..36316b9a 100644
--- a/Compiler.cpp
+++ b/Compiler.cpp
@@ -67,19 +67,52 @@ void Compiler::initializeContext(ContractDefinition const& _contract,
void Compiler::packIntoContractCreator(ContractDefinition const& _contract, CompilerContext const& _runtimeContext)
{
+ // arguments for base constructors, filled in derived-to-base order
+ map<ContractDefinition const*, vector<ASTPointer<Expression>> const*> baseArguments;
set<FunctionDefinition const*> neededFunctions;
- // TODO constructors of base classes
- FunctionDefinition const* constructor = _contract.getConstructor();
- if (constructor)
- neededFunctions = getFunctionsNeededByConstructor(*constructor);
+ set<ASTNode const*> nodesUsedInConstructors;
+
+ // Determine the arguments that are used for the base constructors and also which functions
+ // are needed at compile time.
+ std::vector<ContractDefinition const*> const& bases = _contract.getLinearizedBaseContracts();
+ for (ContractDefinition const* contract: bases)
+ {
+ if (FunctionDefinition const* constructor = contract->getConstructor())
+ nodesUsedInConstructors.insert(constructor);
+ for (ASTPointer<InheritanceSpecifier> const& base: contract->getBaseContracts())
+ {
+ ContractDefinition const* baseContract = dynamic_cast<ContractDefinition const*>(
+ base->getName()->getReferencedDeclaration());
+ solAssert(baseContract, "");
+ if (baseArguments.count(baseContract) == 0)
+ {
+ baseArguments[baseContract] = &base->getArguments();
+ for (ASTPointer<Expression> const& arg: base->getArguments())
+ nodesUsedInConstructors.insert(arg.get());
+ }
+ }
+ }
+
+ //@TODO add virtual functions
+ neededFunctions = getFunctionsCalled(nodesUsedInConstructors);
- // TODO we should add the overridden functions
for (FunctionDefinition const* fun: neededFunctions)
m_context.addFunction(*fun);
- // we have many of them now
- if (constructor)
- appendConstructorCall(*constructor);
+ // Call constructors in base-to-derived order.
+ // The Constructor for the most derived contract is called later.
+ for (unsigned i = 1; i < bases.size(); i++)
+ {
+ ContractDefinition const* base = bases[bases.size() - i];
+ solAssert(base, "");
+ FunctionDefinition const* baseConstructor = base->getConstructor();
+ if (!baseConstructor)
+ continue;
+ solAssert(baseArguments[base], "");
+ appendBaseConstructorCall(*baseConstructor, *baseArguments[base]);
+ }
+ if (_contract.getConstructor())
+ appendConstructorCall(*_contract.getConstructor());
eth::AssemblyItem sub = m_context.addSubroutine(_runtimeContext.getAssembly());
// stack contains sub size
@@ -92,6 +125,21 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract, Comp
fun->accept(*this);
}
+void Compiler::appendBaseConstructorCall(FunctionDefinition const& _constructor,
+ vector<ASTPointer<Expression>> const& _arguments)
+{
+ FunctionType constructorType(_constructor);
+ eth::AssemblyItem returnLabel = m_context.pushNewTag();
+ for (unsigned i = 0; i < _arguments.size(); ++i)
+ {
+ compileExpression(*_arguments[i]);
+ ExpressionCompiler::appendTypeConversion(m_context, *_arguments[i]->getType(),
+ *constructorType.getParameterTypes()[i]);
+ }
+ m_context.appendJumpTo(m_context.getFunctionEntryLabel(_constructor));
+ m_context << returnLabel;
+}
+
void Compiler::appendConstructorCall(FunctionDefinition const& _constructor)
{
eth::AssemblyItem returnTag = m_context.pushNewTag();
@@ -111,11 +159,12 @@ void Compiler::appendConstructorCall(FunctionDefinition const& _constructor)
m_context << returnTag;
}
-set<FunctionDefinition const*> Compiler::getFunctionsNeededByConstructor(FunctionDefinition const& _constructor)
+set<FunctionDefinition const*> Compiler::getFunctionsCalled(set<ASTNode const*> const& _nodes)
{
+ // TODO this does not add virtual functions
CallGraph callgraph;
- callgraph.addFunction(_constructor);
- callgraph.computeCallGraph();
+ for (ASTNode const* node: _nodes)
+ callgraph.addNode(*node);
return callgraph.getCalls();
}