mirror of
https://github.com/golang/go
synced 2024-11-18 19:24:39 -07:00
added key:val extension to
structure and array literals R=r OCL=29190 CL=29190
This commit is contained in:
parent
f2dfc55f34
commit
a016081f43
@ -786,6 +786,10 @@ gen_as_init(Node *nr, Node *nl)
|
||||
goto yes;
|
||||
}
|
||||
|
||||
if(nr->op == OCOMPMAP) {
|
||||
goto yes;
|
||||
}
|
||||
|
||||
if(nr->type == T ||
|
||||
!eqtype(nl->type, nr->type))
|
||||
goto no;
|
||||
|
@ -19,6 +19,7 @@ OFILES=\
|
||||
lex.$O\
|
||||
subr.$O\
|
||||
dcl.$O\
|
||||
sinit.$O\
|
||||
export.$O\
|
||||
walk.$O\
|
||||
swt.$O\
|
||||
|
@ -773,3 +773,26 @@ smallintconst(Node *n)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
nonnegconst(Node *n)
|
||||
{
|
||||
if(n->op == OLITERAL)
|
||||
switch(simtype[n->type->etype]) {
|
||||
case TINT8:
|
||||
case TUINT8:
|
||||
case TINT16:
|
||||
case TUINT16:
|
||||
case TINT32:
|
||||
case TUINT32:
|
||||
case TINT64:
|
||||
case TUINT64:
|
||||
case TIDEAL:
|
||||
// check negative and 2^31
|
||||
if(mpcmpfixfix(n->val.u.xval, minintval[TUINT32]) < 0
|
||||
|| mpcmpfixfix(n->val.u.xval, maxintval[TINT32]) > 0)
|
||||
break;
|
||||
return mpgetfix(n->val.u.xval);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
232
src/cmd/gc/dcl.c
232
src/cmd/gc/dcl.c
@ -1322,238 +1322,6 @@ anyinit(Node *n)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* the init code (thru initfix) reformats the
|
||||
* var = ...
|
||||
* statements, rewriting the automatic
|
||||
* variables with the static variables.
|
||||
* this allows the code generator to
|
||||
* generate DATA statements instead
|
||||
* of assignment statements.
|
||||
* it is quadradic, may need to change.
|
||||
* it is extremely fragile knowing exactly
|
||||
* how the code from (struct|array|map)lit
|
||||
* will look. ideally the lit routines could
|
||||
* write the code in this form, but ...
|
||||
*/
|
||||
|
||||
static Node* xxx;
|
||||
|
||||
void
|
||||
initlin(Node* n)
|
||||
{
|
||||
if(n == N)
|
||||
return;
|
||||
initlin(n->ninit);
|
||||
switch(n->op) {
|
||||
default:
|
||||
print("o = %O\n", n->op);
|
||||
n->ninit = N;
|
||||
xxx = list(xxx, n);
|
||||
break;
|
||||
|
||||
case OCALL:
|
||||
// call to mapassign1
|
||||
if(n->left->op != ONAME ||
|
||||
n->right->op != OLIST ||
|
||||
n->right->left->op != OAS ||
|
||||
n->right->right->op != OLIST ||
|
||||
n->right->right->left->op != OAS ||
|
||||
n->right->right->right->op != OAS ||
|
||||
strcmp(n->left->sym->name, "mapassign1") != 0)
|
||||
dump("o=call", n);
|
||||
n->ninit = N;
|
||||
xxx = list(xxx, n);
|
||||
break;
|
||||
|
||||
case OAS:
|
||||
n->ninit = N;
|
||||
xxx = list(xxx, n);
|
||||
break;
|
||||
|
||||
case OLIST:
|
||||
initlin(n->left);
|
||||
initlin(n->right);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
inittmp(Node *n)
|
||||
{
|
||||
if(n != N)
|
||||
if(n->op == ONAME)
|
||||
if(n->sym != S)
|
||||
if(n->class == PAUTO)
|
||||
if(strcmp(n->sym->name, "!tmpname!") == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sametmp(Node *n1, Node *n2)
|
||||
{
|
||||
if(inittmp(n1))
|
||||
if(n1->xoffset == n2->xoffset)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
indsametmp(Node *n1, Node *n2)
|
||||
{
|
||||
if(n1->op == OIND)
|
||||
if(inittmp(n1->left))
|
||||
if(n1->left->xoffset == n2->xoffset)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Node*
|
||||
slicerewrite(Node *n)
|
||||
{
|
||||
Iter param;
|
||||
Node *a, *wid, *nel;
|
||||
Type *t;
|
||||
int b;
|
||||
|
||||
if(n == N || n->op != OCALL || !isslice(n->type) ||
|
||||
n->left == N || n->left->sym == S ||
|
||||
strcmp(n->left->sym->name, "newarray") != 0)
|
||||
goto no;
|
||||
|
||||
// call to newarray - find width and nel
|
||||
wid = N;
|
||||
nel = N;
|
||||
a = listfirst(¶m, &n->right);
|
||||
while(a != N) {
|
||||
if(a->op == OAS &&
|
||||
a->left != N && a->right != N &&
|
||||
a->left->op == OINDREG && a->right->op == OLITERAL &&
|
||||
a->left->sym != S) {
|
||||
if(strcmp(a->left->sym->name, "nel") == 0)
|
||||
nel = a->right;
|
||||
if(strcmp(a->left->sym->name, "width") == 0)
|
||||
wid = a->right;
|
||||
}
|
||||
a = listnext(¶m);
|
||||
}
|
||||
if(wid == N || nel == N)
|
||||
goto no;
|
||||
|
||||
b = mpgetfix(nel->val.u.xval);
|
||||
if(b == 0)
|
||||
goto no;
|
||||
|
||||
t = shallow(n->type);
|
||||
t->bound = b;
|
||||
a = staticname(t);
|
||||
a = nod(OCOMPSLICE, a, N);
|
||||
a->type = n->type;
|
||||
return a;
|
||||
|
||||
no:
|
||||
return N;
|
||||
}
|
||||
|
||||
int
|
||||
initsub(Node *n, Node *nam)
|
||||
{
|
||||
Iter iter, param;
|
||||
Node *r, *w;
|
||||
int any;
|
||||
|
||||
any = 0;
|
||||
r = listfirst(&iter, &xxx);
|
||||
while(r != N) {
|
||||
switch(r->op) {
|
||||
case OAS:
|
||||
case OEMPTY:
|
||||
if(r->left != N)
|
||||
switch(r->left->op) {
|
||||
case ONAME:
|
||||
if(sametmp(r->left, nam)) {
|
||||
any = 1;
|
||||
w = slicerewrite(r->right);
|
||||
r->left = n;
|
||||
if(w != N) {
|
||||
n = w->left; // from now on use fixed array
|
||||
r->right = w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ODOT:
|
||||
if(sametmp(r->left->left, nam)) {
|
||||
any = 1;
|
||||
r->left->left = n;
|
||||
}
|
||||
if(indsametmp(r->left->left, nam)) {
|
||||
any = 1;
|
||||
r->left->left->left = n;
|
||||
}
|
||||
break;
|
||||
case OINDEX:
|
||||
if(sametmp(r->left->left, nam)) {
|
||||
any = 1;
|
||||
r->left->left = n;
|
||||
}
|
||||
if(indsametmp(r->left->left, nam)) {
|
||||
any = 1;
|
||||
r->left->left->left = n;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OCALL:
|
||||
// call to mapassign1
|
||||
// look through the parameters
|
||||
w = listfirst(¶m, &r->right);
|
||||
while(w != N) {
|
||||
if(sametmp(w->right, nam)) {
|
||||
any = 1;
|
||||
w->right = n;
|
||||
}
|
||||
if(indsametmp(w->right, nam)) {
|
||||
any = 1;
|
||||
w->right->left = n;
|
||||
}
|
||||
w = listnext(¶m);
|
||||
}
|
||||
break;
|
||||
}
|
||||
r = listnext(&iter);
|
||||
}
|
||||
return any;
|
||||
}
|
||||
|
||||
Node*
|
||||
initfix(Node* n)
|
||||
{
|
||||
Iter iter;
|
||||
Node *r;
|
||||
|
||||
//dump("prelin", n);
|
||||
|
||||
xxx = N;
|
||||
initlin(n);
|
||||
xxx = rev(xxx);
|
||||
|
||||
//dump("preinitfix", xxx);
|
||||
// look for the copy-out reference
|
||||
r = listfirst(&iter, &xxx);
|
||||
while(r != N) {
|
||||
if(r->op == OAS)
|
||||
if(inittmp(r->right)) {
|
||||
if(initsub(r->left, r->right))
|
||||
r->op = OEMPTY;
|
||||
}
|
||||
r = listnext(&iter);
|
||||
}
|
||||
//dump("postinitfix", xxx);
|
||||
return xxx;
|
||||
}
|
||||
|
||||
void
|
||||
fninit(Node *n)
|
||||
{
|
||||
|
@ -849,6 +849,12 @@ void funclit0(Type*);
|
||||
Node* funclit1(Type*, Node*);
|
||||
Node* unsafenmagic(Node*, Node*);
|
||||
|
||||
/*
|
||||
* sinit.c
|
||||
*/
|
||||
|
||||
Node* initfix(Node*);
|
||||
|
||||
/*
|
||||
* export.c
|
||||
*/
|
||||
@ -939,6 +945,7 @@ void convlit(Node*, Type*);
|
||||
void evconst(Node*);
|
||||
int cmpslit(Node *l, Node *r);
|
||||
int smallintconst(Node*);
|
||||
long nonnegconst(Node*);
|
||||
int consttype(Node*);
|
||||
int isconst(Node*, int);
|
||||
|
||||
|
@ -1786,12 +1786,20 @@ hidden_interfacedcl_list:
|
||||
$$ = rev($1);
|
||||
}
|
||||
|
||||
/*
|
||||
* list of combo of keyval and val
|
||||
*/
|
||||
keyval_list_r:
|
||||
keyval
|
||||
| expr
|
||||
| keyval_list_r ',' keyval
|
||||
{
|
||||
$$ = nod(OLIST, $1, $3);
|
||||
}
|
||||
| keyval_list_r ',' expr
|
||||
{
|
||||
$$ = nod(OLIST, $1, $3);
|
||||
}
|
||||
|
||||
/*
|
||||
* have to spell this out using _r lists to avoid yacc conflict
|
||||
@ -1804,10 +1812,6 @@ braced_keyexpr_list:
|
||||
{
|
||||
$$ = rev($1);
|
||||
}
|
||||
| expr_list_r ocomma
|
||||
{
|
||||
$$ = rev($1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
346
src/cmd/gc/sinit.c
Normal file
346
src/cmd/gc/sinit.c
Normal file
@ -0,0 +1,346 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "go.h"
|
||||
|
||||
static struct
|
||||
{
|
||||
Node* list;
|
||||
Node* mapname;
|
||||
Type* type;
|
||||
} xxx;
|
||||
|
||||
/*
|
||||
* the init code (thru initfix) reformats the
|
||||
* var = ...
|
||||
* statements, rewriting the automatic
|
||||
* variables with the static variables.
|
||||
* this allows the code generator to
|
||||
* generate DATA statements instead
|
||||
* of assignment statements.
|
||||
* it is quadradic, may need to change.
|
||||
* it is extremely fragile knowing exactly
|
||||
* how the code from (struct|array|map)lit
|
||||
* will look. ideally the lit routines could
|
||||
* write the code in this form, but ...
|
||||
*/
|
||||
|
||||
void
|
||||
initlin(Node* n)
|
||||
{
|
||||
if(n == N)
|
||||
return;
|
||||
initlin(n->ninit);
|
||||
switch(n->op) {
|
||||
default:
|
||||
print("o = %O\n", n->op);
|
||||
n->ninit = N;
|
||||
xxx.list = list(xxx.list, n);
|
||||
break;
|
||||
|
||||
case OCALL:
|
||||
// call to mapassign1
|
||||
if(n->left->op != ONAME ||
|
||||
n->right->op != OLIST ||
|
||||
n->right->left->op != OAS ||
|
||||
n->right->right->op != OLIST ||
|
||||
n->right->right->left->op != OAS ||
|
||||
n->right->right->right->op != OAS ||
|
||||
strcmp(n->left->sym->name, "mapassign1") != 0)
|
||||
dump("o=call", n);
|
||||
n->ninit = N;
|
||||
xxx.list = list(xxx.list, n);
|
||||
break;
|
||||
|
||||
case OAS:
|
||||
n->ninit = N;
|
||||
xxx.list = list(xxx.list, n);
|
||||
break;
|
||||
|
||||
case OLIST:
|
||||
initlin(n->left);
|
||||
initlin(n->right);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
inittmp(Node *n)
|
||||
{
|
||||
if(n != N)
|
||||
if(n->op == ONAME)
|
||||
if(n->sym != S)
|
||||
if(n->class == PAUTO)
|
||||
if(strcmp(n->sym->name, "!tmpname!") == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sametmp(Node *n1, Node *n2)
|
||||
{
|
||||
if(inittmp(n1))
|
||||
if(n1->xoffset == n2->xoffset)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
indsametmp(Node *n1, Node *n2)
|
||||
{
|
||||
if(n1->op == OIND)
|
||||
if(inittmp(n1->left))
|
||||
if(n1->left->xoffset == n2->xoffset)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Node*
|
||||
findarg(Node *n, char *arg, char *fn)
|
||||
{
|
||||
Iter param;
|
||||
Node *a;
|
||||
|
||||
if(n == N || n->op != OCALL ||
|
||||
n->left == N || n->left->sym == S ||
|
||||
strcmp(n->left->sym->name, fn) != 0)
|
||||
return N;
|
||||
|
||||
a = listfirst(¶m, &n->right);
|
||||
while(a != N) {
|
||||
if(a->op == OAS &&
|
||||
a->left != N && a->right != N &&
|
||||
a->left->op == OINDREG &&
|
||||
a->left->sym != S)
|
||||
if(strcmp(a->left->sym->name, arg) == 0)
|
||||
return a->right;
|
||||
a = listnext(¶m);
|
||||
}
|
||||
return N;
|
||||
}
|
||||
|
||||
Node*
|
||||
slicerewrite(Node *n)
|
||||
{
|
||||
Node *nel;
|
||||
Type *t;
|
||||
int b;
|
||||
Node *a;
|
||||
|
||||
// call to newarray - find nel argument
|
||||
nel = findarg(n, "nel", "newarray");
|
||||
if(nel == N || !isslice(n->type))
|
||||
goto no;
|
||||
|
||||
b = mpgetfix(nel->val.u.xval);
|
||||
t = shallow(n->type);
|
||||
t->bound = b;
|
||||
|
||||
// special hack for zero-size array
|
||||
// invent an l-value to point at
|
||||
if(b == 0)
|
||||
a = staticname(types[TBOOL]);
|
||||
else
|
||||
a = staticname(t);
|
||||
|
||||
a = nod(OCOMPSLICE, a, N);
|
||||
a->type = n->type;
|
||||
return a;
|
||||
|
||||
no:
|
||||
return N;
|
||||
}
|
||||
|
||||
Node*
|
||||
maprewrite(Node *n)
|
||||
{
|
||||
Node *nel;
|
||||
Type *ta, *tb;
|
||||
Node *a;
|
||||
|
||||
// call to newarray - find nel argument
|
||||
nel = findarg(n, "hint", "newmap");
|
||||
if(nel == N)
|
||||
goto no;
|
||||
ta = n->type;
|
||||
if(ta->etype != TMAP)
|
||||
goto no;
|
||||
|
||||
// create a new type from map[index]value
|
||||
// [0]struct { a index; b value) }
|
||||
|
||||
tb = typ(TFIELD);
|
||||
tb->type = ta->down;
|
||||
tb->sym = lookup("key");
|
||||
tb->nname = newname(tb->sym);
|
||||
tb->down = typ(TFIELD);
|
||||
tb->down->type = ta->type;
|
||||
tb->down->sym = lookup("val");
|
||||
tb->down->nname = newname(tb->down->sym);
|
||||
|
||||
ta = typ(TSTRUCT);
|
||||
ta->type = tb;
|
||||
|
||||
tb = typ(TARRAY);
|
||||
tb->type = ta;
|
||||
tb->bound = 0;
|
||||
|
||||
dowidth(tb);
|
||||
|
||||
a = staticname(tb);
|
||||
a = nod(OCOMPMAP, a, N);
|
||||
a->type = n->type;
|
||||
|
||||
// save stuff for this iteration
|
||||
xxx.mapname = a->left;
|
||||
xxx.type = tb;
|
||||
|
||||
return a;
|
||||
|
||||
no:
|
||||
return N;
|
||||
}
|
||||
|
||||
// convert the call to mapassign1
|
||||
// into static[i].key = k, static[i].val = v
|
||||
Node*
|
||||
mapindex(Node *n)
|
||||
{
|
||||
Node *index, *val, *key, *a, *b;
|
||||
|
||||
// pull all the primatives
|
||||
key = findarg(n, "key", "mapassign1");
|
||||
val = findarg(n, "val", "mapassign1");
|
||||
index = nodintconst(xxx.type->bound);
|
||||
xxx.type->bound++;
|
||||
dowidth(xxx.type);
|
||||
|
||||
// build tree
|
||||
a = nod(OINDEX, xxx.mapname, index);
|
||||
a = nod(ODOT, a, newname(lookup("key")));
|
||||
a = nod(OAS, a, key);
|
||||
|
||||
b = nod(OINDEX, xxx.mapname, index);
|
||||
b = nod(ODOT, b, newname(lookup("val")));
|
||||
b = nod(OAS, b, val);
|
||||
|
||||
a = nod(OLIST, a, b);
|
||||
walktype(a, Etop);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
// for a copy out reference, A = B,
|
||||
// look through the whole structure
|
||||
// and substitute references of B to A.
|
||||
// some rewrite goes on also.
|
||||
int
|
||||
initsub(Node *n, Node *nam)
|
||||
{
|
||||
Iter iter;
|
||||
Node *r, *w;
|
||||
int any;
|
||||
|
||||
any = 0;
|
||||
r = listfirst(&iter, &xxx.list);
|
||||
while(r != N) {
|
||||
switch(r->op) {
|
||||
case OAS:
|
||||
case OEMPTY:
|
||||
if(r->left != N)
|
||||
switch(r->left->op) {
|
||||
case ONAME:
|
||||
if(sametmp(r->left, nam)) {
|
||||
any = 1;
|
||||
r->left = n;
|
||||
|
||||
w = slicerewrite(r->right);
|
||||
if(w != N) {
|
||||
n = w->left; // from now on use fixed array
|
||||
r->right = w;
|
||||
break;
|
||||
}
|
||||
|
||||
w = maprewrite(r->right);
|
||||
if(w != N) {
|
||||
n = w->left; // from now on use fixed array
|
||||
r->right = w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ODOT:
|
||||
if(sametmp(r->left->left, nam)) {
|
||||
any = 1;
|
||||
r->left->left = n;
|
||||
}
|
||||
if(indsametmp(r->left->left, nam)) {
|
||||
any = 1;
|
||||
r->left->left->left = n;
|
||||
}
|
||||
break;
|
||||
case OINDEX:
|
||||
if(sametmp(r->left->left, nam)) {
|
||||
any = 1;
|
||||
r->left->left = n;
|
||||
}
|
||||
if(indsametmp(r->left->left, nam)) {
|
||||
any = 1;
|
||||
r->left->left->left = n;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OCALL:
|
||||
// call to mapassign1
|
||||
// look through the parameters
|
||||
w = findarg(r, "hmap", "mapassign1");
|
||||
if(w == N)
|
||||
break;
|
||||
if(sametmp(w, nam)) {
|
||||
any = 1;
|
||||
*r = *mapindex(r);
|
||||
}
|
||||
if(indsametmp(w, nam)) {
|
||||
fatal("indirect map index");
|
||||
any = 1;
|
||||
w->right->left = n;
|
||||
}
|
||||
break;
|
||||
}
|
||||
r = listnext(&iter);
|
||||
}
|
||||
return any;
|
||||
}
|
||||
|
||||
Node*
|
||||
initfix(Node* n)
|
||||
{
|
||||
Iter iter;
|
||||
Node *r;
|
||||
|
||||
//dump("prelin", n);
|
||||
|
||||
xxx.list = N;
|
||||
initlin(n);
|
||||
xxx.list = rev(xxx.list);
|
||||
|
||||
return xxx.list;
|
||||
if(debug['A'])
|
||||
dump("preinitfix", xxx.list);
|
||||
|
||||
// look for the copy-out reference
|
||||
r = listfirst(&iter, &xxx.list);
|
||||
while(r != N) {
|
||||
if(r->op == OAS)
|
||||
if(inittmp(r->right)) {
|
||||
if(initsub(r->left, r->right))
|
||||
r->op = OEMPTY;
|
||||
}
|
||||
r = listnext(&iter);
|
||||
}
|
||||
if(debug['A'])
|
||||
dump("postinitfix", xxx.list);
|
||||
return xxx.list;
|
||||
}
|
@ -637,7 +637,7 @@ loop:
|
||||
break;
|
||||
}
|
||||
indir(n, r);
|
||||
walktype(l, Erv);
|
||||
// walktype(l, Erv);
|
||||
goto ret;
|
||||
|
||||
case ORETURN:
|
||||
@ -988,7 +988,7 @@ loop:
|
||||
goto badlit;
|
||||
}
|
||||
|
||||
walktype(n->left->left, Erv);
|
||||
// walktype(n->left->left, Erv);
|
||||
indir(n, nvar);
|
||||
goto ret;
|
||||
}
|
||||
@ -3911,6 +3911,7 @@ structlit(Node *n, Node *var)
|
||||
Iter savel, saver;
|
||||
Type *l, *t;
|
||||
Node *r, *a;
|
||||
int mixflag;
|
||||
|
||||
t = n->type;
|
||||
if(t->etype != TSTRUCT)
|
||||
@ -3921,30 +3922,66 @@ structlit(Node *n, Node *var)
|
||||
tempname(var, t);
|
||||
}
|
||||
|
||||
l = structfirst(&savel, &n->type);
|
||||
r = listfirst(&saver, &n->left);
|
||||
if(r != N && r->op == OEMPTY)
|
||||
r = N;
|
||||
|
||||
loop:
|
||||
mixflag = 0;
|
||||
if(r != N && r->op == OKEY) {
|
||||
a = nod(OAS, var, N);
|
||||
addtop = list(addtop, a);
|
||||
goto loop2;
|
||||
}
|
||||
l = structfirst(&savel, &n->type);
|
||||
|
||||
loop1:
|
||||
// assignment to every field
|
||||
if(l == T || r == N) {
|
||||
if(l != T)
|
||||
yyerror("struct literal expect expr of type %T", l);
|
||||
if(r != N)
|
||||
yyerror("struct literal too many expressions");
|
||||
if(mixflag)
|
||||
yyerror("mixture of field:value initializers");
|
||||
return var;
|
||||
}
|
||||
if(r->op == OKEY) {
|
||||
mixflag = 1;
|
||||
goto incr1;
|
||||
}
|
||||
|
||||
// build list of var.field = expr
|
||||
|
||||
a = nod(ODOT, var, newname(l->sym));
|
||||
a = nod(OAS, a, r);
|
||||
walktype(a, Etop); // add any assignments in r to addtop
|
||||
walktype(a, Etop);
|
||||
addtop = list(addtop, a);
|
||||
|
||||
incr1:
|
||||
l = structnext(&savel);
|
||||
r = listnext(&saver);
|
||||
goto loop;
|
||||
goto loop1;
|
||||
|
||||
loop2:
|
||||
// assignment to field:value elements
|
||||
if(r == N) {
|
||||
if(mixflag)
|
||||
yyerror("mixture of field:value initializers");
|
||||
return var;
|
||||
}
|
||||
if(r->op != OKEY) {
|
||||
mixflag = 1;
|
||||
goto incr2;
|
||||
}
|
||||
|
||||
// build list of var.field = expr
|
||||
a = nod(ODOT, var, newname(r->left->sym));
|
||||
a = nod(OAS, a, r->right);
|
||||
walktype(a, Etop);
|
||||
addtop = list(addtop, a);
|
||||
|
||||
incr2:
|
||||
r = listnext(&saver);
|
||||
goto loop2;
|
||||
}
|
||||
|
||||
Node*
|
||||
@ -3953,19 +3990,28 @@ arraylit(Node *n, Node *var)
|
||||
Iter saver;
|
||||
Type *t;
|
||||
Node *r, *a;
|
||||
int ninit, b;
|
||||
long ninit, b;
|
||||
|
||||
t = n->type;
|
||||
if(t->etype != TARRAY)
|
||||
fatal("arraylit: not array");
|
||||
|
||||
// count initializers
|
||||
// find max index
|
||||
ninit = 0;
|
||||
b = 0;
|
||||
|
||||
r = listfirst(&saver, &n->left);
|
||||
if(r != N && r->op == OEMPTY)
|
||||
r = N;
|
||||
|
||||
while(r != N) {
|
||||
ninit++;
|
||||
b++;
|
||||
if(r->op == OKEY) {
|
||||
evconst(r->left);
|
||||
b = nonnegconst(r->left);
|
||||
}
|
||||
if(b > ninit)
|
||||
ninit = b;
|
||||
r = listnext(&saver);
|
||||
}
|
||||
|
||||
@ -3998,18 +4044,28 @@ arraylit(Node *n, Node *var)
|
||||
}
|
||||
}
|
||||
|
||||
ninit = 0;
|
||||
b = 0;
|
||||
r = listfirst(&saver, &n->left);
|
||||
if(r != N && r->op == OEMPTY)
|
||||
r = N;
|
||||
while(r != N) {
|
||||
// build list of var[c] = expr
|
||||
a = nodintconst(ninit);
|
||||
if(r->op == OKEY) {
|
||||
b = nonnegconst(r->left);
|
||||
if(b < 0) {
|
||||
yyerror("array index must be non-negative integer");
|
||||
break;
|
||||
}
|
||||
r = r->right;
|
||||
}
|
||||
a = nodintconst(b);
|
||||
a = nod(OINDEX, var, a);
|
||||
a = nod(OAS, a, r);
|
||||
|
||||
walktype(a, Etop); // add any assignments in r to addtop
|
||||
addtop = list(addtop, a);
|
||||
ninit++;
|
||||
b++;
|
||||
|
||||
r = listnext(&saver);
|
||||
}
|
||||
return var;
|
||||
@ -4041,24 +4097,24 @@ maplit(Node *n, Node *var)
|
||||
r = N;
|
||||
|
||||
loop:
|
||||
if(r == N) {
|
||||
return var;
|
||||
while(r != N) {
|
||||
if(r == N)
|
||||
break;
|
||||
|
||||
if(r->op != OKEY) {
|
||||
yyerror("map literal must have key:value pairs");
|
||||
break;
|
||||
}
|
||||
|
||||
// build list of var[c] = expr
|
||||
a = nod(OINDEX, var, r->left);
|
||||
a = nod(OAS, a, r->right);
|
||||
walktype(a, Etop); // add any assignments in r to addtop
|
||||
addtop = list(addtop, a);
|
||||
|
||||
r = listnext(&saver);
|
||||
}
|
||||
|
||||
if(r->op != OKEY) {
|
||||
yyerror("map literal must have key:value pairs");
|
||||
return var;
|
||||
}
|
||||
|
||||
// build list of var[c] = expr
|
||||
|
||||
a = nod(OINDEX, var, r->left);
|
||||
a = nod(OAS, a, r->right);
|
||||
walktype(a, Etop); // add any assignments in r to addtop
|
||||
addtop = list(addtop, a);
|
||||
|
||||
r = listnext(&saver);
|
||||
goto loop;
|
||||
return var;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user