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:
|
case Type::Category::Array:
|
||||||
{
|
{
|
||||||
ArrayType const& type = dynamic_cast<ArrayType const&>(*m_base->getType());
|
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_index->expectType(IntegerType(256));
|
||||||
m_type = type.getBaseType();
|
m_type = type.getBaseType();
|
||||||
m_isLValue = true;
|
m_isLValue = true;
|
||||||
@ -622,14 +624,32 @@ void IndexAccess::checkTypeRequirements()
|
|||||||
case Type::Category::Mapping:
|
case Type::Category::Mapping:
|
||||||
{
|
{
|
||||||
MappingType const& type = dynamic_cast<MappingType const&>(*m_base->getType());
|
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_index->expectType(*type.getKeyType());
|
||||||
m_type = type.getValueType();
|
m_type = type.getValueType();
|
||||||
m_isLValue = true;
|
m_isLValue = true;
|
||||||
break;
|
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:
|
default:
|
||||||
BOOST_THROW_EXCEPTION(m_base->createTypeError(
|
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;
|
virtual void checkTypeRequirements() override;
|
||||||
|
|
||||||
Expression const& getBaseExpression() const { return *m_base; }
|
Expression const& getBaseExpression() const { return *m_base; }
|
||||||
Expression const& getIndexExpression() const { return *m_index; }
|
Expression const* getIndexExpression() const { return m_index.get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASTPointer<Expression> m_base;
|
ASTPointer<Expression> m_base;
|
||||||
|
@ -626,7 +626,8 @@ void IndexAccess::accept(ASTVisitor& _visitor)
|
|||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
{
|
{
|
||||||
m_base->accept(_visitor);
|
m_base->accept(_visitor);
|
||||||
m_index->accept(_visitor);
|
if (m_index)
|
||||||
|
m_index->accept(_visitor);
|
||||||
}
|
}
|
||||||
_visitor.endVisit(*this);
|
_visitor.endVisit(*this);
|
||||||
}
|
}
|
||||||
@ -636,7 +637,8 @@ void IndexAccess::accept(ASTConstVisitor& _visitor) const
|
|||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
{
|
{
|
||||||
m_base->accept(_visitor);
|
m_base->accept(_visitor);
|
||||||
m_index->accept(_visitor);
|
if (m_index)
|
||||||
|
m_index->accept(_visitor);
|
||||||
}
|
}
|
||||||
_visitor.endVisit(*this);
|
_visitor.endVisit(*this);
|
||||||
}
|
}
|
||||||
|
@ -562,7 +562,8 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
|||||||
solAssert(baseType.getCategory() == Type::Category::Mapping, "");
|
solAssert(baseType.getCategory() == Type::Category::Mapping, "");
|
||||||
Type const& keyType = *dynamic_cast<MappingType const&>(baseType).getKeyType();
|
Type const& keyType = *dynamic_cast<MappingType const&>(baseType).getKeyType();
|
||||||
m_context << u256(0);
|
m_context << u256(0);
|
||||||
appendExpressionCopyToMemory(keyType, _indexAccess.getIndexExpression());
|
solAssert(_indexAccess.getIndexExpression(), "Index expression expected.");
|
||||||
|
appendExpressionCopyToMemory(keyType, *_indexAccess.getIndexExpression());
|
||||||
solAssert(baseType.getSizeOnStack() == 1,
|
solAssert(baseType.getSizeOnStack() == 1,
|
||||||
"Unexpected: Not exactly one stack slot taken by subscriptable expression.");
|
"Unexpected: Not exactly one stack slot taken by subscriptable expression.");
|
||||||
m_context << eth::Instruction::SWAP1;
|
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;
|
vector<pair<ASTPointer<Expression>, Location>> indices;
|
||||||
solAssert(m_scanner->getCurrentToken() == Token::LBrack, "");
|
solAssert(m_scanner->getCurrentToken() == Token::LBrack, "");
|
||||||
Location indexLocation = primary->getLocation();
|
Location indexLocation = primary->getLocation();
|
||||||
bool encounteredEmptyBrackets = false;
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
expectToken(Token::LBrack);
|
expectToken(Token::LBrack);
|
||||||
ASTPointer<Expression> index;
|
ASTPointer<Expression> index;
|
||||||
if (m_scanner->getCurrentToken() == Token::RBrack)
|
if (m_scanner->getCurrentToken() != Token::RBrack)
|
||||||
encounteredEmptyBrackets = true;
|
|
||||||
else
|
|
||||||
index = parseExpression();
|
index = parseExpression();
|
||||||
indexLocation.end = getEndPosition();
|
indexLocation.end = getEndPosition();
|
||||||
indices.push_back(make_pair(index, indexLocation));
|
indices.push_back(make_pair(index, indexLocation));
|
||||||
@ -660,7 +657,7 @@ ASTPointer<Statement> Parser::parseSimpleStatement()
|
|||||||
}
|
}
|
||||||
while (m_scanner->getCurrentToken() == Token::LBrack);
|
while (m_scanner->getCurrentToken() == Token::LBrack);
|
||||||
|
|
||||||
if (m_scanner->getCurrentToken() == Token::Identifier || encounteredEmptyBrackets)
|
if (m_scanner->getCurrentToken() == Token::Identifier)
|
||||||
return parseVariableDeclarationStatement(typeNameFromArrayIndexStructure(primary, indices));
|
return parseVariableDeclarationStatement(typeNameFromArrayIndexStructure(primary, indices));
|
||||||
else
|
else
|
||||||
return parseExpressionStatement(expressionFromArrayIndexStructure(primary, indices));
|
return parseExpressionStatement(expressionFromArrayIndexStructure(primary, indices));
|
||||||
@ -768,7 +765,9 @@ ASTPointer<Expression> Parser::parseLeftHandSideExpression(
|
|||||||
case Token::LBrack:
|
case Token::LBrack:
|
||||||
{
|
{
|
||||||
m_scanner->next();
|
m_scanner->next();
|
||||||
ASTPointer<Expression> index = parseExpression();
|
ASTPointer<Expression> index;
|
||||||
|
if (m_scanner->getCurrentToken() != Token::RBrack)
|
||||||
|
index = parseExpression();
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
expectToken(Token::RBrack);
|
expectToken(Token::RBrack);
|
||||||
expression = nodeFactory.createNode<IndexAccess>(expression, index);
|
expression = nodeFactory.createNode<IndexAccess>(expression, index);
|
||||||
|
@ -18,8 +18,9 @@ ParameterList = '(' ( VariableDeclaration (',' VariableDeclaration)* )? ')'
|
|||||||
// semantic restriction: mappings and structs (recursively) containing mappings
|
// semantic restriction: mappings and structs (recursively) containing mappings
|
||||||
// are not allowed in argument lists
|
// are not allowed in argument lists
|
||||||
VariableDeclaration = TypeName Identifier
|
VariableDeclaration = TypeName Identifier
|
||||||
TypeName = ElementaryTypeName | Identifier | Mapping
|
TypeName = ElementaryTypeName | Identifier | Mapping | ArrayTypeName
|
||||||
Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')'
|
Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')'
|
||||||
|
ArrayTypeName = TypeName '[' (Expression)? ']'
|
||||||
|
|
||||||
Block = '{' Statement* '}'
|
Block = '{' Statement* '}'
|
||||||
Statement = IfStatement | WhileStatement | Block |
|
Statement = IfStatement | WhileStatement | Block |
|
||||||
@ -42,5 +43,5 @@ Assignment = Expression (AssignmentOp Expression)
|
|||||||
FunctionCall = Expression '(' Expression ( ',' Expression )* ')'
|
FunctionCall = Expression '(' Expression ( ',' Expression )* ')'
|
||||||
NewExpression = 'new' Identifier
|
NewExpression = 'new' Identifier
|
||||||
MemberAccess = Expression '.' Identifier
|
MemberAccess = Expression '.' Identifier
|
||||||
IndexAccess = Expression '[' Expresison ']'
|
IndexAccess = Expression '[' (Expresison)? ']'
|
||||||
PrimaryExpression = Identifier | NumberLiteral | StringLiteral | ElementaryTypeName | '(' Expression ')'
|
PrimaryExpression = Identifier | NumberLiteral | StringLiteral | ElementaryTypeName | '(' Expression ')'
|
||||||
|
Loading…
Reference in New Issue
Block a user