add composite literal ( ) syntax.

warn about composite literal { } syntax.

R=ken
OCL=25018
CL=25023
This commit is contained in:
Russ Cox 2009-02-13 14:48:16 -08:00
parent 20b6de135b
commit 07244f7c80
4 changed files with 193 additions and 149 deletions

View file

@ -326,7 +326,10 @@ enum
OINDEX, OSLICE, OINDEX, OSLICE,
ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV, ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV,
OLITERAL, OREGISTER, OINDREG, OLITERAL, OREGISTER, OINDREG,
OCONV, OCOMP, OKEY, OPARAM, OKEY, OPARAM,
OCONV,
OCONVDOT,
OCONVPAREN,
OBAD, OBAD,
OEXTEND, // 6g internal OEXTEND, // 6g internal
@ -805,6 +808,7 @@ void gettype(Node*, Node*);
void walk(Node*); void walk(Node*);
void walkstate(Node*); void walkstate(Node*);
void walktype(Node*, int); void walktype(Node*, int);
void walkconv(Node*);
void walkas(Node*); void walkas(Node*);
void walkbool(Node*); void walkbool(Node*);
Type* walkswitch(Node*, Type*(*)(Node*, Type*)); Type* walkswitch(Node*, Type*(*)(Node*, Type*));
@ -840,8 +844,8 @@ Node* reorder2(Node*);
Node* reorder3(Node*); Node* reorder3(Node*);
Node* reorder4(Node*); Node* reorder4(Node*);
Node* structlit(Node*, Node*); Node* structlit(Node*, Node*);
Node* arraylit(Node*); Node* arraylit(Node*, Node*);
Node* maplit(Node*); Node* maplit(Node*, Node*);
Node* selectas(Node*, Node*); Node* selectas(Node*, Node*);
Node* old2new(Node*, Type*); Node* old2new(Node*, Type*);
void addrescapes(Node*); void addrescapes(Node*);

View file

@ -791,7 +791,7 @@ pexpr:
} }
| pexpr '.' '(' type ')' | pexpr '.' '(' type ')'
{ {
$$ = nod(OCONV, $1, N); $$ = nod(OCONVDOT, $1, N);
$$->type = $4; $$->type = $4;
} }
| pexpr '[' expr ']' | pexpr '[' expr ']'
@ -841,20 +841,24 @@ pexpr:
$$ = nod(OMAKE, $5, N); $$ = nod(OMAKE, $5, N);
$$->type = $3; $$->type = $3;
} }
| latype '(' expr ')' | convtype '(' braced_keyexpr_list ')'
{ {
$$ = nod(OCONV, $3, N); // typed literal
$$->type = oldtype($1); $$ = rev($3);
if($$ == N)
$$ = nod(OEMPTY, N, N);
$$ = nod(OCONVPAREN, $$, N);
$$->type = $1;
} }
| convtype '{' braced_keyexpr_list '}' | convtype '{' braced_keyexpr_list '}'
{ {
if(!debug['{'])
warn("braces should now be parens");
// composite literal // composite literal
$$ = rev($3); $$ = rev($3);
if($$ == N) if($$ == N)
$$ = nod(OEMPTY, N, N); $$ = nod(OEMPTY, N, N);
if(!iscomposite($1)) $$ = nod(OCONVPAREN, $$, N);
yyerror("illegal composite literal type %T", $1);
$$ = nod(OCOMP, $$, N);
$$->type = $1; $$->type = $1;
} }
| fnliteral | fnliteral

View file

@ -634,9 +634,10 @@ opnames[] =
[OXCASE] = "XCASE", [OXCASE] = "XCASE",
[OCMP] = "CMP", [OCMP] = "CMP",
[OFALL] = "FALL", [OFALL] = "FALL",
[OCONV] = "CONV", [OCONV] = "CONV",
[OCONVDOT] = "CONVDOT",
[OCONVPAREN] = "CONVPAREN",
[OCOM] = "COM", [OCOM] = "COM",
[OCOMP] = "COMP",
[OCONST] = "CONST", [OCONST] = "CONST",
[OCONTINUE] = "CONTINUE", [OCONTINUE] = "CONTINUE",
[ODCLARG] = "DCLARG", [ODCLARG] = "DCLARG",

View file

@ -507,7 +507,7 @@ loop:
} }
break; break;
case OCONV: case OCONVDOT:
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);
@ -590,128 +590,11 @@ loop:
goto ret; goto ret;
case OCONV: case OCONV:
if(top == Etop) case OCONVDOT:
case OCONVPAREN:
if(top != Erv)
goto nottop; goto nottop;
walkconv(n);
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)
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);
goto ret; goto ret;
case ORETURN: case ORETURN:
@ -1001,14 +884,18 @@ loop:
case OADDR: case OADDR:
if(top != Erv) if(top != Erv)
goto nottop; goto nottop;
if(n->left->op == OCOMP && n->left->type != T) if(n->left->op == OCONVPAREN && n->left->type != T)
if(n->left->type->etype == TSTRUCT) { switch(n->left->type->etype) {
// turn &Point{1, 2} into allocation. case TSTRUCT:
case TARRAY:
case TMAP:
// turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation.
// initialize with // initialize with
// nvar := new(*Point); // nvar := new(*Point);
// *nvar = Point{1, 2}; // *nvar = Point(1, 2);
// and replace expression with nvar // 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); nvar = nod(OXXX, N, N);
tempname(nvar, ptrto(n->left->type)); tempname(nvar, ptrto(n->left->type));
@ -1016,10 +903,27 @@ loop:
nas = nod(OAS, nvar, callnew(n->left->type)); nas = nod(OAS, nvar, callnew(n->left->type));
addtop = list(addtop, nas); 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); indir(n, nvar);
goto ret; goto ret;
} }
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;
@ -1223,6 +1127,133 @@ walkbool(Node *n)
yyerror("IF and FOR require a boolean type"); 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 * return the first type
*/ */
@ -3110,7 +3141,7 @@ multi:
n = list(n, a); n = list(n, a);
break; break;
case OCONV: case OCONVDOT:
// a,b := i.(T) // a,b := i.(T)
if(cl != 2) if(cl != 2)
goto badt; goto badt;
@ -3538,11 +3569,11 @@ loop:
} }
Node* Node*
arraylit(Node *n) arraylit(Node *n, Node *var)
{ {
Iter saver; Iter saver;
Type *t; Type *t;
Node *var, *r, *a, *nnew; Node *r, *a, *nnew;
int idx, ninit, b; int idx, ninit, b;
t = n->type; t = n->type;
@ -3567,8 +3598,10 @@ arraylit(Node *n)
t->bound = b; t->bound = b;
} }
var = nod(OXXX, N, N); if(var == N) {
tempname(var, t); var = nod(OXXX, N, N);
tempname(var, t);
}
nnew = nil; nnew = nil;
if(b < 0) { if(b < 0) {
@ -3606,18 +3639,20 @@ arraylit(Node *n)
} }
Node* Node*
maplit(Node *n) maplit(Node *n, Node *var)
{ {
Iter saver; Iter saver;
Type *t; Type *t;
Node *var, *r, *a; Node *r, *a;
t = n->type; t = n->type;
if(t->etype != TMAP) if(t->etype != TMAP)
fatal("maplit: not map"); fatal("maplit: not map");
var = nod(OXXX, N, N); if(var == N) {
tempname(var, t); var = nod(OXXX, N, N);
tempname(var, t);
}
a = nod(OMAKE, N, N); a = nod(OMAKE, N, N);
a->type = t; a->type = t;