1
0
mirror of https://github.com/golang/go synced 2024-07-08 20:29:48 +00:00

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,
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*);

View 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

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

View 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)
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;
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);
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;