From patchwork Fri Oct 22 21:33:09 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 68972 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id B5A8CB70A7 for ; Sat, 23 Oct 2010 08:33:33 +1100 (EST) Received: (qmail 25682 invoked by alias); 22 Oct 2010 21:33:30 -0000 Received: (qmail 25661 invoked by uid 22791); 22 Oct 2010 21:33:25 -0000 X-SWARE-Spam-Status: No, hits=-2.2 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, SPF_HELO_PASS, TW_CC, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.44.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 22 Oct 2010 21:33:17 +0000 Received: from hpaq3.eem.corp.google.com (hpaq3.eem.corp.google.com [172.25.149.3]) by smtp-out.google.com with ESMTP id o9MLXE1O008267 for ; Fri, 22 Oct 2010 14:33:14 -0700 Received: from pzk27 (pzk27.prod.google.com [10.243.19.155]) by hpaq3.eem.corp.google.com with ESMTP id o9MLXCXX012685 for ; Fri, 22 Oct 2010 14:33:13 -0700 Received: by pzk27 with SMTP id 27so357232pzk.20 for ; Fri, 22 Oct 2010 14:33:12 -0700 (PDT) Received: by 10.142.158.18 with SMTP id g18mr2641657wfe.355.1287783192046; Fri, 22 Oct 2010 14:33:12 -0700 (PDT) Received: from coign.google.com (dhcp-172-22-123-203.mtv.corp.google.com [172.22.123.203]) by mx.google.com with ESMTPS id q13sm5159946wfc.17.2010.10.22.14.33.10 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 22 Oct 2010 14:33:11 -0700 (PDT) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com Subject: [gccgo] Permit omitting types in a composite literal Date: Fri, 22 Oct 2010 14:33:09 -0700 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 X-System-Of-Record: true X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org The Go language was changed to permit omitting some redundant types in nested composite literals. Now instead of [][]int{[]int{1}, []int{2}} you can write [][]int{{1}, {2}} This patch implements that in gccgo. Committed to gccgo branch. Ian diff -r e852fb180b3f go/expressions.cc --- a/go/expressions.cc Fri Oct 22 12:33:37 2010 -0700 +++ b/go/expressions.cc Fri Oct 22 14:27:38 2010 -0700 @@ -2937,8 +2937,8 @@ } } - return Expression::make_composite_literal(type, false, vals, - location); + return Expression::make_slice_composite_literal(type, vals, + location); } } } @@ -7823,14 +7823,19 @@ vals->push_back(*pa); } - Type* ctype; + Expression* val; if (element_type == NULL) - ctype = Type::make_struct_type(fields, loc); + { + Type* ctype = Type::make_struct_type(fields, loc); + val = Expression::make_struct_composite_literal(ctype, vals, loc); + } else - ctype = Type::make_array_type(element_type, NULL); - - new_args->push_back(Expression::make_composite_literal(ctype, false, - vals, loc)); + { + Type* ctype = Type::make_array_type(element_type, NULL); + val = Expression::make_slice_composite_literal(ctype, vals, loc); + } + + new_args->push_back(val); } } @@ -7842,9 +7847,9 @@ { Struct_field_list* fields = new Struct_field_list(); Type* param_type = Type::make_struct_type(fields, loc); - new_args->push_back(Expression::make_composite_literal(param_type, - false, NULL, - loc)); + Expression* v = Expression::make_struct_composite_literal(param_type, + NULL, loc); + new_args->push_back(v); } } @@ -10962,10 +10967,10 @@ class Composite_literal_expression : public Parser_expression { public: - Composite_literal_expression(Type* type, bool has_keys, + Composite_literal_expression(Type* type, int depth, bool has_keys, Expression_list* vals, source_location location) : Parser_expression(EXPRESSION_COMPOSITE_LITERAL, location), - type_(type), vals_(vals), has_keys_(has_keys) + type_(type), depth_(depth), vals_(vals), has_keys_(has_keys) { } protected: @@ -10978,7 +10983,8 @@ Expression* do_copy() { - return new Composite_literal_expression(this->type_, this->has_keys_, + return new Composite_literal_expression(this->type_, this->depth_, + this->has_keys_, (this->vals_ == NULL ? NULL : this->vals_->copy()), @@ -10987,19 +10993,22 @@ private: Expression* - lower_struct(); + lower_struct(Type*); Expression* - lower_array(); + lower_array(Type*); Expression* - make_array(Expression_list*); + make_array(Type*, Expression_list*); Expression* - lower_map(); + lower_map(Type*); // The type of the composite literal. Type* type_; + // The depth within a list of composite literals within a composite + // literal, when the type is omitted. + int depth_; // The values to put in the composite literal. Expression_list* vals_; // If this is true, then VALS_ is a list of pairs: a key and a @@ -11025,18 +11034,36 @@ Composite_literal_expression::do_lower(Gogo*, Named_object*, int) { Type* type = this->type_; + + for (int depth = this->depth_; depth > 0; --depth) + { + if (type->array_type() != NULL) + type = type->array_type()->element_type(); + else if (type->map_type() != NULL) + type = type->map_type()->val_type(); + else + { + if (!type->is_error_type()) + error_at(this->location(), + ("may only omit types within composite literals " + "of slice, array, or map type")); + return Expression::make_error(this->location()); + } + } + if (type->is_error_type()) return Expression::make_error(this->location()); else if (type->struct_type() != NULL) - return this->lower_struct(); + return this->lower_struct(type); else if (type->array_type() != NULL) - return this->lower_array(); + return this->lower_array(type); else if (type->map_type() != NULL) - return this->lower_map(); + return this->lower_map(type); else { error_at(this->location(), - "expected struct, array, or map type for composite literal"); + ("expected struct, slice, array, or map type " + "for composite literal")); return Expression::make_error(this->location()); } } @@ -11044,13 +11071,12 @@ // Lower a struct composite literal. Expression* -Composite_literal_expression::lower_struct() +Composite_literal_expression::lower_struct(Type* type) { source_location location = this->location(); - Struct_type* st = this->type_->struct_type(); + Struct_type* st = type->struct_type(); if (this->vals_ == NULL || !this->has_keys_) - return new Struct_construction_expression(this->type_, this->vals_, - location); + return new Struct_construction_expression(type, this->vals_, location); size_t field_count = st->field_count(); std::vector vals(field_count); @@ -11153,8 +11179,8 @@ { error_at(name_expr->location(), "unknown field %qs in %qs", Gogo::unpack_hidden_name(name).c_str(), - (this->type_->named_type() != NULL - ? this->type_->named_type()->message_name().c_str() + (type->named_type() != NULL + ? type->named_type()->message_name().c_str() : "unnamed struct")); return Expression::make_error(location); } @@ -11163,8 +11189,8 @@ error_at(name_expr->location(), "duplicate value for field %qs in %qs", Gogo::unpack_hidden_name(name).c_str(), - (this->type_->named_type() != NULL - ? this->type_->named_type()->message_name().c_str() + (type->named_type() != NULL + ? type->named_type()->message_name().c_str() : "unnamed struct")); return Expression::make_error(location); } @@ -11177,17 +11203,17 @@ for (size_t i = 0; i < field_count; ++i) list->push_back(vals[i]); - return new Struct_construction_expression(this->type_, list, location); + return new Struct_construction_expression(type, list, location); } // Lower an array composite literal. Expression* -Composite_literal_expression::lower_array() +Composite_literal_expression::lower_array(Type* type) { source_location location = this->location(); if (this->vals_ == NULL || !this->has_keys_) - return this->make_array(this->vals_); + return this->make_array(type, this->vals_); std::vector vals; vals.reserve(this->vals_->size()); @@ -11261,17 +11287,17 @@ for (size_t i = 0; i < size; ++i) list->push_back(vals[i]); - return this->make_array(list); + return this->make_array(type, list); } // Actually build the array composite literal. This handles // [...]{...}. Expression* -Composite_literal_expression::make_array(Expression_list* vals) +Composite_literal_expression::make_array(Type* type, Expression_list* vals) { source_location location = this->location(); - Array_type* at = this->type_->array_type(); + Array_type* at = type->array_type(); if (at->length() != NULL && at->length()->is_nil_expression()) { size_t size = vals == NULL ? 0 : vals->size(); @@ -11280,18 +11306,18 @@ Expression* elen = Expression::make_integer(&vlen, NULL, location); mpz_clear(vlen); at = Type::make_array_type(at->element_type(), elen); - this->type_ = at; + type = at; } if (at->length() != NULL) - return new Fixed_array_construction_expression(this->type_, vals, location); + return new Fixed_array_construction_expression(type, vals, location); else - return new Open_array_construction_expression(this->type_, vals, location); + return new Open_array_construction_expression(type, vals, location); } // Lower a map composite literal. Expression* -Composite_literal_expression::lower_map() +Composite_literal_expression::lower_map(Type* type) { source_location location = this->location(); if (this->vals_ != NULL) @@ -11316,17 +11342,18 @@ } } - return new Map_construction_expression(this->type_, this->vals_, location); + return new Map_construction_expression(type, this->vals_, location); } // Make a composite literal expression. Expression* -Expression::make_composite_literal(Type* type, bool has_keys, +Expression::make_composite_literal(Type* type, int depth, bool has_keys, Expression_list* vals, source_location location) { - return new Composite_literal_expression(type, has_keys, vals, location); + return new Composite_literal_expression(type, depth, has_keys, vals, + location); } // Return whether this expression is a composite literal. diff -r e852fb180b3f go/expressions.h --- a/go/expressions.h Fri Oct 22 12:33:37 2010 -0700 +++ b/go/expressions.h Fri Oct 22 14:27:38 2010 -0700 @@ -248,9 +248,10 @@ static Expression* make_cast(Type*, Expression*, source_location); - // Make a composite literal. + // Make a composite literal. The DEPTH parameter is how far down we + // are in a list of composite literals with omitted types. static Expression* - make_composite_literal(Type*, bool has_keys, Expression_list*, + make_composite_literal(Type*, int depth, bool has_keys, Expression_list*, source_location); // Make a struct composite literal. diff -r e852fb180b3f go/parse.cc --- a/go/parse.cc Fri Oct 22 12:33:37 2010 -0700 +++ b/go/parse.cc Fri Oct 22 14:27:38 2010 -0700 @@ -2314,19 +2314,25 @@ return e; } -// CompositeLit = LiteralType "{" [ ElementList ] "}" . +// CompositeLit = LiteralType LiteralValue . // LiteralType = StructType | ArrayType | "[" "..." "]" ElementType | // SliceType | MapType | TypeName . -// ElementList = Element { "," Element } [ "," ] . +// LiteralValue = "{" [ ElementList [ "," ] ] "}" . +// ElementList = Element { "," Element } . // Element = [ Key ":" ] Value . // Key = Expression . -// Value = Expression . - -// We have already seen the type. The case "[" "..." "]" ElementType -// will be seen here as an array type whose length is "nil". +// Value = Expression | LiteralValue . + +// We have already seen the type if there is one, and we are now +// looking at the LiteralValue. The case "[" "..." "]" ElementType +// will be seen here as an array type whose length is "nil". The +// DEPTH parameter is non-zero if this is an embedded composite +// literal and the type was omitted. It gives the number of steps up +// to the type which was provided. E.g., in [][]int{{1}} it will be +// 1. In [][][]int{{{1}}} it will be 2. Expression* -Parse::composite_lit(Type* type, source_location location) +Parse::composite_lit(Type* type, int depth, source_location location) { gcc_assert(this->peek_token()->is_op(OPERATOR_LCURLY)); this->advance_token(); @@ -2334,16 +2340,30 @@ if (this->peek_token()->is_op(OPERATOR_RCURLY)) { this->advance_token(); - return Expression::make_composite_literal(type, false, NULL, location); + return Expression::make_composite_literal(type, depth, false, NULL, + location); } bool has_keys = false; Expression_list* vals = new Expression_list; while (true) { - Expression* val = this->expression(PRECEDENCE_NORMAL, false, true, NULL); + Expression* val; + bool is_type_omitted = false; const Token* token = this->peek_token(); + + if (!token->is_op(OPERATOR_LCURLY)) + val = this->expression(PRECEDENCE_NORMAL, false, true, NULL); + else + { + // This must be a composite literal inside another composite + // literal, with the type omitted for the inner one. + val = this->composite_lit(type, depth + 1, token->location()); + is_type_omitted = true; + } + + token = this->peek_token(); if (!token->is_op(OPERATOR_COLON)) { if (has_keys) @@ -2351,6 +2371,12 @@ } else { + if (is_type_omitted && !val->is_error_expression()) + { + this->error("unexpected %<:%>"); + val = Expression::make_error(this->location()); + } + this->advance_token(); if (!has_keys && !vals->empty()) @@ -2414,7 +2440,8 @@ } } - return Expression::make_composite_literal(type, has_keys, vals, location); + return Expression::make_composite_literal(type, depth, has_keys, vals, + location); } // FunctionLit = "func" Signature Block . @@ -2540,7 +2567,7 @@ if (is_parenthesized) error_at(start_loc, "cannot parenthesize type in composite literal"); - ret = this->composite_lit(ret->type(), ret->location()); + ret = this->composite_lit(ret->type(), 0, ret->location()); } else if (this->peek_token()->is_op(OPERATOR_LPAREN)) { diff -r e852fb180b3f go/parse.h --- a/go/parse.h Fri Oct 22 12:33:37 2010 -0700 +++ b/go/parse.h Fri Oct 22 14:27:38 2010 -0700 @@ -206,7 +206,7 @@ Expression* operand(bool may_be_sink); Expression* enclosing_var_reference(Named_object*, Named_object*, source_location); - Expression* composite_lit(Type*, source_location); + Expression* composite_lit(Type*, int depth, source_location); Expression* function_lit(); Expression* create_closure(Named_object* function, Enclosing_vars*, source_location);