Allow conversion to dynamic arrays and update grammar.

This commit is contained in:
Christian 2015-02-21 18:25:08 +01:00
parent be15e0b424
commit 261786d909
6 changed files with 36 additions and 13 deletions

22
AST.cpp
View File

@ -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
AST.h
View File

@ -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;

View File

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

View File

@ -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;

View File

@ -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);

View File

@ -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 ')'