mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Access to blockchain data.
This commit is contained in:
parent
5d75263ff1
commit
6e6b85b58a
@ -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;
|
||||
|
@ -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)
|
||||
|
50
Types.cpp
50
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."));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
24
Types.h
24
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;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user