]> Cypherpunks repositories - gostls13.git/commitdiff
gc: implement new composite literal spec
authorRuss Cox <rsc@golang.org>
Fri, 22 Oct 2010 03:17:20 +0000 (23:17 -0400)
committerRuss Cox <rsc@golang.org>
Fri, 22 Oct 2010 03:17:20 +0000 (23:17 -0400)
R=ken2
CC=golang-dev
https://golang.org/cl/2350041

src/cmd/gc/go.y
src/cmd/gc/typecheck.c

index 8a98d240175b31082fc3cbae3b48cf486135fd09..7960a22640d4172af2676cee79a28513a93b7fe4 100644 (file)
@@ -52,7 +52,7 @@ static void fixlbrace(int);
 %type  <node>  stmt ntype
 %type  <node>  arg_type
 %type  <node>  case caseblock
-%type  <node>  compound_stmt dotname embed expr
+%type  <node>  compound_stmt dotname embed expr complitexpr
 %type  <node>  expr_or_type
 %type  <node>  fndcl fnliteral
 %type  <node>  for_body for_header for_stmt if_header if_stmt non_dcl_stmt
@@ -889,6 +889,20 @@ pexpr_no_paren:
        }
 |      fnliteral
 
+keyval:
+       expr ':' complitexpr
+       {
+               $$ = nod(OKEY, $1, $3);
+       }
+
+complitexpr:
+       expr
+|      '{' braced_keyval_list '}'
+       {
+               $$ = nod(OCOMPLIT, N, N);
+               $$->list = $2;
+       }
+
 pexpr:
        pexpr_no_paren
 |      '(' expr_or_type ')'
@@ -1094,13 +1108,6 @@ interfacetype:
                fixlbrace($2);
        }
 
-keyval:
-       expr ':' expr
-       {
-               $$ = nod(OKEY, $1, $3);
-       }
-
-
 /*
  * function stuff
  * all in one place to show how crappy it all is
@@ -1552,7 +1559,7 @@ keyval_list:
        {
                $$ = list1($1);
        }
-|      expr
+|      complitexpr
        {
                $$ = list1($1);
        }
@@ -1560,7 +1567,7 @@ keyval_list:
        {
                $$ = list($1, $3);
        }
-|      keyval_list ',' expr
+|      keyval_list ',' complitexpr
        {
                $$ = list($1, $3);
        }
index 89cd1d65917a04c7cbd2f870889b917390c9175e..43cf4a7c3671a2241786b9a38dda40d6777e81ec 100644 (file)
@@ -1776,7 +1776,7 @@ typecheckcomplit(Node **np)
        int bad, i, len, nerr;
        Node *l, *n, *hash[101];
        NodeList *ll;
-       Type *t, *f;
+       Type *t, *f, *pushtype;
        Sym *s;
        int32 lno;
 
@@ -1784,11 +1784,38 @@ typecheckcomplit(Node **np)
        lno = lineno;
 
        memset(hash, 0, sizeof hash);
+       if(n->right == N) {
+               if(n->list != nil)
+                       setlineno(n->list->n);
+               yyerror("missing type in composite literal");
+               goto error;
+       }
+
        setlineno(n->right);
        l = typecheck(&n->right /* sic */, Etype);
        if((t = l->type) == T)
                goto error;
        nerr = nerrors;
+
+       // can omit type on composite literal values if the outer
+       // composite literal is array, slice, or map, and the 
+       // element type is itself a struct, array, slice, or map.
+       pushtype = T;
+       if(t->etype == TARRAY || t->etype == TMAP) {
+               pushtype = t->type;
+               if(pushtype != T) {
+                       switch(pushtype->etype) {
+                       case TSTRUCT:
+                       case TARRAY:
+                       case TMAP:
+                               break;
+                       default:
+                               pushtype = T;
+                               break;
+                       }
+               }
+       }
+
        switch(t->etype) {
        default:
                yyerror("invalid type for composite literal: %T", t);
@@ -1801,27 +1828,22 @@ typecheckcomplit(Node **np)
                for(ll=n->list; ll; ll=ll->next) {
                        l = ll->n;
                        setlineno(l);
-                       if(l->op == OKEY) {
-                               typecheck(&l->left, Erv);
-                               evconst(l->left);
-                               i = nonnegconst(l->left);
-                               if(i < 0) {
-                                       yyerror("array index must be non-negative integer constant");
-                                       i = -(1<<30);   // stay negative for a while
-                               }
-                               typecheck(&l->right, Erv);
-                               defaultlit(&l->right, t->type);
-                               l->right = assignconv(l->right, t->type, "array index");
-                       } else {
-                               typecheck(&ll->n, Erv);
-                               defaultlit(&ll->n, t->type);
-                               ll->n = assignconv(ll->n, t->type, "array index");
-                               ll->n = nod(OKEY, nodintconst(i), ll->n);
-                               ll->n->left->type = types[TINT];
-                               ll->n->left->typecheck = 1;
+                       if(l->op != OKEY) {
+                               l = nod(OKEY, nodintconst(i), l);
+                               l->left->type = types[TINT];
+                               l->left->typecheck = 1;
+                               ll->n = l;
+                       }
+
+                       typecheck(&l->left, Erv);
+                       evconst(l->left);
+                       i = nonnegconst(l->left);
+                       if(i < 0) {
+                               yyerror("array index must be non-negative integer constant");
+                               i = -(1<<30);   // stay negative for a while
                        }
                        if(i >= 0)
-                               indexdup(ll->n->left, hash, nelem(hash));
+                               indexdup(l->left, hash, nelem(hash));
                        i++;
                        if(i > len) {
                                len = i;
@@ -1831,6 +1853,12 @@ typecheckcomplit(Node **np)
                                        t->bound = -1;  // no more errors
                                }
                        }
+
+                       if(l->right->op == OCOMPLIT && l->right->right == N && pushtype != T)
+                               l->right->right = typenod(pushtype);
+                       typecheck(&l->right, Erv);
+                       defaultlit(&l->right, t->type);
+                       l->right = assignconv(l->right, t->type, "array index");
                }
                if(t->bound == -100)
                        t->bound = len;
@@ -1848,13 +1876,17 @@ typecheckcomplit(Node **np)
                                yyerror("missing key in map literal");
                                continue;
                        }
+
                        typecheck(&l->left, Erv);
-                       typecheck(&l->right, Erv);
                        defaultlit(&l->left, t->down);
-                       defaultlit(&l->right, t->type);
                        l->left = assignconv(l->left, t->down, "map key");
-                       l->right = assignconv(l->right, t->type, "map value");
                        keydup(l->left, hash, nelem(hash));
+
+                       if(l->right->op == OCOMPLIT && l->right->right == N && pushtype != T)
+                               l->right->right = typenod(pushtype);
+                       typecheck(&l->right, Erv);
+                       defaultlit(&l->right, t->type);
+                       l->right = assignconv(l->right, t->type, "map value");
                }
                n->op = OMAPLIT;
                break;