compiler: Permit "for range x" clauses.
Fixes Issue 8370. From-SVN: r216051
This commit is contained in:
parent
3369b91936
commit
ea411f8480
2 changed files with 36 additions and 19 deletions
|
@ -3836,6 +3836,12 @@ Parse::simple_stat(bool may_be_composite_lit, bool* return_exp,
|
|||
this->unget_token(Token::make_identifier_token(identifier, is_exported,
|
||||
location));
|
||||
}
|
||||
else if (p_range_clause != NULL && token->is_keyword(KEYWORD_RANGE))
|
||||
{
|
||||
Typed_identifier_list til;
|
||||
this->range_clause_decl(&til, p_range_clause);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Expression* exp = this->expression(PRECEDENCE_NORMAL, true,
|
||||
may_be_composite_lit,
|
||||
|
@ -5278,7 +5284,7 @@ Parse::for_clause(Expression** cond, Block** post)
|
|||
}
|
||||
}
|
||||
|
||||
// RangeClause = IdentifierList ( "=" | ":=" ) "range" Expression .
|
||||
// RangeClause = [ IdentifierList ( "=" | ":=" ) ] "range" Expression .
|
||||
|
||||
// This is the := version. It is called with a list of identifiers.
|
||||
|
||||
|
@ -5291,7 +5297,6 @@ Parse::range_clause_decl(const Typed_identifier_list* til,
|
|||
|
||||
p_range_clause->found = true;
|
||||
|
||||
go_assert(til->size() >= 1);
|
||||
if (til->size() > 2)
|
||||
error_at(this->location(), "too many variables for range clause");
|
||||
|
||||
|
@ -5300,6 +5305,9 @@ Parse::range_clause_decl(const Typed_identifier_list* til,
|
|||
NULL);
|
||||
p_range_clause->range = expr;
|
||||
|
||||
if (til->empty())
|
||||
return;
|
||||
|
||||
bool any_new = false;
|
||||
|
||||
const Typed_identifier* pti = &til->front();
|
||||
|
@ -5347,6 +5355,9 @@ Parse::range_clause_expr(const Expression_list* vals,
|
|||
p_range_clause->range = this->expression(PRECEDENCE_NORMAL, false, false,
|
||||
NULL, NULL);
|
||||
|
||||
if (vals->empty())
|
||||
return;
|
||||
|
||||
p_range_clause->index = vals->front();
|
||||
if (vals->size() == 1)
|
||||
p_range_clause->value = NULL;
|
||||
|
|
|
@ -5305,8 +5305,12 @@ Statement::make_for_statement(Block* init, Expression* cond, Block* post,
|
|||
int
|
||||
For_range_statement::do_traverse(Traverse* traverse)
|
||||
{
|
||||
if (this->traverse_expression(traverse, &this->index_var_) == TRAVERSE_EXIT)
|
||||
return TRAVERSE_EXIT;
|
||||
if (this->index_var_ != NULL)
|
||||
{
|
||||
if (this->traverse_expression(traverse, &this->index_var_)
|
||||
== TRAVERSE_EXIT)
|
||||
return TRAVERSE_EXIT;
|
||||
}
|
||||
if (this->value_var_ != NULL)
|
||||
{
|
||||
if (this->traverse_expression(traverse, &this->value_var_)
|
||||
|
@ -5434,25 +5438,27 @@ For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
|
|||
if (iter_init != NULL)
|
||||
body->add_statement(Statement::make_block_statement(iter_init, loc));
|
||||
|
||||
Statement* assign;
|
||||
Expression* index_ref = Expression::make_temporary_reference(index_temp, loc);
|
||||
if (this->value_var_ == NULL)
|
||||
if (this->index_var_ != NULL)
|
||||
{
|
||||
assign = Statement::make_assignment(this->index_var_, index_ref, loc);
|
||||
}
|
||||
else
|
||||
{
|
||||
Expression_list* lhs = new Expression_list();
|
||||
lhs->push_back(this->index_var_);
|
||||
lhs->push_back(this->value_var_);
|
||||
Statement* assign;
|
||||
Expression* index_ref =
|
||||
Expression::make_temporary_reference(index_temp, loc);
|
||||
if (this->value_var_ == NULL)
|
||||
assign = Statement::make_assignment(this->index_var_, index_ref, loc);
|
||||
else
|
||||
{
|
||||
Expression_list* lhs = new Expression_list();
|
||||
lhs->push_back(this->index_var_);
|
||||
lhs->push_back(this->value_var_);
|
||||
|
||||
Expression_list* rhs = new Expression_list();
|
||||
rhs->push_back(index_ref);
|
||||
rhs->push_back(Expression::make_temporary_reference(value_temp, loc));
|
||||
Expression_list* rhs = new Expression_list();
|
||||
rhs->push_back(index_ref);
|
||||
rhs->push_back(Expression::make_temporary_reference(value_temp, loc));
|
||||
|
||||
assign = Statement::make_tuple_assignment(lhs, rhs, loc);
|
||||
assign = Statement::make_tuple_assignment(lhs, rhs, loc);
|
||||
}
|
||||
body->add_statement(assign);
|
||||
}
|
||||
body->add_statement(assign);
|
||||
|
||||
body->add_statement(Statement::make_block_statement(this->statements_, loc));
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue