aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2014-11-24 20:23:58 +0800
committerChristian <c@ethdev.com>2014-11-24 20:24:03 +0800
commit6e6b85b58a478a7e2bc0f8bee976df97f9861b91 (patch)
tree19902870438bb0cdb76e161bd5f26319676c4600
parent5d75263ff15aadfcacd35334cbab396cce65d260 (diff)
downloaddexon-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.cpp31
-rw-r--r--GlobalContext.cpp18
-rw-r--r--Types.cpp50
-rw-r--r--Types.h24
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)
diff --git a/Types.cpp b/Types.cpp
index 8ded428f..616c9183 100644
--- a/Types.cpp
+++ b/Types.cpp
@@ -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."));
+ }
+}
+
}
}
diff --git a/Types.h b/Types.h
index a8caf715..2dd4af64 100644
--- a/Types.h
+++ b/Types.h
@@ -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;
+};
+
}
}