mirror of
https://github.com/golang/go
synced 2024-10-14 20:05:36 +00:00
add composite literal ( ) syntax.
warn about composite literal { } syntax. R=ken OCL=25018 CL=25023
This commit is contained in:
parent
20b6de135b
commit
07244f7c80
|
@ -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*);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -635,8 +635,9 @@ opnames[] =
|
||||||
[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",
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(var == N) {
|
||||||
var = nod(OXXX, N, N);
|
var = nod(OXXX, N, N);
|
||||||
tempname(var, t);
|
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");
|
||||||
|
|
||||||
|
if(var == N) {
|
||||||
var = nod(OXXX, N, N);
|
var = nod(OXXX, N, N);
|
||||||
tempname(var, t);
|
tempname(var, t);
|
||||||
|
}
|
||||||
|
|
||||||
a = nod(OMAKE, N, N);
|
a = nod(OMAKE, N, N);
|
||||||
a->type = t;
|
a->type = t;
|
||||||
|
|
Loading…
Reference in a new issue