Browse Source

Allow conversion to dynamic arrays and update grammar.

cl-refactor
Christian 10 years ago
parent
commit
92507f5bf0
  1. 22
      libsolidity/AST.cpp
  2. 2
      libsolidity/AST.h
  3. 2
      libsolidity/AST_accept.h
  4. 3
      libsolidity/ExpressionCompiler.cpp
  5. 11
      libsolidity/Parser.cpp
  6. 5
      libsolidity/grammar.txt
  7. 11
      test/SolidityParser.cpp

22
libsolidity/AST.cpp

@ -614,6 +614,8 @@ void IndexAccess::checkTypeRequirements()
case Type::Category::Array:
{
ArrayType const& type = dynamic_cast<ArrayType const&>(*m_base->getType());
if (!m_index)
BOOST_THROW_EXCEPTION(createTypeError("Index expression cannot be omitted."));
m_index->expectType(IntegerType(256));
m_type = type.getBaseType();
m_isLValue = true;
@ -622,14 +624,32 @@ void IndexAccess::checkTypeRequirements()
case Type::Category::Mapping:
{
MappingType const& type = dynamic_cast<MappingType const&>(*m_base->getType());
if (!m_index)
BOOST_THROW_EXCEPTION(createTypeError("Index expression cannot be omitted."));
m_index->expectType(*type.getKeyType());
m_type = type.getValueType();
m_isLValue = true;
break;
}
case Type::Category::TypeType:
{
TypeType const& type = dynamic_cast<TypeType const&>(*m_base->getType());
if (!m_index)
m_type = make_shared<TypeType>(make_shared<ArrayType>(ArrayType::Location::Memory, type.getActualType()));
else
{
m_index->checkTypeRequirements();
auto length = dynamic_cast<IntegerConstantType const*>(m_index->getType().get());
if (!length)
BOOST_THROW_EXCEPTION(m_index->createTypeError("Integer constant expected."));
m_type = make_shared<TypeType>(make_shared<ArrayType>(
ArrayType::Location::Memory, type.getActualType(), length->literalValue(nullptr)));
}
break;
}
default:
BOOST_THROW_EXCEPTION(m_base->createTypeError(
"Indexed expression has to be a mapping or array (is " + m_base->getType()->toString() + ")"));
"Indexed expression has to be a type, mapping or array (is " + m_base->getType()->toString() + ")"));
}
}

2
libsolidity/AST.h

@ -1102,7 +1102,7 @@ public:
virtual void checkTypeRequirements() override;
Expression const& getBaseExpression() const { return *m_base; }
Expression const& getIndexExpression() const { return *m_index; }
Expression const* getIndexExpression() const { return m_index.get(); }
private:
ASTPointer<Expression> m_base;

2
libsolidity/AST_accept.h

@ -626,6 +626,7 @@ void IndexAccess::accept(ASTVisitor& _visitor)
if (_visitor.visit(*this))
{
m_base->accept(_visitor);
if (m_index)
m_index->accept(_visitor);
}
_visitor.endVisit(*this);
@ -636,6 +637,7 @@ void IndexAccess::accept(ASTConstVisitor& _visitor) const
if (_visitor.visit(*this))
{
m_base->accept(_visitor);
if (m_index)
m_index->accept(_visitor);
}
_visitor.endVisit(*this);

3
libsolidity/ExpressionCompiler.cpp

@ -562,7 +562,8 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
solAssert(baseType.getCategory() == Type::Category::Mapping, "");
Type const& keyType = *dynamic_cast<MappingType const&>(baseType).getKeyType();
m_context << u256(0);
appendExpressionCopyToMemory(keyType, _indexAccess.getIndexExpression());
solAssert(_indexAccess.getIndexExpression(), "Index expression expected.");
appendExpressionCopyToMemory(keyType, *_indexAccess.getIndexExpression());
solAssert(baseType.getSizeOnStack() == 1,
"Unexpected: Not exactly one stack slot taken by subscriptable expression.");
m_context << eth::Instruction::SWAP1;

11
libsolidity/Parser.cpp

@ -645,14 +645,11 @@ ASTPointer<Statement> Parser::parseSimpleStatement()
vector<pair<ASTPointer<Expression>, Location>> indices;
solAssert(m_scanner->getCurrentToken() == Token::LBrack, "");
Location indexLocation = primary->getLocation();
bool encounteredEmptyBrackets = false;
do
{
expectToken(Token::LBrack);
ASTPointer<Expression> index;
if (m_scanner->getCurrentToken() == Token::RBrack)
encounteredEmptyBrackets = true;
else
if (m_scanner->getCurrentToken() != Token::RBrack)
index = parseExpression();
indexLocation.end = getEndPosition();
indices.push_back(make_pair(index, indexLocation));
@ -660,7 +657,7 @@ ASTPointer<Statement> Parser::parseSimpleStatement()
}
while (m_scanner->getCurrentToken() == Token::LBrack);
if (m_scanner->getCurrentToken() == Token::Identifier || encounteredEmptyBrackets)
if (m_scanner->getCurrentToken() == Token::Identifier)
return parseVariableDeclarationStatement(typeNameFromArrayIndexStructure(primary, indices));
else
return parseExpressionStatement(expressionFromArrayIndexStructure(primary, indices));
@ -768,7 +765,9 @@ ASTPointer<Expression> Parser::parseLeftHandSideExpression(
case Token::LBrack:
{
m_scanner->next();
ASTPointer<Expression> index = parseExpression();
ASTPointer<Expression> index;
if (m_scanner->getCurrentToken() != Token::RBrack)
index = parseExpression();
nodeFactory.markEndPosition();
expectToken(Token::RBrack);
expression = nodeFactory.createNode<IndexAccess>(expression, index);

5
libsolidity/grammar.txt

@ -18,8 +18,9 @@ ParameterList = '(' ( VariableDeclaration (',' VariableDeclaration)* )? ')'
// semantic restriction: mappings and structs (recursively) containing mappings
// are not allowed in argument lists
VariableDeclaration = TypeName Identifier
TypeName = ElementaryTypeName | Identifier | Mapping
TypeName = ElementaryTypeName | Identifier | Mapping | ArrayTypeName
Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')'
ArrayTypeName = TypeName '[' (Expression)? ']'
Block = '{' Statement* '}'
Statement = IfStatement | WhileStatement | Block |
@ -42,5 +43,5 @@ Assignment = Expression (AssignmentOp Expression)
FunctionCall = Expression '(' Expression ( ',' Expression )* ')'
NewExpression = 'new' Identifier
MemberAccess = Expression '.' Identifier
IndexAccess = Expression '[' Expresison ']'
IndexAccess = Expression '[' (Expresison)? ']'
PrimaryExpression = Identifier | NumberLiteral | StringLiteral | ElementaryTypeName | '(' Expression ')'

11
test/SolidityParser.cpp

@ -481,6 +481,17 @@ BOOST_AUTO_TEST_CASE(statement_starting_with_type_conversion)
" function fun() {\n"
" uint64(2);\n"
" uint64[7](3);\n"
" uint64[](3);\n"
" }\n"
"}\n";
BOOST_CHECK_NO_THROW(parseText(text));
}
BOOST_AUTO_TEST_CASE(type_conversion_to_dynamic_array)
{
char const* text = "contract test {\n"
" function fun() {\n"
" var x = uint64[](3);\n"
" }\n"
"}\n";
BOOST_CHECK_NO_THROW(parseText(text));

Loading…
Cancel
Save