]> Cypherpunks repositories - gostls13.git/commitdiff
add composite literal ( ) syntax.
authorRuss Cox <rsc@golang.org>
Fri, 13 Feb 2009 22:48:16 +0000 (14:48 -0800)
committerRuss Cox <rsc@golang.org>
Fri, 13 Feb 2009 22:48:16 +0000 (14:48 -0800)
warn about composite literal { } syntax.

R=ken
OCL=25018
CL=25023

src/cmd/gc/go.h
src/cmd/gc/go.y
src/cmd/gc/subr.c
src/cmd/gc/walk.c

index 7ec215b0e47fa3e09a4031ed4170b9f724022ffe..0f8d26506d47439bb2cd93e063d124411af83635 100644 (file)
@@ -326,7 +326,10 @@ enum
        OINDEX, OSLICE,
        ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV,
        OLITERAL, OREGISTER, OINDREG,
-       OCONV, OCOMP, OKEY, OPARAM,
+       OKEY, OPARAM,
+       OCONV,
+       OCONVDOT,
+       OCONVPAREN,
        OBAD,
 
        OEXTEND,        // 6g internal
@@ -805,6 +808,7 @@ void        gettype(Node*, Node*);
 void   walk(Node*);
 void   walkstate(Node*);
 void   walktype(Node*, int);
+void   walkconv(Node*);
 void   walkas(Node*);
 void   walkbool(Node*);
 Type*  walkswitch(Node*, Type*(*)(Node*, Type*));
@@ -840,8 +844,8 @@ Node*       reorder2(Node*);
 Node*  reorder3(Node*);
 Node*  reorder4(Node*);
 Node*  structlit(Node*, Node*);
-Node*  arraylit(Node*);
-Node*  maplit(Node*);
+Node*  arraylit(Node*, Node*);
+Node*  maplit(Node*, Node*);
 Node*  selectas(Node*, Node*);
 Node*  old2new(Node*, Type*);
 void   addrescapes(Node*);
index 29a08912d4a2fd72c04067a885e133fdcebe0edf..072db35b682ec2b39265181bbc8dbdaf7fec7c2a 100644 (file)
@@ -791,7 +791,7 @@ pexpr:
        }
 |      pexpr '.' '(' type ')'
        {
-               $$ = nod(OCONV, $1, N);
+               $$ = nod(OCONVDOT, $1, N);
                $$->type = $4;
        }
 |      pexpr '[' expr ']'
@@ -841,20 +841,24 @@ pexpr:
                $$ = nod(OMAKE, $5, N);
                $$->type = $3;
        }
-|      latype '(' expr ')'
+|      convtype '(' braced_keyexpr_list ')'
        {
-               $$ = nod(OCONV, $3, N);
-               $$->type = oldtype($1);
+               // typed literal
+               $$ = rev($3);
+               if($$ == N)
+                       $$ = nod(OEMPTY, N, N);
+               $$ = nod(OCONVPAREN, $$, N);
+               $$->type = $1;
        }
 |      convtype '{' braced_keyexpr_list '}'
        {
+               if(!debug['{'])
+                       warn("braces should now be parens");
                // composite literal
                $$ = rev($3);
                if($$ == N)
                        $$ = nod(OEMPTY, N, N);
-               if(!iscomposite($1))
-                       yyerror("illegal composite literal type %T", $1);
-               $$ = nod(OCOMP, $$, N);
+               $$ = nod(OCONVPAREN, $$, N);
                $$->type = $1;
        }
 |      fnliteral
index 841f5c36141afd83d0958edd9001b26b1e2bdc33..2ddf6e8cadc3a03671acaeed82a22d1cc01efa3f 100644 (file)
@@ -634,9 +634,10 @@ opnames[] =
        [OXCASE]        = "XCASE",
        [OCMP]          = "CMP",
        [OFALL]         = "FALL",
-       [OCONV]         = "CONV",
+       [OCONV] = "CONV",
+       [OCONVDOT]              = "CONVDOT",
+       [OCONVPAREN]    = "CONVPAREN",
        [OCOM]          = "COM",
-       [OCOMP]         = "COMP",
        [OCONST]        = "CONST",
        [OCONTINUE]     = "CONTINUE",
        [ODCLARG]       = "DCLARG",
index 440c897795d27e2a17519a2d352bf6b32a393531..1d206334876819788bd71d0737da9afa1c925a71 100644 (file)
@@ -507,7 +507,7 @@ loop:
                        }
                        break;
 
-               case OCONV:
+               case OCONVDOT:
                        if(cl == 2 && cr == 1) {
                                // a,b = i.(T)
                                walktype(r->left, Erv);
@@ -590,128 +590,11 @@ loop:
                goto ret;
 
        case OCONV:
-               if(top == Etop)
-                       goto nottop;
-
-               l = n->left;
-               if(l == N)
-                       goto ret;
-
-               walktype(l, Erv);
-
-               t = n->type;
-               if(t == T)
-                       goto ret;
-
-               convlit1(l, t, 1);
-
-               // nil conversion
-               if(eqtype(t, l->type, 0)) {
-                       if(l->op != ONAME) {
-                               indir(n, l);
-                               n->type = t;
-                       }
-                       goto ret;
-               }
-
-               // simple fix-float
-               if(l->type != T)
-               if(isint[l->type->etype] || isfloat[l->type->etype])
-               if(isint[t->etype] || isfloat[t->etype]) {
-                       evconst(n);
-                       goto ret;
-               }
-
-               // to string
-               if(l->type != T)
-               if(istype(t, TSTRING)) {
-                       et = l->type->etype;
-                       if(isint[et]) {
-                               indir(n, stringop(n, top));
-                               goto ret;
-                       }
-                       if(et == TARRAY)
-                       if(istype(l->type->type, TUINT8)) {
-                               n->op = OARRAY;
-                               indir(n, stringop(n, top));
-                               goto ret;
-                       }
-               }
-
-               // convert dynamic to static generated by ONEW/OMAKE
-               if(isfixedarray(t) && isslice(l->type))
-                       goto ret;
-
-               // convert static array to dynamic array
-               if(isslice(t) && isfixedarray(l->type)) {
-                       if(eqtype(t->type->type, l->type->type->type, 0)) {
-                               indir(n, arrayop(n, Erv));
-                               goto ret;
-                       }
-               }
-
-               // interface assignment
-               et = ifaceas(n->type, l->type, 1);
-               if(et != Inone) {
-                       indir(n, ifaceop(n->type, l, et));
-                       goto ret;
-               }
-
-               // convert to unsafe.pointer
-               if(isptrto(n->type, TANY)) {
-                       if(isptr[l->type->etype])
-                               goto ret;
-                       if(l->type->etype == TUINTPTR)
-                               goto ret;
-               }
-
-               // convert from unsafe.pointer
-               if(isptrto(l->type, TANY)) {
-                       if(isptr[n->type->etype])
-                               goto ret;
-                       if(n->type->etype == TUINTPTR)
-                               goto ret;
-               }
-
-               if(l->type != T)
-                       yyerror("cannot convert %T to %T", l->type, t);
-               goto ret;
-
-       case OCOMP:
-               if(top == Etop)
+       case OCONVDOT:
+       case OCONVPAREN:
+               if(top != Erv)
                        goto nottop;
-
-               l = n->left;
-               if(l == N)
-                       goto ret;
-
-               walktype(l, Erv);
-
-               t = n->type;
-               if(t == T)
-                       goto ret;
-
-               // structure literal
-               if(t->etype == TSTRUCT) {
-                       indir(n, structlit(n, nil));
-                       goto ret;
-               }
-
-               // array literal
-               if(t->etype == TARRAY) {
-                       r = arraylit(n);
-                       indir(n, r);
-                       goto ret;
-               }
-
-               // map literal
-               if(t->etype == TMAP) {
-                       r = maplit(n);
-                       indir(n, r);
-                       goto ret;
-               }
-
-               yyerror("bad composite literal %T", t);
+               walkconv(n);
                goto ret;
 
        case ORETURN:
@@ -1001,14 +884,18 @@ loop:
        case OADDR:
                if(top != Erv)
                        goto nottop;
-               if(n->left->op == OCOMP && n->left->type != T)
-               if(n->left->type->etype == TSTRUCT) {
-                       // turn &Point{1, 2} into allocation.
+               if(n->left->op == OCONVPAREN && n->left->type != T)
+               switch(n->left->type->etype) {
+               case TSTRUCT:
+               case TARRAY:
+               case TMAP:
+                       // turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation.
                        // initialize with
                        //      nvar := new(*Point);
-                       //      *nvar = Point{1, 2};
+                       //      *nvar = Point(1, 2);
                        // and replace expression with nvar
-                       Node *nvar, *nas;
+                       ; // stupid c syntax - case label must be on stmt, not decl
+                       Node *nvar, *nas, *nstar;
 
                        nvar = nod(OXXX, N, N);
                        tempname(nvar, ptrto(n->left->type));
@@ -1016,10 +903,27 @@ loop:
                        nas = nod(OAS, nvar, callnew(n->left->type));
                        addtop = list(addtop, nas);
 
-                       structlit(n->left, nvar);
+                       nstar = nod(OIND, nvar, N);
+                       nstar->type = n->left->type;
+
+                       switch(n->left->type->etype) {
+                       case TSTRUCT:
+                               structlit(n->left, nstar);
+                               break;
+                       case TARRAY:
+                               arraylit(n->left, nstar);
+                               break;
+                       case TMAP:
+                               maplit(n->left, nstar);
+                               break;
+                       default:
+                               fatal("addr lit %T", n->left->type);
+                       }
+
                        indir(n, nvar);
                        goto ret;
                }
+
                if(istype(n->left->type, TFUNC) && n->left->class == PFUNC) {
                        if(!n->diag) {
                                n->diag = 1;
@@ -1223,6 +1127,133 @@ walkbool(Node *n)
                        yyerror("IF and FOR require a boolean type");
 }
 
+void
+walkconv(Node *n)
+{
+       int et, op;
+       Type *t;
+       Node *l;
+
+       t = n->type;
+       if(t == T)
+               return;
+       l = n->left;
+       if(l == N)
+               return;
+       walktype(l, Erv);
+
+       switch(t->etype) {
+       case TSTRUCT:
+       case TMAP:
+       case TARRAY:
+               break;
+       default:
+               convlit1(l, t, 1);
+       }
+
+       op = n->op;
+       n->op = OCONV;  // generic conversion
+
+       // nil conversion
+       if(eqtype(t, l->type, 0)) {
+               if(l->op != ONAME) {
+                       indir(n, l);
+                       n->type = t;
+               }
+               return;
+       }
+
+       // simple fix-float
+       if(l->type != T)
+       if(isint[l->type->etype] || isfloat[l->type->etype])
+       if(isint[t->etype] || isfloat[t->etype]) {
+               evconst(n);
+               return;
+       }
+
+       // to string
+       if(l->type != T)
+       if(istype(t, TSTRING)) {
+               et = l->type->etype;
+               if(isint[et]) {
+                       indir(n, stringop(n, Erv));
+                       return;
+               }
+               if(et == TARRAY)
+               if(istype(l->type->type, TUINT8)) {
+                       n->op = OARRAY;
+                       indir(n, stringop(n, Erv));
+                       return;
+               }
+       }
+
+       // convert dynamic to static generated by ONEW/OMAKE
+       if(isfixedarray(t) && isslice(l->type))
+               return;
+
+       // convert static array to dynamic array
+       if(isslice(t) && isfixedarray(l->type)) {
+               if(eqtype(t->type->type, l->type->type->type, 0)) {
+                       indir(n, arrayop(n, Erv));
+                       return;
+               }
+       }
+
+       // convert to unsafe.pointer
+       if(isptrto(n->type, TANY)) {
+               if(isptr[l->type->etype])
+                       return;
+               if(l->type->etype == TUINTPTR)
+                       return;
+       }
+
+       // convert from unsafe.pointer
+       if(isptrto(l->type, TANY)) {
+               if(isptr[n->type->etype])
+                       return;
+               if(n->type->etype == TUINTPTR)
+                       return;
+       }
+
+       // possible interface conversion if using .(T)
+       if(op == OCONVDOT) {
+               // interface conversion
+               et = ifaceas(n->type, l->type, 1);
+               if(et != Inone) {
+                       indir(n, ifaceop(n->type, l, et));
+                       return;
+               }
+       }
+
+       // possible composite literal if using T()
+       if(op == OCONVPAREN) {
+               // structure literal
+               if(t->etype == TSTRUCT) {
+                       indir(n, structlit(n, N));
+                       return;
+               }
+
+               // array literal
+               if(t->etype == TARRAY) {
+                       indir(n, arraylit(n, N));
+                       return;
+               }
+
+               // map literal
+               if(t->etype == TMAP) {
+                       indir(n, maplit(n, N));
+                       return;
+               }
+       }
+
+       if(l->type != T)
+               yyerror("invalid conversion: %T to %T", l->type, t);
+       else if(n->left->op == OLIST)
+               yyerror("invalid type for composite literal: %T", t);
+}
+
+
+
 /*
  * return the first type
  */
@@ -3110,7 +3141,7 @@ multi:
                n = list(n, a);
                break;
 
-       case OCONV:
+       case OCONVDOT:
                // a,b := i.(T)
                if(cl != 2)
                        goto badt;
@@ -3538,11 +3569,11 @@ loop:
 }
 
 Node*
-arraylit(Node *n)
+arraylit(Node *n, Node *var)
 {
        Iter saver;
        Type *t;
-       Node *var, *r, *a, *nnew;
+       Node *r, *a, *nnew;
        int idx, ninit, b;
 
        t = n->type;
@@ -3567,8 +3598,10 @@ arraylit(Node *n)
                t->bound = b;
        }
 
-       var = nod(OXXX, N, N);
-       tempname(var, t);
+       if(var == N) {
+               var = nod(OXXX, N, N);
+               tempname(var, t);
+       }
 
        nnew = nil;
        if(b < 0) {
@@ -3606,18 +3639,20 @@ arraylit(Node *n)
 }
 
 Node*
-maplit(Node *n)
+maplit(Node *n, Node *var)
 {
        Iter saver;
        Type *t;
-       Node *var, *r, *a;
+       Node *r, *a;
 
        t = n->type;
        if(t->etype != TMAP)
                fatal("maplit: not map");
 
-       var = nod(OXXX, N, N);
-       tempname(var, t);
+       if(var == N) {
+               var = nod(OXXX, N, N);
+               tempname(var, t);
+       }
 
        a = nod(OMAKE, N, N);
        a->type = t;