]> Cypherpunks repositories - gostls13.git/commitdiff
back to T{x}, stricter handling of T(x) vs x.(T)
authorRuss Cox <rsc@golang.org>
Tue, 3 Mar 2009 16:41:02 +0000 (08:41 -0800)
committerRuss Cox <rsc@golang.org>
Tue, 3 Mar 2009 16:41:02 +0000 (08:41 -0800)
R=ken
DELTA=131  (60 added, 41 deleted, 30 changed)
OCL=25617
CL=25633

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

index 0f8d26506d47439bb2cd93e063d124411af83635..8445a9158e2839dc6df0192c0b20a2a56e98fe3d 100644 (file)
@@ -327,9 +327,9 @@ enum
        ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV,
        OLITERAL, OREGISTER, OINDREG,
        OKEY, OPARAM,
+       OCOMPOS,
        OCONV,
-       OCONVDOT,
-       OCONVPAREN,
+       ODOTTYPE,
        OBAD,
 
        OEXTEND,        // 6g internal
index 320c9c6849f84af1140f9a79c0c2990ccbd53dbe..20c981d6c3b0054cdd34102632368e71ba1cbca5 100644 (file)
@@ -51,7 +51,7 @@
 %type  <node>          stmt_list_r Astmt_list_r Bstmt_list_r
 %type  <node>          Astmt Bstmt
 %type  <node>          for_stmt for_body for_header
-%type  <node>          if_stmt if_body if_header select_stmt
+%type  <node>          if_stmt if_body if_header select_stmt condition
 %type  <node>          simple_stmt osimple_stmt range_stmt semi_stmt
 %type  <node>          expr uexpr pexpr expr_list oexpr oexpr_list expr_list_r
 %type  <node>          exprsym3_list_r exprsym3
 %left                  '+' '-' '|' '^'
 %left                  '*' '/' '%' '&' LLSH LRSH
 
+/*
+ * resolve { vs condition in favor of condition
+ */
+%left                  '{'
+%left                  Condition
+
+
 %%
 file:
        package import_there imports oxdcl_list
@@ -562,7 +569,7 @@ for_header:
                $$->ntest = $3;
                $$->nincr = $5;
        }
-|      osimple_stmt
+|      condition
        {
                // normal test
                $$ = nod(OFOR, N, N);
@@ -591,15 +598,30 @@ for_stmt:
                $$ = $2;
        }
 
+/*
+ * using cond instead of osimple_stmt creates
+ * a shift/reduce conflict on an input like
+ *
+ *     if x == []int { true } { true }
+ *
+ * at the first {, giving us an opportunity
+ * to resolve it by reduce, which implements
+ * the rule about { } inside if conditions
+ * needing parens.
+ */
+condition:
+       osimple_stmt    %prec Condition
+
+
 if_header:
-       osimple_stmt
+       condition
        {
                // test
                $$ = nod(OIF, N, N);
                $$->ninit = N;
                $$->ntest = $1;
        }
-|      osimple_stmt ';' osimple_stmt
+|      osimple_stmt ';' condition
        {
                // init ; test
                $$ = nod(OIF, N, N);
@@ -791,7 +813,7 @@ pexpr:
        }
 |      pexpr '.' '(' type ')'
        {
-               $$ = nod(OCONVDOT, $1, N);
+               $$ = nod(ODOTTYPE, $1, N);
                $$->type = $4;
        }
 |      pexpr '[' expr ']'
@@ -841,24 +863,22 @@ pexpr:
                $$ = nod(OMAKE, $5, N);
                $$->type = $3;
        }
-|      convtype '(' braced_keyexpr_list ')'
+|      convtype '(' expr ')'
        {
-               // typed literal
+               // conversion
                $$ = rev($3);
                if($$ == N)
                        $$ = nod(OEMPTY, N, N);
-               $$ = nod(OCONVPAREN, $$, N);
+               $$ = nod(OCONV, $$, N);
                $$->type = $1;
        }
 |      convtype '{' braced_keyexpr_list '}'
        {
-               if(!debug['{'])
-                       warn("braces should now be parens");
-               // composite literal
+               // composite expression
                $$ = rev($3);
                if($$ == N)
                        $$ = nod(OEMPTY, N, N);
-               $$ = nod(OCONVPAREN, $$, N);
+               $$ = nod(OCOMPOS, $$, N);
                $$->type = $1;
        }
 |      fnliteral
index 2ddf6e8cadc3a03671acaeed82a22d1cc01efa3f..7d5890c6bb234c118a8138a7cbe7f8adfd337364 100644 (file)
@@ -634,9 +634,9 @@ opnames[] =
        [OXCASE]        = "XCASE",
        [OCMP]          = "CMP",
        [OFALL]         = "FALL",
+       [OCOMPOS]       = "COMPOS",
+       [ODOTTYPE]              = "DOTTYPE",
        [OCONV] = "CONV",
-       [OCONVDOT]              = "CONVDOT",
-       [OCONVPAREN]    = "CONVPAREN",
        [OCOM]          = "COM",
        [OCONST]        = "CONST",
        [OCONTINUE]     = "CONTINUE",
index 116fdec2c9d89784bbe92be37294c476f52b0551..c7deefc91636f5039a2fd1dd4dbf114c54187933 100644 (file)
@@ -510,7 +510,7 @@ loop:
                        }
                        break;
 
-               case OCONVDOT:
+               case ODOTTYPE:
                        if(cl == 2 && cr == 1) {
                                // a,b = i.(T)
                                walktype(r->left, Erv);
@@ -593,13 +593,41 @@ loop:
                goto ret;
 
        case OCONV:
-       case OCONVDOT:
-       case OCONVPAREN:
+       case ODOTTYPE:
                if(top != Erv)
                        goto nottop;
                walkconv(n);
                goto ret;
 
+       case OCOMPOS:
+               t = n->type;
+               if(t == T)
+                       goto ret;
+               l = n->left;
+               if(l == N)
+                       goto ret;
+               walktype(l, Erv);
+       
+               // structure literal
+               if(t->etype == TSTRUCT) {
+                       indir(n, structlit(n, N));
+                       goto ret;
+               }
+
+               // array literal
+               if(t->etype == TARRAY) {
+                       indir(n, arraylit(n, N));
+                       goto ret;
+               }
+
+               // map literal
+               if(t->etype == TMAP) {
+                       indir(n, maplit(n, N));
+                       goto ret;
+               }
+               yyerror("invalid type for composite literal: %T", t);
+               goto ret;
+
        case ORETURN:
                if(top != Etop)
                        goto nottop;
@@ -887,11 +915,7 @@ loop:
        case OADDR:
                if(top != Erv)
                        goto nottop;
-               if(n->left->op == OCONVPAREN && n->left->type != T)
-               switch(n->left->type->etype) {
-               case TSTRUCT:
-               case TARRAY:
-               case TMAP:
+               if(n->left->op == OCOMPOS && n->left->type != T) {
                        // turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation.
                        // initialize with
                        //      nvar := new(*Point);
@@ -920,13 +944,14 @@ loop:
                                maplit(n->left, nstar);
                                break;
                        default:
-                               fatal("addr lit %T", n->left->type);
+                               goto badlit;
                        }
 
                        indir(n, nvar);
                        goto ret;
                }
 
+       badlit:
                if(istype(n->left->type, TFUNC) && n->left->class == PFUNC) {
                        if(!n->diag) {
                                n->diag = 1;
@@ -1130,10 +1155,12 @@ walkbool(Node *n)
                        yyerror("IF and FOR require a boolean type");
 }
 
+
+
 void
 walkconv(Node *n)
 {
-       int et, op;
+       int et;
        Type *t;
        Node *l;
 
@@ -1145,17 +1172,20 @@ walkconv(Node *n)
                return;
        walktype(l, Erv);
 
-       switch(t->etype) {
-       case TSTRUCT:
-       case TMAP:
-       case TARRAY:
-               break;
-       default:
-               convlit1(l, t, 1);
+       convlit1(l, t, 1);
+
+       // if using .(T), interface assertion.
+       if(n->op == ODOTTYPE) {
+               // interface conversion
+               et = ifaceas(n->type, l->type, 1);
+               if(et != Inone) {
+                       indir(n, ifaceop(n->type, l, et));
+                       return;
+               }
+               goto bad;
        }
 
-       op = n->op;
-       n->op = OCONV;  // generic conversion
+       // otherwise, conversion.
 
        // nil conversion
        if(eqtype(t, l->type, 0)) {
@@ -1218,37 +1248,7 @@ walkconv(Node *n)
                        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;
-               }
-       }
-
+bad:
        if(l->type != T)
                yyerror("invalid conversion: %T to %T", l->type, t);
        else if(n->left->op == OLIST)
@@ -1256,7 +1256,6 @@ walkconv(Node *n)
 }
 
 
-
 /*
  * return the first type
  */
@@ -3146,7 +3145,7 @@ multi:
                n = list(n, a);
                break;
 
-       case OCONVDOT:
+       case ODOTTYPE:
                // a,b := i.(T)
                if(cl != 2)
                        goto badt;