Browse Source

Merge pull request #1053 from chriseth/sol_someEnumChanges

Some changes to enums.
cl-refactor
chriseth 10 years ago
parent
commit
6e145789db
  1. 13
      libsolidity/AST.cpp
  2. 4
      libsolidity/AST.h
  3. 19
      libsolidity/ExpressionCompiler.cpp
  4. 8
      libsolidity/NameAndTypeResolver.cpp
  5. 1
      libsolidity/NameAndTypeResolver.h
  6. 15
      test/SolidityEndToEndTest.cpp
  7. 2
      test/SolidityNameAndTypeResolution.cpp

13
libsolidity/AST.cpp

@ -262,19 +262,6 @@ void StructDefinition::checkRecursion() const
} }
} }
void EnumDefinition::checkValidityOfMembers() const
{
vector<ASTPointer<EnumValue>> members(getMembers());
auto compareDecls = [](ASTPointer<EnumValue> a, ASTPointer<EnumValue> b)
{
return a->getName() < b->getName();
};
sort(begin(members), end(members), compareDecls);
for (size_t i = 0; i < members.size() - 1; ++i)
if (members[i]->getName() == members[i + 1]->getName())
BOOST_THROW_EXCEPTION(members[i]->createTypeError("Duplicate member detected in Enum"));
}
TypePointer EnumDefinition::getType(ContractDefinition const*) const TypePointer EnumDefinition::getType(ContractDefinition const*) const
{ {
return make_shared<TypeType>(make_shared<EnumType>(*this)); return make_shared<TypeType>(make_shared<EnumType>(*this));

4
libsolidity/AST.h

@ -333,11 +333,7 @@ public:
virtual TypePointer getType(ContractDefinition const*) const override; virtual TypePointer getType(ContractDefinition const*) const override;
/// Checks that the members do not include any duplicate names
void checkValidityOfMembers() const;
private: private:
std::vector<ASTPointer<EnumValue>> m_members; std::vector<ASTPointer<EnumValue>> m_members;
}; };

19
libsolidity/ExpressionCompiler.cpp

@ -498,12 +498,10 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
case Type::Category::TypeType: case Type::Category::TypeType:
{ {
TypeType const& type = dynamic_cast<TypeType const&>(*_memberAccess.getExpression().getType()); TypeType const& type = dynamic_cast<TypeType const&>(*_memberAccess.getExpression().getType());
ContractType const* contractType;
EnumType const* enumType;
if (!type.getMembers().getMemberType(member)) if (!type.getMembers().getMemberType(member))
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to " + type.toString())); BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to " + type.toString()));
if ((contractType = dynamic_cast<ContractType const*>(type.getActualType().get()))) if (auto contractType = dynamic_cast<ContractType const*>(type.getActualType().get()))
{ {
ContractDefinition const& contract = contractType->getContractDefinition(); ContractDefinition const& contract = contractType->getContractDefinition();
for (ASTPointer<FunctionDefinition> const& function: contract.getDefinedFunctions()) for (ASTPointer<FunctionDefinition> const& function: contract.getDefinedFunctions())
@ -513,12 +511,9 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
return; return;
} }
} }
else if ((enumType = dynamic_cast<EnumType const*>(type.getActualType().get()))) else if (auto enumType = dynamic_cast<EnumType const*>(type.getActualType().get()))
{
m_context << enumType->getMemberValue(_memberAccess.getMemberName()); m_context << enumType->getMemberValue(_memberAccess.getMemberName());
return; break;
}
} }
case Type::Category::ByteArray: case Type::Category::ByteArray:
{ {
@ -764,8 +759,11 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con
} }
} }
} }
else if (stackTypeCategory == Type::Category::Enum)
solAssert(targetTypeCategory == Type::Category::Integer ||
targetTypeCategory == Type::Category::Enum, "");
else if (stackTypeCategory == Type::Category::Integer || stackTypeCategory == Type::Category::Contract || else if (stackTypeCategory == Type::Category::Integer || stackTypeCategory == Type::Category::Contract ||
stackTypeCategory == Type::Category::IntegerConstant || stackTypeCategory == Type::Category::Enum) stackTypeCategory == Type::Category::IntegerConstant)
{ {
if (targetTypeCategory == Type::Category::String && stackTypeCategory == Type::Category::Integer) if (targetTypeCategory == Type::Category::String && stackTypeCategory == Type::Category::Integer)
{ {
@ -777,6 +775,9 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con
solAssert(typeOnStack.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same."); solAssert(typeOnStack.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same.");
m_context << (u256(1) << (256 - typeOnStack.getNumBits())) << eth::Instruction::MUL; m_context << (u256(1) << (256 - typeOnStack.getNumBits())) << eth::Instruction::MUL;
} }
else if (targetTypeCategory == Type::Category::Enum)
// just clean
appendTypeConversion(_typeOnStack, *_typeOnStack.getRealType(), true);
else else
{ {
solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Contract, ""); solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Contract, "");

8
libsolidity/NameAndTypeResolver.cpp

@ -81,8 +81,6 @@ void NameAndTypeResolver::checkTypeRequirements(ContractDefinition& _contract)
{ {
for (ASTPointer<StructDefinition> const& structDef: _contract.getDefinedStructs()) for (ASTPointer<StructDefinition> const& structDef: _contract.getDefinedStructs())
structDef->checkValidityOfMembers(); structDef->checkValidityOfMembers();
for (ASTPointer<EnumDefinition> const& enumDef: _contract.getDefinedEnums())
enumDef->checkValidityOfMembers();
_contract.checkTypeRequirements(); _contract.checkTypeRequirements();
} }
@ -236,6 +234,12 @@ void DeclarationRegistrationHelper::endVisit(EnumDefinition&)
closeCurrentScope(); closeCurrentScope();
} }
bool DeclarationRegistrationHelper::visit(EnumValue& _value)
{
registerDeclaration(_value, false);
return true;
}
bool DeclarationRegistrationHelper::visit(FunctionDefinition& _function) bool DeclarationRegistrationHelper::visit(FunctionDefinition& _function)
{ {
registerDeclaration(_function, true); registerDeclaration(_function, true);

1
libsolidity/NameAndTypeResolver.h

@ -100,6 +100,7 @@ private:
void endVisit(StructDefinition& _struct) override; void endVisit(StructDefinition& _struct) override;
bool visit(EnumDefinition& _enum) override; bool visit(EnumDefinition& _enum) override;
void endVisit(EnumDefinition& _enum) override; void endVisit(EnumDefinition& _enum) override;
bool visit(EnumValue& _value) override;
bool visit(FunctionDefinition& _function) override; bool visit(FunctionDefinition& _function) override;
void endVisit(FunctionDefinition& _function) override; void endVisit(FunctionDefinition& _function) override;
bool visit(ModifierDefinition& _modifier) override; bool visit(ModifierDefinition& _modifier) override;

15
test/SolidityEndToEndTest.cpp

@ -2519,6 +2519,21 @@ BOOST_AUTO_TEST_CASE(using_enums)
BOOST_CHECK(callContractFunction("getChoice()") == encodeArgs(2)); BOOST_CHECK(callContractFunction("getChoice()") == encodeArgs(2));
} }
BOOST_AUTO_TEST_CASE(constructing_enums_from_ints)
{
char const* sourceCode = R"(
contract c {
enum Truth { False, True }
function test() returns (uint)
{
return uint(Truth(uint8(0x701)));
}
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("test()") == encodeArgs(1));
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

2
test/SolidityNameAndTypeResolution.cpp

@ -1080,7 +1080,7 @@ BOOST_AUTO_TEST_CASE(enum_duplicate_values)
enum ActionChoices { GoLeft, GoRight, GoLeft, Sit } enum ActionChoices { GoLeft, GoRight, GoLeft, Sit }
} }
)"; )";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError);
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

Loading…
Cancel
Save