Inheritance in compiler.

This commit is contained in:
Christian 2015-01-15 20:04:24 +01:00
parent e6c0a9b922
commit 4d833bc86b
4 changed files with 30 additions and 11 deletions

View File

@ -21,6 +21,7 @@
*/
#include <algorithm>
#include <boost/range/adaptor/reversed.hpp>
#include <libevmcore/Instruction.h>
#include <libevmcore/Assembly.h>
#include <libsolidity/AST.h>
@ -40,14 +41,16 @@ void Compiler::compileContract(ContractDefinition const& _contract,
m_context = CompilerContext(); // clear it just in case
initializeContext(_contract, _contracts);
for (ASTPointer<FunctionDefinition> 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<FunctionDefinition> const& function: contract->getDefinedFunctions())
if (function->getName() != contract->getName()) // don't add the constructor here
m_context.addFunction(*function);
appendFunctionSelector(_contract);
for (ASTPointer<FunctionDefinition> 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<FunctionDefinition> 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<FunctionDefinition const*> 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<VariableDeclaration> const& variable: _contract.getStateVariables())
m_context.addStateVariable(*variable);
for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.getLinearizedBaseContracts()))
for (ASTPointer<VariableDeclaration> const& variable: contract->getStateVariables())
m_context.addStateVariable(*variable);
}
bool Compiler::visit(FunctionDefinition const& _function)

View File

@ -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);

View File

@ -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<Declaration const*, eth::AssemblyItem> m_functionEntryLabels;
/// Labels pointing to the entry points of function overrides.
std::map<std::string, eth::AssemblyItem> m_virtualFunctionEntryLabels;
};
}

View File

@ -453,7 +453,7 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
}
if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration))
{
m_context << m_context.getFunctionEntryLabel(*functionDef).pushTag();
m_context << m_context.getVirtualFunctionEntryLabel(*functionDef).pushTag();
return;
}
if (dynamic_cast<VariableDeclaration const*>(declaration))