aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2014-11-26 20:19:17 +0800
committerChristian <c@ethdev.com>2014-11-26 22:42:54 +0800
commitc4a43c64c2878dea08dd2366ae6954173c4372cc (patch)
tree24f1e8fb7154405fd508e7a94daf36367ede4cf2
parentf30dc68cdd3ae97305b8dfc8891da81a6d489882 (diff)
downloaddexon-solidity-c4a43c64c2878dea08dd2366ae6954173c4372cc.tar
dexon-solidity-c4a43c64c2878dea08dd2366ae6954173c4372cc.tar.gz
dexon-solidity-c4a43c64c2878dea08dd2366ae6954173c4372cc.tar.bz2
dexon-solidity-c4a43c64c2878dea08dd2366ae6954173c4372cc.tar.lz
dexon-solidity-c4a43c64c2878dea08dd2366ae6954173c4372cc.tar.xz
dexon-solidity-c4a43c64c2878dea08dd2366ae6954173c4372cc.tar.zst
dexon-solidity-c4a43c64c2878dea08dd2366ae6954173c4372cc.zip
Global functions.
-rw-r--r--AST.h11
-rw-r--r--ExpressionCompiler.cpp55
-rw-r--r--GlobalContext.cpp37
-rw-r--r--Types.h2
4 files changed, 77 insertions, 28 deletions
diff --git a/AST.h b/AST.h
index 89f268b3..3fb251d9 100644
--- a/AST.h
+++ b/AST.h
@@ -233,23 +233,20 @@ private:
};
/**
- * Pseudo AST node that is used as declaration for "this", "msg", "tx" and "block" when the
- * identifier is encountered. Will never have a valid location in the source code.
+ * Pseudo AST node that is used as declaration for "this", "msg", "tx", "block" and the global
+ * functions when such an identifier is encountered. Will never have a valid location in the source code.
*/
class MagicVariableDeclaration: public Declaration
{
public:
- enum class VariableKind { THIS, MSG, TX, BLOCK };
- MagicVariableDeclaration(VariableKind _kind, ASTString const& _name, std::shared_ptr<Type const> const& _type):
- Declaration(Location(), std::make_shared<ASTString>(_name)), m_kind(_kind), m_type(_type) {}
+ MagicVariableDeclaration(ASTString const& _name, std::shared_ptr<Type const> const& _type):
+ Declaration(Location(), std::make_shared<ASTString>(_name)), m_type(_type) {}
virtual void accept(ASTVisitor&) override { BOOST_THROW_EXCEPTION(InternalCompilerError()
<< errinfo_comment("MagicVariableDeclaration used inside real AST.")); }
std::shared_ptr<Type const> const& getType() const { return m_type; }
- VariableKind getKind() const { return m_kind; }
private:
- VariableKind m_kind;
std::shared_ptr<Type const> m_type;
};
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;
}
diff --git a/GlobalContext.cpp b/GlobalContext.cpp
index 4120dae5..e958352f 100644
--- a/GlobalContext.cpp
+++ b/GlobalContext.cpp
@@ -33,15 +33,33 @@ namespace solidity
{
GlobalContext::GlobalContext():
- m_magicVariables{make_shared<MagicVariableDeclaration>(MagicVariableDeclaration::VariableKind::BLOCK,
- "block",
- make_shared<MagicType>(MagicType::Kind::BLOCK)),
- make_shared<MagicVariableDeclaration>(MagicVariableDeclaration::VariableKind::MSG,
- "msg",
- make_shared<MagicType>(MagicType::Kind::MSG)),
- make_shared<MagicVariableDeclaration>(MagicVariableDeclaration::VariableKind::TX,
- "tx",
- make_shared<MagicType>(MagicType::Kind::TX))}
+ m_magicVariables{make_shared<MagicVariableDeclaration>("block", make_shared<MagicType>(MagicType::Kind::BLOCK)),
+ make_shared<MagicVariableDeclaration>("msg", make_shared<MagicType>(MagicType::Kind::MSG)),
+ make_shared<MagicVariableDeclaration>("tx", make_shared<MagicType>(MagicType::Kind::TX)),
+ make_shared<MagicVariableDeclaration>("suicide",
+ make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(0,
+ IntegerType::Modifier::ADDRESS)}),
+ TypePointers(),
+ FunctionType::Location::SUICIDE)),
+ make_shared<MagicVariableDeclaration>("sha3",
+ make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
+ TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
+ FunctionType::Location::SHA3)),
+ make_shared<MagicVariableDeclaration>("sha256",
+ make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
+ TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
+ FunctionType::Location::SHA256)),
+ make_shared<MagicVariableDeclaration>("ecrecover",
+ make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH),
+ std::make_shared<IntegerType>(8, IntegerType::Modifier::HASH),
+ std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH),
+ std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
+ TypePointers({std::make_shared<IntegerType>(0, IntegerType::Modifier::ADDRESS)}),
+ FunctionType::Location::ECRECOVER)),
+ make_shared<MagicVariableDeclaration>("ripemd160",
+ make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
+ TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
+ FunctionType::Location::RIPEMD160))}
{
}
@@ -64,7 +82,6 @@ MagicVariableDeclaration*GlobalContext::getCurrentThis() const
{
if (!m_thisPointer[m_currentContract])
m_thisPointer[m_currentContract] = make_shared<MagicVariableDeclaration>(
- MagicVariableDeclaration::VariableKind::THIS,
"this", make_shared<ContractType>(*m_currentContract));
return m_thisPointer[m_currentContract].get();
diff --git a/Types.h b/Types.h
index 630c9c21..b655f9e0 100644
--- a/Types.h
+++ b/Types.h
@@ -356,7 +356,7 @@ private:
class MagicType: public Type
{
public:
- enum class Kind { BLOCK, MSG, TX }; //@todo should be unified with MagicVariableDeclaration::VariableKind;
+ enum class Kind { BLOCK, MSG, TX };
virtual Category getCategory() const override { return Category::MAGIC; }
MagicType(Kind _kind);