Browse Source

Enum type conversion and member value access.

- Added tests for the type conversion part.

- Enum member value access still needs some work
cl-refactor
Lefteris Karapetsas 10 years ago
parent
commit
07886f42bb
  1. 13
      libsolidity/AST.cpp
  2. 3
      libsolidity/AST.h
  3. 12
      libsolidity/ExpressionCompiler.cpp
  4. 5
      libsolidity/Types.cpp
  5. 2
      libsolidity/Types.h
  6. 2
      test/SolidityEndToEndTest.cpp
  7. 34
      test/SolidityNameAndTypeResolution.cpp

13
libsolidity/AST.cpp

@ -277,6 +277,19 @@ TypePointer EnumDefinition::getType(ContractDefinition const*) const
return make_shared<TypeType>(make_shared<EnumType>(*this));
}
unsigned int EnumDefinition::getMemberValue(ASTString const& _member) const
{
unsigned int index = 0;
for (ASTPointer<EnumDeclaration> const& decl: m_members)
{
if (decl->getName() == _member)
return index;
++index;
}
BOOST_THROW_EXCEPTION(createTypeError("Requested unknown enum value ." + _member));
}
TypePointer FunctionDefinition::getType(ContractDefinition const*) const
{
return make_shared<FunctionType>(*this);

3
libsolidity/AST.h

@ -348,6 +348,9 @@ public:
virtual TypePointer getType(ContractDefinition const*) const override;
/// @returns the value that the string has in the Enum
unsigned int getMemberValue(ASTString const& _member) const;
/// Checks that the members do not include any duplicate names
void checkValidityOfMembers() const;

12
libsolidity/ExpressionCompiler.cpp

@ -489,6 +489,12 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
m_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess);
break;
}
case Type::Category::Enum:
{
EnumType const& type = dynamic_cast<EnumType const&>(*_memberAccess.getExpression().getType());
EnumDefinition const& enumDef = type.getEnumDefinition();
m_context << enumDef.getMemberValue(_memberAccess.getMemberName());
}
case Type::Category::TypeType:
{
TypeType const& type = dynamic_cast<TypeType const&>(*_memberAccess.getExpression().getType());
@ -562,6 +568,10 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
{
// no-op
}
else if (dynamic_cast<EnumDefinition const*>(declaration))
{
// no-op
}
else
{
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier type not expected in expression context."));
@ -746,7 +756,7 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con
}
}
else if (stackTypeCategory == Type::Category::Integer || stackTypeCategory == Type::Category::Contract ||
stackTypeCategory == Type::Category::IntegerConstant)
stackTypeCategory == Type::Category::IntegerConstant || stackTypeCategory == Type::Category::Enum)
{
if (targetTypeCategory == Type::Category::String && stackTypeCategory == Type::Category::Integer)
{

5
libsolidity/Types.cpp

@ -682,6 +682,11 @@ string EnumType::toString() const
return string("enum ") + m_enum.getName();
}
bool EnumType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
return _convertTo.getCategory() == getCategory() || _convertTo.getCategory() == Category::Integer;
}
FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal):
m_location(_isInternal ? Location::Internal : Location::External),
m_isConstant(_function.isDeclaredConst()),

2
libsolidity/Types.h

@ -381,6 +381,8 @@ public:
virtual std::string toString() const override;
virtual bool isValueType() const override { return true; }
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
EnumDefinition const& getEnumDefinition() const { return m_enum; }
private:

2
test/SolidityEndToEndTest.cpp

@ -2510,7 +2510,7 @@ BOOST_AUTO_TEST_CASE(using_enums)
}
function getChoice() returns (uint d)
{
d = choices;
d = uint256(choices);
}
ActionChoices choices;
}

34
test/SolidityNameAndTypeResolution.cpp

@ -1022,6 +1022,40 @@ BOOST_AUTO_TEST_CASE(enum_invalid_member_access)
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(enum_explicit_conversion_is_okay)
{
char const* text = R"(
contract test {
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit };
function test()
{
a = uint256(ActionChoices.GoStraight);
b = uint64(ActionChoices.Sit);
}
uint256 a;
uint64 b;
}
)";
BOOST_CHECK_NO_THROW(parseTextAndResolveNamesWithChecks(text));
}
BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay)
{
char const* text = R"(
contract test {
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit };
function test()
{
a = ActionChoices.GoStraight;
b = ActionChoices.Sit;
}
uint256 a;
uint64 b;
}
)";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_SUITE_END()
}

Loading…
Cancel
Save