diff options
author | Christian <c@ethdev.com> | 2015-01-23 09:35:27 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2015-01-26 17:23:39 +0800 |
commit | 7ded95c776717cf96e96dffb7425c86b47ad8b0e (patch) | |
tree | 35ef6d03bd36236ab72f9d9bf3cae6acd4c02b51 /Compiler.cpp | |
parent | 941c77c8fadd6195809cd2d572feb64478c4fb20 (diff) | |
download | dexon-solidity-7ded95c776717cf96e96dffb7425c86b47ad8b0e.tar dexon-solidity-7ded95c776717cf96e96dffb7425c86b47ad8b0e.tar.gz dexon-solidity-7ded95c776717cf96e96dffb7425c86b47ad8b0e.tar.bz2 dexon-solidity-7ded95c776717cf96e96dffb7425c86b47ad8b0e.tar.lz dexon-solidity-7ded95c776717cf96e96dffb7425c86b47ad8b0e.tar.xz dexon-solidity-7ded95c776717cf96e96dffb7425c86b47ad8b0e.tar.zst dexon-solidity-7ded95c776717cf96e96dffb7425c86b47ad8b0e.zip |
Compilation of function modifiers.
Diffstat (limited to 'Compiler.cpp')
-rw-r--r-- | Compiler.cpp | 80 |
1 files changed, 64 insertions, 16 deletions
diff --git a/Compiler.cpp b/Compiler.cpp index 5a434a71..fa8eb775 100644 --- a/Compiler.cpp +++ b/Compiler.cpp @@ -77,6 +77,7 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract, Comp std::vector<ContractDefinition const*> const& bases = _contract.getLinearizedBaseContracts(); for (ContractDefinition const* contract: bases) { + //TODO include modifiers if (FunctionDefinition const* constructor = contract->getConstructor()) nodesUsedInConstructors.insert(constructor); for (ASTPointer<InheritanceSpecifier> const& base: contract->getBaseContracts()) @@ -150,11 +151,7 @@ void Compiler::appendBaseConstructorCall(FunctionDefinition const& _constructor, 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]); - } + compileExpression(*_arguments[i], constructorType.getParameterTypes()[i]); m_context.appendJumpTo(m_context.getFunctionEntryLabel(_constructor)); m_context << returnLabel; } @@ -280,20 +277,28 @@ bool Compiler::visit(FunctionDefinition const& _function) m_returnTag = m_context.newTag(); m_breakTags.clear(); m_continueTags.clear(); + m_stackCleanupForReturn = 0; + m_currentFunction = &_function; + m_modifierDepth = 0; m_context << m_context.getFunctionEntryLabel(_function); // stack upon entry: [return address] [arg0] [arg1] ... [argn] // reserve additional slots: [retarg0] ... [retargm] [localvar0] ... [localvarp] + unsigned parametersSize = CompilerUtils::getSizeOnStack(_function.getParameters()); + m_context.adjustStackOffset(parametersSize); for (ASTPointer<VariableDeclaration const> const& variable: _function.getParameters()) - m_context.addVariable(*variable); + { + m_context.addVariable(*variable, parametersSize); + parametersSize -= variable->getType()->getSizeOnStack(); + } for (ASTPointer<VariableDeclaration const> const& variable: _function.getReturnParameters()) m_context.addAndInitializeVariable(*variable); for (VariableDeclaration const* localVariable: _function.getLocalVariables()) m_context.addAndInitializeVariable(*localVariable); - _function.getBody().accept(*this); + appendModifierOrFunctionCode(); m_context << m_returnTag; @@ -420,13 +425,15 @@ bool Compiler::visit(Return const& _return) //@todo modifications are needed to make this work with functions returning multiple values if (Expression const* expression = _return.getExpression()) { - compileExpression(*expression); - VariableDeclaration const& firstVariable = *_return.getFunctionReturnParameters().getParameters().front(); - ExpressionCompiler::appendTypeConversion(m_context, *expression->getType(), *firstVariable.getType()); - + solAssert(_return.getFunctionReturnParameters(), "Invalid return parameters pointer."); + VariableDeclaration const& firstVariable = *_return.getFunctionReturnParameters()->getParameters().front(); + compileExpression(*expression, firstVariable.getType()); CompilerUtils(m_context).moveToStackVariable(firstVariable); } + for (unsigned i = 0; i < m_stackCleanupForReturn; ++i) + m_context << eth::Instruction::POP; m_context.appendJumpTo(m_returnTag); + m_context.adjustStackOffset(m_stackCleanupForReturn); return false; } @@ -434,10 +441,7 @@ bool Compiler::visit(VariableDefinition const& _variableDefinition) { if (Expression const* expression = _variableDefinition.getExpression()) { - compileExpression(*expression); - ExpressionCompiler::appendTypeConversion(m_context, - *expression->getType(), - *_variableDefinition.getDeclaration().getType()); + compileExpression(*expression, _variableDefinition.getDeclaration().getType()); CompilerUtils(m_context).moveToStackVariable(_variableDefinition.getDeclaration()); } return false; @@ -451,9 +455,53 @@ bool Compiler::visit(ExpressionStatement const& _expressionStatement) return false; } -void Compiler::compileExpression(Expression const& _expression) +bool Compiler::visit(PlaceholderStatement const&) +{ + ++m_modifierDepth; + appendModifierOrFunctionCode(); + --m_modifierDepth; +} + +void Compiler::appendModifierOrFunctionCode() +{ + solAssert(m_currentFunction, ""); + if (m_modifierDepth >= m_currentFunction->getModifiers().size()) + m_currentFunction->getBody().accept(*this); + else + { + ASTPointer<ModifierInvocation> const& modifierInvocation = m_currentFunction->getModifiers()[m_modifierDepth]; + + // TODO get the most derived override of the modifier + ModifierDefinition const* modifier = dynamic_cast<ModifierDefinition const*>( + modifierInvocation->getName()->getReferencedDeclaration()); + solAssert(!!modifier, "Modifier not found."); + solAssert(modifier->getParameters().size() == modifierInvocation->getArguments().size(), ""); + for (unsigned i = 0; i < modifier->getParameters().size(); ++i) + { + m_context.addVariable(*modifier->getParameters()[i]); + compileExpression(*modifierInvocation->getArguments()[i], + modifier->getParameters()[i]->getType()); + } + for (VariableDeclaration const* localVariable: modifier->getLocalVariables()) + m_context.addAndInitializeVariable(*localVariable); + + unsigned const c_stackSurplus = CompilerUtils::getSizeOnStack(modifier->getParameters()) + + CompilerUtils::getSizeOnStack(modifier->getLocalVariables()); + m_stackCleanupForReturn += c_stackSurplus; + + modifier->getBody().accept(*this); + + for (unsigned i = 0; i < c_stackSurplus; ++i) + m_context << eth::Instruction::POP; + m_stackCleanupForReturn -= c_stackSurplus; + } +} + +void Compiler::compileExpression(Expression const& _expression, TypePointer const& _targetType) { ExpressionCompiler::compileExpression(m_context, _expression, m_optimize); + if (_targetType) + ExpressionCompiler::appendTypeConversion(m_context, *_expression.getType(), *_targetType); } } |