From 4d833bc86bf10a685a8b5d72e90c49a24a33f8b3 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 15 Jan 2015 20:04:24 +0100 Subject: [PATCH] Inheritance in compiler. --- Compiler.cpp | 24 +++++++++++++++--------- CompilerContext.cpp | 11 ++++++++++- CompilerContext.h | 4 ++++ ExpressionCompiler.cpp | 2 +- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Compiler.cpp b/Compiler.cpp index d86c939c8..aa3022aad 100644 --- a/Compiler.cpp +++ b/Compiler.cpp @@ -21,6 +21,7 @@ */ #include +#include #include #include #include @@ -40,14 +41,16 @@ void Compiler::compileContract(ContractDefinition const& _contract, m_context = CompilerContext(); // clear it just in case initializeContext(_contract, _contracts); - for (ASTPointer const& function: _contract.getDefinedFunctions()) - if (function->getName() != _contract.getName()) // don't add the constructor here - m_context.addFunction(*function); + for (ContractDefinition const* contract: _contract.getLinearizedBaseContracts()) + for (ASTPointer const& function: contract->getDefinedFunctions()) + if (function->getName() != contract->getName()) // don't add the constructor here + m_context.addFunction(*function); appendFunctionSelector(_contract); - for (ASTPointer const& function: _contract.getDefinedFunctions()) - if (function->getName() != _contract.getName()) // don't add the constructor here - function->accept(*this); + for (ContractDefinition const* contract: _contract.getLinearizedBaseContracts()) + for (ASTPointer const& function: contract->getDefinedFunctions()) + if (function->getName() != contract->getName()) // don't add the constructor here + function->accept(*this); // Swap the runtime context with the creation-time context swap(m_context, m_runtimeContext); @@ -65,13 +68,16 @@ void Compiler::initializeContext(ContractDefinition const& _contract, void Compiler::packIntoContractCreator(ContractDefinition const& _contract, CompilerContext const& _runtimeContext) { set neededFunctions; + // TODO constructors of base classes FunctionDefinition const* constructor = _contract.getConstructor(); if (constructor) neededFunctions = getFunctionsNeededByConstructor(*constructor); + // 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); @@ -191,9 +197,9 @@ void Compiler::appendReturnValuePacker(FunctionDefinition const& _function) void Compiler::registerStateVariables(ContractDefinition const& _contract) { - //@todo sort them? - for (ASTPointer const& variable: _contract.getStateVariables()) - m_context.addStateVariable(*variable); + for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.getLinearizedBaseContracts())) + for (ASTPointer const& variable: contract->getStateVariables()) + m_context.addStateVariable(*variable); } bool Compiler::visit(FunctionDefinition const& _function) diff --git a/CompilerContext.cpp b/CompilerContext.cpp index 29e98eabf..27ec3efd5 100644 --- a/CompilerContext.cpp +++ b/CompilerContext.cpp @@ -61,7 +61,9 @@ void CompilerContext::addAndInitializeVariable(VariableDeclaration const& _decla void CompilerContext::addFunction(FunctionDefinition const& _function) { - m_functionEntryLabels.insert(std::make_pair(&_function, m_asm.newTag())); + eth::AssemblyItem tag(m_asm.newTag()); + m_functionEntryLabels.insert(make_pair(&_function, tag)); + m_virtualFunctionEntryLabels.insert(make_pair(_function.getName(), tag)); } bytes const& CompilerContext::getCompiledContract(const ContractDefinition& _contract) const @@ -83,6 +85,13 @@ eth::AssemblyItem CompilerContext::getFunctionEntryLabel(FunctionDefinition cons return res->second.tag(); } +eth::AssemblyItem CompilerContext::getVirtualFunctionEntryLabel(FunctionDefinition const& _function) const +{ + auto res = m_virtualFunctionEntryLabels.find(_function.getName()); + solAssert(res != m_virtualFunctionEntryLabels.end(), "Function entry label not found."); + return res->second.tag(); +} + unsigned CompilerContext::getBaseStackOffsetOfVariable(Declaration const& _declaration) const { auto res = m_localVariables.find(&_declaration); diff --git a/CompilerContext.h b/CompilerContext.h index cf505d654..cde992d58 100644 --- a/CompilerContext.h +++ b/CompilerContext.h @@ -57,6 +57,8 @@ public: bool isStateVariable(Declaration const* _declaration) const { return m_stateVariables.count(_declaration) != 0; } eth::AssemblyItem getFunctionEntryLabel(FunctionDefinition const& _function) const; + /// @returns the entry label of the given function and takes overrides into account. + eth::AssemblyItem getVirtualFunctionEntryLabel(FunctionDefinition const& _function) const; /// Returns the distance of the given local variable from the top of the local variable stack. unsigned getBaseStackOffsetOfVariable(Declaration const& _declaration) const; /// If supplied by a value returned by @ref getBaseStackOffsetOfVariable(variable), returns @@ -116,6 +118,8 @@ private: unsigned m_localVariablesSize; /// Labels pointing to the entry points of funcitons. std::map m_functionEntryLabels; + /// Labels pointing to the entry points of function overrides. + std::map m_virtualFunctionEntryLabels; }; } diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index df90d0d9d..5a45bfd6d 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -453,7 +453,7 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier) } if (FunctionDefinition const* functionDef = dynamic_cast(declaration)) { - m_context << m_context.getFunctionEntryLabel(*functionDef).pushTag(); + m_context << m_context.getVirtualFunctionEntryLabel(*functionDef).pushTag(); return; } if (dynamic_cast(declaration))