Commit 49cc649e authored by Russ Cox's avatar Russ Cox

back to T{x}, stricter handling of T(x) vs x.(T)

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