1
0
mirror of https://github.com/golang/go synced 2024-11-25 12:17:56 -07:00

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
This commit is contained in:
Russ Cox 2009-03-03 08:41:02 -08:00
parent be2edb5761
commit 49cc649e59
4 changed files with 87 additions and 68 deletions

View File

@ -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

View File

@ -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 @@
%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:
$$->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:
$$ = $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:
} }
| 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:
$$ = 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

View File

@ -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",

View File

@ -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:
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:
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:
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)
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)
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)
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)
} }
/* /*
* return the first type * return the first type
*/ */
@ -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;