diff options
author | Christian <c@ethdev.com> | 2014-11-24 20:23:58 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2014-11-24 20:24:03 +0800 |
commit | 6e6b85b58a478a7e2bc0f8bee976df97f9861b91 (patch) | |
tree | 19902870438bb0cdb76e161bd5f26319676c4600 | |
parent | 5d75263ff15aadfcacd35334cbab396cce65d260 (diff) | |
download | dexon-solidity-6e6b85b58a478a7e2bc0f8bee976df97f9861b91.tar dexon-solidity-6e6b85b58a478a7e2bc0f8bee976df97f9861b91.tar.gz dexon-solidity-6e6b85b58a478a7e2bc0f8bee976df97f9861b91.tar.bz2 dexon-solidity-6e6b85b58a478a7e2bc0f8bee976df97f9861b91.tar.lz dexon-solidity-6e6b85b58a478a7e2bc0f8bee976df97f9861b91.tar.xz dexon-solidity-6e6b85b58a478a7e2bc0f8bee976df97f9861b91.tar.zst dexon-solidity-6e6b85b58a478a7e2bc0f8bee976df97f9861b91.zip |
Access to blockchain data.
-rw-r--r-- | ExpressionCompiler.cpp | 31 | ||||
-rw-r--r-- | GlobalContext.cpp | 18 | ||||
-rw-r--r-- | Types.cpp | 50 | ||||
-rw-r--r-- | Types.h | 24 |
4 files changed, 112 insertions, 11 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index b1a49457..de8bc1d2 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -212,10 +212,11 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall) void ExpressionCompiler::endVisit(MemberAccess& _memberAccess) { + ASTString const& member = _memberAccess.getMemberName(); switch (_memberAccess.getExpression().getType()->getCategory()) { case Type::Category::INTEGER: - if (asserts(_memberAccess.getMemberName() == "balance")) + if (asserts(member == "balance")) BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to integer.")); m_context << eth::Instruction::BALANCE; break; @@ -224,12 +225,36 @@ void ExpressionCompiler::endVisit(MemberAccess& _memberAccess) BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Contract variables not yet implemented.")); break; case Type::Category::MAGIC: - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Magic variables not yet implemented.")); + // we can ignore the kind of magic and only look at the name of the member + if (member == "coinbase") + m_context << eth::Instruction::COINBASE; + else if (member == "timestamp") + m_context << eth::Instruction::TIMESTAMP; + else if (member == "prevhash") + m_context << eth::Instruction::PREVHASH; + else if (member == "difficulty") + m_context << eth::Instruction::DIFFICULTY; + else if (member == "number") + m_context << eth::Instruction::NUMBER; + else if (member == "gaslimit") + m_context << eth::Instruction::GASLIMIT; + else if (member == "sender") + m_context << eth::Instruction::CALLER; + else if (member == "value") + m_context << eth::Instruction::CALLVALUE; + else if (member == "origin") + m_context << eth::Instruction::ORIGIN; + else if (member == "gas") + m_context << eth::Instruction::GAS; + else if (member == "gasprice") + m_context << eth::Instruction::GASPRICE; + else + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown magic member.")); break; case Type::Category::STRUCT: { StructType const& type = dynamic_cast<StructType const&>(*_memberAccess.getExpression().getType()); - m_context << type.getStorageOffsetOfMember(_memberAccess.getMemberName()) << eth::Instruction::ADD; + m_context << type.getStorageOffsetOfMember(member) << eth::Instruction::ADD; m_currentLValue = LValue(m_context, LValue::STORAGE); m_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess); break; diff --git a/GlobalContext.cpp b/GlobalContext.cpp index f2e6d9ce..4120dae5 100644 --- a/GlobalContext.cpp +++ b/GlobalContext.cpp @@ -32,15 +32,17 @@ namespace dev namespace solidity { -GlobalContext::GlobalContext() +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))} { - // CurrentContract this; // @todo type depends on context -> switch prior to entering contract - // Message msg; - // Transaction tx; - // Block block; - - //@todo type will be a custom complex type, maybe the same type class for msg tx and block. - //addVariable("msg", ); } void GlobalContext::setCurrentContract(ContractDefinition const& _contract) @@ -333,5 +333,55 @@ bool TypeType::operator==(Type const& _other) const return *getActualType() == *other.getActualType(); } +MagicType::MagicType(MagicType::Kind _kind): + m_kind(_kind) +{ + switch (m_kind) + { + case Kind::BLOCK: + m_members = MemberList({{"coinbase", make_shared<IntegerType const>(0, IntegerType::Modifier::ADDRESS)}, + {"timestamp", make_shared<IntegerType const>(256)}, + {"prevhash", make_shared<IntegerType const>(256, IntegerType::Modifier::HASH)}, + {"difficulty", make_shared<IntegerType const>(256)}, + {"number", make_shared<IntegerType const>(256)}, + {"gaslimit", make_shared<IntegerType const>(256)}}); + break; + case Kind::MSG: + m_members = MemberList({{"sender", make_shared<IntegerType const>(0, IntegerType::Modifier::ADDRESS)}, + {"value", make_shared<IntegerType const>(256)}}); + break; + case Kind::TX: + m_members = MemberList({{"origin", make_shared<IntegerType const>(0, IntegerType::Modifier::ADDRESS)}, + {"gas", make_shared<IntegerType const>(256)}, + {"gasprice", make_shared<IntegerType const>(256)}}); + break; + default: + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown kind of magic.")); + } +} + +bool MagicType::operator==(Type const& _other) const +{ + if (_other.getCategory() != getCategory()) + return false; + MagicType const& other = dynamic_cast<MagicType const&>(_other); + return other.m_kind == m_kind; +} + +string MagicType::toString() const +{ + switch (m_kind) + { + case Kind::BLOCK: + return "block"; + case Kind::MSG: + return "msg"; + case Kind::TX: + return "tx"; + default: + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown kind of magic.")); + } +} + } } @@ -327,5 +327,29 @@ private: }; +/** + * Special type for magic variables (block, msg, tx), similar to a struct but without any reference + * (it always references a global singleton by name). + */ +class MagicType: public Type +{ +public: + enum class Kind { BLOCK, MSG, TX }; //@todo should be unified with MagicVariableDeclaration::VariableKind; + virtual Category getCategory() const override { return Category::MAGIC; } + + MagicType(Kind _kind); + virtual bool operator==(Type const& _other) const; + virtual bool canBeStored() const override { return false; } + virtual bool canLiveOutsideStorage() const override { return true; } + virtual MemberList const& getMembers() const override { return m_members; } + + virtual std::string toString() const override; + +private: + Kind m_kind; + + MemberList m_members; +}; + } } |