Commit 26b8f7eb by Ian Lance Taylor

compiler: Implement 3-index slicing.

From-SVN: r204034
parent ccc23115
...@@ -232,19 +232,21 @@ class Expression ...@@ -232,19 +232,21 @@ class Expression
Named_object* function, Location); Named_object* function, Location);
// Make an index or slice expression. This is a parser expression // Make an index or slice expression. This is a parser expression
// which represents LEFT[START:END]. END may be NULL, meaning an // which represents LEFT[START:END:CAP]. END may be NULL, meaning an
// index rather than a slice. At parse time we may not know the // index rather than a slice. CAP may be NULL, meaning we use the default
// type of LEFT. After parsing this is lowered to an array index, a // capacity of LEFT. At parse time we may not know the type of LEFT.
// string index, or a map index. // After parsing this is lowered to an array index, a string index,
// or a map index.
static Expression* static Expression*
make_index(Expression* left, Expression* start, Expression* end, make_index(Expression* left, Expression* start, Expression* end,
Location); Expression* cap, Location);
// Make an array index expression. END may be NULL, in which case // Make an array index expression. END may be NULL, in which case
// this is an lvalue. // this is an lvalue. CAP may be NULL, in which case it defaults
// to cap(ARRAY).
static Expression* static Expression*
make_array_index(Expression* array, Expression* start, Expression* end, make_array_index(Expression* array, Expression* start, Expression* end,
Location); Expression* cap, Location);
// Make a string index expression. END may be NULL. This is never // Make a string index expression. END may be NULL. This is never
// an lvalue. // an lvalue.
...@@ -1672,9 +1674,9 @@ class Index_expression : public Parser_expression ...@@ -1672,9 +1674,9 @@ class Index_expression : public Parser_expression
{ {
public: public:
Index_expression(Expression* left, Expression* start, Expression* end, Index_expression(Expression* left, Expression* start, Expression* end,
Location location) Expression* cap, Location location)
: Parser_expression(EXPRESSION_INDEX, location), : Parser_expression(EXPRESSION_INDEX, location),
left_(left), start_(start), end_(end), is_lvalue_(false) left_(left), start_(start), end_(end), cap_(cap), is_lvalue_(false)
{ } { }
// Record that this expression is an lvalue. // Record that this expression is an lvalue.
...@@ -1683,10 +1685,11 @@ class Index_expression : public Parser_expression ...@@ -1683,10 +1685,11 @@ class Index_expression : public Parser_expression
{ this->is_lvalue_ = true; } { this->is_lvalue_ = true; }
// Dump an index expression, i.e. an expression of the form // Dump an index expression, i.e. an expression of the form
// expr[expr] or expr[expr:expr], to a dump context. // expr[expr], expr[expr:expr], or expr[expr:expr:expr] to a dump context.
static void static void
dump_index_expression(Ast_dump_context*, const Expression* expr, dump_index_expression(Ast_dump_context*, const Expression* expr,
const Expression* start, const Expression* end); const Expression* start, const Expression* end,
const Expression* cap);
protected: protected:
int int
...@@ -1702,6 +1705,9 @@ class Index_expression : public Parser_expression ...@@ -1702,6 +1705,9 @@ class Index_expression : public Parser_expression
(this->end_ == NULL (this->end_ == NULL
? NULL ? NULL
: this->end_->copy()), : this->end_->copy()),
(this->cap_ == NULL
? NULL
: this->cap_->copy()),
this->location()); this->location());
} }
...@@ -1723,6 +1729,10 @@ class Index_expression : public Parser_expression ...@@ -1723,6 +1729,10 @@ class Index_expression : public Parser_expression
// The second index. This is NULL for an index, non-NULL for a // The second index. This is NULL for an index, non-NULL for a
// slice. // slice.
Expression* end_; Expression* end_;
// The capacity argument. This is NULL for indices and slices that use the
// default capacity, non-NULL for indices and slices that specify the
// capacity.
Expression* cap_;
// Whether this is being used as an l-value. We set this during the // Whether this is being used as an l-value. We set this during the
// parse because map index expressions need to know. // parse because map index expressions need to know.
bool is_lvalue_; bool is_lvalue_;
......
...@@ -3152,7 +3152,7 @@ Parse::selector(Expression* left, bool* is_type_switch) ...@@ -3152,7 +3152,7 @@ Parse::selector(Expression* left, bool* is_type_switch)
} }
// Index = "[" Expression "]" . // Index = "[" Expression "]" .
// Slice = "[" Expression ":" [ Expression ] "]" . // Slice = "[" Expression ":" [ Expression ] [ ":" Expression ] "]" .
Expression* Expression*
Parse::index(Expression* expr) Parse::index(Expression* expr)
...@@ -3178,14 +3178,31 @@ Parse::index(Expression* expr) ...@@ -3178,14 +3178,31 @@ Parse::index(Expression* expr)
// We use nil to indicate a missing high expression. // We use nil to indicate a missing high expression.
if (this->advance_token()->is_op(OPERATOR_RSQUARE)) if (this->advance_token()->is_op(OPERATOR_RSQUARE))
end = Expression::make_nil(this->location()); end = Expression::make_nil(this->location());
else if (this->peek_token()->is_op(OPERATOR_COLON))
{
error_at(this->location(), "middle index required in 3-index slice");
end = Expression::make_error(this->location());
}
else else
end = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL); end = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
} }
Expression* cap = NULL;
if (this->peek_token()->is_op(OPERATOR_COLON))
{
if (this->advance_token()->is_op(OPERATOR_RSQUARE))
{
error_at(this->location(), "final index required in 3-index slice");
cap = Expression::make_error(this->location());
}
else
cap = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
}
if (!this->peek_token()->is_op(OPERATOR_RSQUARE)) if (!this->peek_token()->is_op(OPERATOR_RSQUARE))
error_at(this->location(), "missing %<]%>"); error_at(this->location(), "missing %<]%>");
else else
this->advance_token(); this->advance_token();
return Expression::make_index(expr, start, end, location); return Expression::make_index(expr, start, end, cap, location);
} }
// Call = "(" [ ArgumentList [ "," ] ] ")" . // Call = "(" [ ArgumentList [ "," ] ] ")" .
......
...@@ -5540,7 +5540,7 @@ For_range_statement::lower_range_array(Gogo* gogo, ...@@ -5540,7 +5540,7 @@ For_range_statement::lower_range_array(Gogo* gogo,
ref = this->make_range_ref(range_object, range_temp, loc); ref = this->make_range_ref(range_object, range_temp, loc);
Expression* ref2 = Expression::make_temporary_reference(index_temp, loc); Expression* ref2 = Expression::make_temporary_reference(index_temp, loc);
Expression* index = Expression::make_index(ref, ref2, NULL, loc); Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
tref = Expression::make_temporary_reference(value_temp, loc); tref = Expression::make_temporary_reference(value_temp, loc);
tref->set_is_lvalue(); tref->set_is_lvalue();
...@@ -5641,7 +5641,7 @@ For_range_statement::lower_range_slice(Gogo* gogo, ...@@ -5641,7 +5641,7 @@ For_range_statement::lower_range_slice(Gogo* gogo,
ref = Expression::make_temporary_reference(for_temp, loc); ref = Expression::make_temporary_reference(for_temp, loc);
Expression* ref2 = Expression::make_temporary_reference(index_temp, loc); Expression* ref2 = Expression::make_temporary_reference(index_temp, loc);
Expression* index = Expression::make_index(ref, ref2, NULL, loc); Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
tref = Expression::make_temporary_reference(value_temp, loc); tref = Expression::make_temporary_reference(value_temp, loc);
tref->set_is_lvalue(); tref->set_is_lvalue();
...@@ -5849,7 +5849,7 @@ For_range_statement::lower_range_map(Gogo*, ...@@ -5849,7 +5849,7 @@ For_range_statement::lower_range_map(Gogo*,
Expression* zexpr = Expression::make_integer(&zval, NULL, loc); Expression* zexpr = Expression::make_integer(&zval, NULL, loc);
mpz_clear(zval); mpz_clear(zval);
Expression* index = Expression::make_index(ref, zexpr, NULL, loc); Expression* index = Expression::make_index(ref, zexpr, NULL, NULL, loc);
Expression* ne = Expression::make_binary(OPERATOR_NOTEQ, index, Expression* ne = Expression::make_binary(OPERATOR_NOTEQ, index,
Expression::make_nil(loc), Expression::make_nil(loc),
......
...@@ -5645,12 +5645,12 @@ Array_type::write_equal_function(Gogo* gogo, Named_type* name) ...@@ -5645,12 +5645,12 @@ Array_type::write_equal_function(Gogo* gogo, Named_type* name)
Expression* e1 = Expression::make_temporary_reference(p1, bloc); Expression* e1 = Expression::make_temporary_reference(p1, bloc);
e1 = Expression::make_unary(OPERATOR_MULT, e1, bloc); e1 = Expression::make_unary(OPERATOR_MULT, e1, bloc);
ref = Expression::make_temporary_reference(index, bloc); ref = Expression::make_temporary_reference(index, bloc);
e1 = Expression::make_array_index(e1, ref, NULL, bloc); e1 = Expression::make_array_index(e1, ref, NULL, NULL, bloc);
Expression* e2 = Expression::make_temporary_reference(p2, bloc); Expression* e2 = Expression::make_temporary_reference(p2, bloc);
e2 = Expression::make_unary(OPERATOR_MULT, e2, bloc); e2 = Expression::make_unary(OPERATOR_MULT, e2, bloc);
ref = Expression::make_temporary_reference(index, bloc); ref = Expression::make_temporary_reference(index, bloc);
e2 = Expression::make_array_index(e2, ref, NULL, bloc); e2 = Expression::make_array_index(e2, ref, NULL, NULL, bloc);
Expression* cond = Expression::make_binary(OPERATOR_NOTEQ, e1, e2, bloc); Expression* cond = Expression::make_binary(OPERATOR_NOTEQ, e1, e2, bloc);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment