mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Allow conversion to dynamic arrays and update grammar.
This commit is contained in:
parent
be15e0b424
commit
261786d909
22
AST.cpp
22
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
AST.h
2
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;
|
||||
|
@ -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);
|
||||
|
@ -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
Parser.cpp
11
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);
|
||||
|
@ -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 ')'
|
||||
|
Loading…
Reference in New Issue
Block a user