Most trivial members.

This commit is contained in:
chriseth 2019-05-02 21:17:06 +02:00
parent b99ad2aaa3
commit acca390ef5
3 changed files with 187 additions and 6 deletions

View File

@ -393,6 +393,154 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
}
}
void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
{
ASTString const& member = _memberAccess.memberName();
if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type))
if (funType->bound())
{
solUnimplementedAssert(false, "");
}
switch (_memberAccess.expression().annotation().type->category())
{
case Type::Category::Contract:
{
ContractType const& type = dynamic_cast<ContractType const&>(*_memberAccess.expression().annotation().type);
if (type.isSuper())
{
solUnimplementedAssert(false, "");
}
// ordinary contract type
else if (Declaration const* declaration = _memberAccess.annotation().referencedDeclaration)
{
u256 identifier;
if (auto const* variable = dynamic_cast<VariableDeclaration const*>(declaration))
identifier = FunctionType(*variable).externalIdentifier();
else if (auto const* function = dynamic_cast<FunctionDefinition const*>(declaration))
identifier = FunctionType(*function).externalIdentifier();
else
solAssert(false, "Contract member is neither variable nor function.");
// TODO here, we need to assign address and function identifier to two variables.
// We migt also just combine them into a single variable already....
solUnimplementedAssert(false, "");
}
else
solAssert(false, "Invalid member access in contract");
break;
}
case Type::Category::Integer:
{
solAssert(false, "Invalid member access to integer");
break;
}
case Type::Category::Address:
{
if (member == "balance")
defineExpression(_memberAccess) <<
"balance(" <<
expressionAsType(_memberAccess.expression(), *TypeProvider::address()) <<
")\n";
else if (set<string>{"send", "transfer"}.count(member))
{
solAssert(dynamic_cast<AddressType const&>(*_memberAccess.expression().annotation().type).stateMutability() == StateMutability::Payable, "");
defineExpression(_memberAccess) <<
expressionAsType(_memberAccess.expression(), *TypeProvider::payableAddress()) <<
"\n";
}
else if (set<string>{"call", "callcode", "delegatecall", "staticcall"}.count(member))
defineExpression(_memberAccess) <<
expressionAsType(_memberAccess.expression(), *TypeProvider::address()) <<
"\n";
else
solAssert(false, "Invalid member access to address");
break;
}
case Type::Category::Function:
if (member == "selector")
{
solUnimplementedAssert(false, "");
}
else
solAssert(
!!_memberAccess.expression().annotation().type->memberType(member),
"Invalid member access to function."
);
break;
case Type::Category::Magic:
// we can ignore the kind of magic and only look at the name of the member
if (member == "coinbase")
defineExpression(_memberAccess) << "coinbase()\n";
else if (member == "timestamp")
defineExpression(_memberAccess) << "timestamp()\n";
else if (member == "difficulty")
defineExpression(_memberAccess) << "difficulty()\n";
else if (member == "number")
defineExpression(_memberAccess) << "number()\n";
else if (member == "gaslimit")
defineExpression(_memberAccess) << "gaslimit()\n";
else if (member == "sender")
defineExpression(_memberAccess) << "caller()\n";
else if (member == "value")
defineExpression(_memberAccess) << "callvalue()\n";
else if (member == "origin")
defineExpression(_memberAccess) << "origin()\n";
else if (member == "gasprice")
defineExpression(_memberAccess) << "gasprice()\n";
else if (member == "data")
solUnimplementedAssert(false, "");
else if (member == "sig")
defineExpression(_memberAccess) <<
"and(calldataload(0), " <<
formatNumber(u256(0xffffffff) << (256 - 32)) <<
")\n";
else if (member == "gas")
solAssert(false, "Gas has been removed.");
else if (member == "blockhash")
solAssert(false, "Blockhash has been removed.");
else if (member == "creationCode" || member == "runtimeCode")
{
solUnimplementedAssert(false, "");
}
else if (member == "name")
{
solUnimplementedAssert(false, "");
}
else if (set<string>{"encode", "encodePacked", "encodeWithSelector", "encodeWithSignature", "decode"}.count(member))
{
// no-op
}
else
solAssert(false, "Unknown magic member.");
break;
case Type::Category::Struct:
{
solUnimplementedAssert(false, "");
}
case Type::Category::Enum:
{
EnumType const& type = dynamic_cast<EnumType const&>(*_memberAccess.expression().annotation().type);
defineExpression(_memberAccess) << to_string(type.memberValue(_memberAccess.memberName())) << "\n";
break;
}
case Type::Category::Array:
{
solUnimplementedAssert(false, "");
}
case Type::Category::FixedBytes:
{
auto const& type = dynamic_cast<FixedBytesType const&>(*_memberAccess.expression().annotation().type);
if (member == "length")
defineExpression(_memberAccess) << to_string(type.numBytes());
else
solAssert(false, "Illegal fixed bytes member.");
break;
}
default:
solAssert(false, "Member access to unknown type.");
}
}
bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm)
{
CopyTranslate bodyCopier{m_context, _inlineAsm.annotation().externalReferences};
@ -405,10 +553,32 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm)
return false;
}
bool IRGeneratorForStatements::visit(Identifier const& _identifier)
void IRGeneratorForStatements::endVisit(Identifier const& _identifier)
{
Declaration const* declaration = _identifier.annotation().referencedDeclaration;
if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration))
if (MagicVariableDeclaration const* magicVar = dynamic_cast<MagicVariableDeclaration const*>(declaration))
{
switch (magicVar->type()->category())
{
case Type::Category::Contract:
if (dynamic_cast<ContractType const&>(*magicVar->type()).isSuper())
solAssert(_identifier.name() == "super", "");
else
{
solAssert(_identifier.name() == "this", "");
defineExpression(_identifier) << "address()\n";
}
break;
case Type::Category::Integer:
solAssert(_identifier.name() == "now", "");
defineExpression(_identifier) << "timestamp()\n";
break;
default:
break;
}
return;
}
else if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration))
defineExpression(_identifier) << to_string(m_context.virtualFunction(*functionDef).id()) << "\n";
else if (VariableDeclaration const* varDecl = dynamic_cast<VariableDeclaration const*>(declaration))
{
@ -426,9 +596,8 @@ bool IRGeneratorForStatements::visit(Identifier const& _identifier)
setLValue(_identifier, move(lvalue));
}
else if (!dynamic_cast<MagicVariableDeclaration const*>(declaration))
solUnimplemented("");
return false;
else
solUnimplemented("Identifier of type " + declaration->type()->toString() + " not implemented.");
}
bool IRGeneratorForStatements::visit(Literal const& _literal)

View File

@ -55,8 +55,9 @@ public:
void endVisit(UnaryOperation const& _unaryOperation) override;
bool visit(BinaryOperation const& _binOp) override;
void endVisit(FunctionCall const& _funCall) override;
void endVisit(MemberAccess const& _memberAccess) override;
bool visit(InlineAssembly const& _inlineAsm) override;
bool visit(Identifier const& _identifier) override;
void endVisit(Identifier const& _identifier) override;
bool visit(Literal const& _literal) override;
private:

View File

@ -0,0 +1,11 @@
contract C {
function test() public view returns (bool) {
address x;
assembly { x := caller() }
return x == msg.sender;
}
}
// ====
// compileViaYul: true
// ----
// test() -> true