diff options
author | Christian <c@ethdev.com> | 2014-11-26 20:19:17 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2014-11-26 22:42:54 +0800 |
commit | c4a43c64c2878dea08dd2366ae6954173c4372cc (patch) | |
tree | 24f1e8fb7154405fd508e7a94daf36367ede4cf2 /ExpressionCompiler.cpp | |
parent | f30dc68cdd3ae97305b8dfc8891da81a6d489882 (diff) | |
download | dexon-solidity-c4a43c64c2878dea08dd2366ae6954173c4372cc.tar.gz dexon-solidity-c4a43c64c2878dea08dd2366ae6954173c4372cc.tar.zst dexon-solidity-c4a43c64c2878dea08dd2366ae6954173c4372cc.zip |
Global functions.
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r-- | ExpressionCompiler.cpp | 55 |
1 files changed, 45 insertions, 10 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index f5ab829c..4dc37779 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -160,6 +160,7 @@ bool ExpressionCompiler::visit(BinaryOperation& _binaryOperation) bool ExpressionCompiler::visit(FunctionCall& _functionCall) { + using Location = FunctionType::Location; if (_functionCall.isTypeConversion()) { //@todo struct construction @@ -184,7 +185,7 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall) if (asserts(arguments.size() == function.getParameterTypes().size())) BOOST_THROW_EXCEPTION(InternalCompilerError()); - if (function.getLocation() == FunctionType::Location::INTERNAL) + if (function.getLocation() == Location::INTERNAL) { // Calling convention: Caller pushes return address and arguments // Callee removes them and pushes return values @@ -208,29 +209,57 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall) for (unsigned i = 1; i < function.getReturnParameterTypes().size(); ++i) m_context << eth::Instruction::POP; } - else if (function.getLocation() == FunctionType::Location::EXTERNAL) - { + else if (function.getLocation() == Location::EXTERNAL) BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("External function calls not implemented yet.")); - } else { switch (function.getLocation()) { - case FunctionType::Location::SEND: + case Location::SEND: m_context << u256(0) << u256(0) << u256(0) << u256(0); arguments.front()->accept(*this); //@todo might not be necessary - appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front()); + appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front(), true); _functionCall.getExpression().accept(*this); m_context << u256(25) << eth::Instruction::GAS << eth::Instruction::SUB << eth::Instruction::CALL << eth::Instruction::POP; break; - case FunctionType::Location::SUICIDE: + case Location::SUICIDE: arguments.front()->accept(*this); //@todo might not be necessary - appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front()); + appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front(), true); m_context << eth::Instruction::SUICIDE; + break; + case Location::SHA3: + arguments.front()->accept(*this); + appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front(), true); + // @todo move this once we actually use memory + m_context << u256(0) << eth::Instruction::MSTORE << u256(32) << u256(0) << eth::Instruction::SHA3; + break; + case Location::ECRECOVER: + case Location::SHA256: + case Location::RIPEMD160: + { + static const map<Location, u256> contractAddresses{{Location::ECRECOVER, 1}, + {Location::SHA256, 2}, + {Location::RIPEMD160, 3}}; + u256 contractAddress = contractAddresses.find(function.getLocation())->second; + // @todo later, combine this code with external function call + for (unsigned i = 0; i < arguments.size(); ++i) + { + arguments[i]->accept(*this); + appendTypeConversion(*arguments[i]->getType(), *function.getParameterTypes()[i], true); + // @todo move this once we actually use memory + m_context << u256(i * 32) << eth::Instruction::MSTORE; + } + m_context << u256(32) << u256(0) << u256(arguments.size() * 32) << u256(0) << u256(0) + << contractAddress << u256(500) //@todo determine actual gas requirement + << eth::Instruction::CALL + << eth::Instruction::POP + << u256(0) << eth::Instruction::MLOAD; + break; + } default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Function not yet implemented.")); } @@ -246,9 +275,15 @@ void ExpressionCompiler::endVisit(MemberAccess& _memberAccess) { case Type::Category::INTEGER: if (member == "balance") + { + appendTypeConversion(*_memberAccess.getExpression().getType(), + IntegerType(0, IntegerType::Modifier::ADDRESS), true); m_context << eth::Instruction::BALANCE; + } else if (member == "send") - { // no modification + { + appendTypeConversion(*_memberAccess.getExpression().getType(), + IntegerType(0, IntegerType::Modifier::ADDRESS), true); } else BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to integer.")); @@ -319,7 +354,7 @@ void ExpressionCompiler::endVisit(Identifier& _identifier) Declaration* declaration = _identifier.getReferencedDeclaration(); if (MagicVariableDeclaration* magicVar = dynamic_cast<MagicVariableDeclaration*>(declaration)) { - if (magicVar->getKind() == MagicVariableDeclaration::VariableKind::THIS) + if (magicVar->getType()->getCategory() == Type::Category::CONTRACT) // must be "this" m_context << eth::Instruction::ADDRESS; return; } |