Commit e52e9ca8 authored by Russ Cox's avatar Russ Cox

another step toward eliminating forward declarations.

introduce NodeList* type in compiler to replace OLIST.
this clarifies where lists can and cannot occur.
list append and concatenation are now cheap.
the _r rules are gone from yacc.
rev and unrev are gone.
no more lists of lists.

the representation of assignments is a bit clunkier.
split into OAS (1=1) and OAS2 (2 or more on one side).

delete dead chanrecv3 code.

delay construction of func types.

R=ken
OCL=31745
CL=31762
parent 9b475bd2
...@@ -26,7 +26,7 @@ compile(Node *fn) ...@@ -26,7 +26,7 @@ compile(Node *fn)
throwreturn = sysfunc("throwreturn"); throwreturn = sysfunc("throwreturn");
} }
if(fn->nbody == N) if(fn->nbody == nil)
return; return;
// set up domain for labels // set up domain for labels
...@@ -42,7 +42,7 @@ compile(Node *fn) ...@@ -42,7 +42,7 @@ compile(Node *fn)
t = structfirst(&save, getoutarg(curfn->type)); t = structfirst(&save, getoutarg(curfn->type));
while(t != T) { while(t != T) {
if(t->nname != N) if(t->nname != N)
curfn->nbody = list(nod(OAS, t->nname, N), curfn->nbody); curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody);
t = structnext(&save); t = structnext(&save);
} }
} }
...@@ -65,8 +65,8 @@ compile(Node *fn) ...@@ -65,8 +65,8 @@ compile(Node *fn)
ptxt = gins(ATEXT, curfn->nname, &nod1); ptxt = gins(ATEXT, curfn->nname, &nod1);
afunclit(&ptxt->from); afunclit(&ptxt->from);
gen(curfn->enter); genlist(curfn->enter);
gen(curfn->nbody); genlist(curfn->nbody);
checklabels(); checklabels();
if(curfn->type->outtuple != 0) if(curfn->type->outtuple != 0)
...@@ -326,7 +326,7 @@ cgen_aret(Node *n, Node *res) ...@@ -326,7 +326,7 @@ cgen_aret(Node *n, Node *res)
void void
cgen_ret(Node *n) cgen_ret(Node *n)
{ {
gen(n->left); // copy out args genlist(n->list); // copy out args
if(hasdefer) if(hasdefer)
ginscall(deferreturn, 0); ginscall(deferreturn, 0);
gins(ARET, N, N); gins(ARET, N, N);
......
...@@ -26,7 +26,7 @@ compile(Node *fn) ...@@ -26,7 +26,7 @@ compile(Node *fn)
throwreturn = sysfunc("throwreturn"); throwreturn = sysfunc("throwreturn");
} }
if(fn->nbody == N) if(fn->nbody == nil)
return; return;
// set up domain for labels // set up domain for labels
...@@ -42,7 +42,7 @@ compile(Node *fn) ...@@ -42,7 +42,7 @@ compile(Node *fn)
t = structfirst(&save, getoutarg(curfn->type)); t = structfirst(&save, getoutarg(curfn->type));
while(t != T) { while(t != T) {
if(t->nname != N) if(t->nname != N)
curfn->nbody = list(nod(OAS, t->nname, N), curfn->nbody); curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody);
t = structnext(&save); t = structnext(&save);
} }
} }
...@@ -66,8 +66,8 @@ compile(Node *fn) ...@@ -66,8 +66,8 @@ compile(Node *fn)
afunclit(&ptxt->from); afunclit(&ptxt->from);
ginit(); ginit();
gen(curfn->enter); genlist(curfn->enter);
gen(curfn->nbody); genlist(curfn->nbody);
gclean(); gclean();
checklabels(); checklabels();
...@@ -164,7 +164,7 @@ cgen_callinter(Node *n, Node *res, int proc) ...@@ -164,7 +164,7 @@ cgen_callinter(Node *n, Node *res, int proc)
i = &tmpi; i = &tmpi;
} }
gen(n->right); // args genlist(n->list); // assign the args
regalloc(&nodr, types[tptr], res); regalloc(&nodr, types[tptr], res);
regalloc(&nodo, types[tptr], &nodr); regalloc(&nodo, types[tptr], &nodr);
...@@ -214,7 +214,7 @@ cgen_call(Node *n, int proc) ...@@ -214,7 +214,7 @@ cgen_call(Node *n, int proc)
cgen(n->left, &afun); cgen(n->left, &afun);
} }
gen(n->right); // assign the args genlist(n->list); // assign the args
t = n->left->type; t = n->left->type;
setmaxarg(t); setmaxarg(t);
...@@ -322,7 +322,7 @@ cgen_aret(Node *n, Node *res) ...@@ -322,7 +322,7 @@ cgen_aret(Node *n, Node *res)
void void
cgen_ret(Node *n) cgen_ret(Node *n)
{ {
gen(n->left); // copy out args genlist(n->list); // copy out args
if(hasdefer) if(hasdefer)
ginscall(deferreturn, 0); ginscall(deferreturn, 0);
gins(ARET, N, N); gins(ARET, N, N);
......
...@@ -24,7 +24,7 @@ compile(Node *fn) ...@@ -24,7 +24,7 @@ compile(Node *fn)
throwreturn = sysfunc("throwreturn"); throwreturn = sysfunc("throwreturn");
} }
if(fn->nbody == N) if(fn->nbody == nil)
return; return;
// set up domain for labels // set up domain for labels
...@@ -40,7 +40,7 @@ compile(Node *fn) ...@@ -40,7 +40,7 @@ compile(Node *fn)
t = structfirst(&save, getoutarg(curfn->type)); t = structfirst(&save, getoutarg(curfn->type));
while(t != T) { while(t != T) {
if(t->nname != N) if(t->nname != N)
curfn->nbody = list(nod(OAS, t->nname, N), curfn->nbody); curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody);
t = structnext(&save); t = structnext(&save);
} }
} }
...@@ -64,8 +64,8 @@ compile(Node *fn) ...@@ -64,8 +64,8 @@ compile(Node *fn)
afunclit(&ptxt->from); afunclit(&ptxt->from);
ginit(); ginit();
gen(curfn->enter); genlist(curfn->enter);
gen(curfn->nbody); genlist(curfn->nbody);
gclean(); gclean();
checklabels(); checklabels();
...@@ -200,7 +200,7 @@ cgen_callinter(Node *n, Node *res, int proc) ...@@ -200,7 +200,7 @@ cgen_callinter(Node *n, Node *res, int proc)
i = &tmpi; i = &tmpi;
} }
gen(n->right); // args genlist(n->list); // assign the args
// Can regalloc now; i is known to be addable, // Can regalloc now; i is known to be addable,
// so the agen will be easy. // so the agen will be easy.
...@@ -255,7 +255,7 @@ cgen_call(Node *n, int proc) ...@@ -255,7 +255,7 @@ cgen_call(Node *n, int proc)
cgen(n->left, &afun); cgen(n->left, &afun);
} }
gen(n->right); // assign the args genlist(n->list); // assign the args
t = n->left->type; t = n->left->type;
setmaxarg(t); setmaxarg(t);
...@@ -360,7 +360,7 @@ cgen_aret(Node *n, Node *res) ...@@ -360,7 +360,7 @@ cgen_aret(Node *n, Node *res)
void void
cgen_ret(Node *n) cgen_ret(Node *n)
{ {
gen(n->left); // copy out args genlist(n->list); // copy out args
if(hasdefer) if(hasdefer)
ginscall(deferreturn, 0); ginscall(deferreturn, 0);
gins(ARET, N, N); gins(ARET, N, N);
......
...@@ -307,7 +307,7 @@ typeinit(void) ...@@ -307,7 +307,7 @@ typeinit(void)
mpatoflt(minfltval[TFLOAT64], "-1.7976931348623157e+308"); mpatoflt(minfltval[TFLOAT64], "-1.7976931348623157e+308");
/* for walk to use in error messages */ /* for walk to use in error messages */
types[TFUNC] = functype(N, N, N); types[TFUNC] = functype(N, nil, nil);
/* types used in front end */ /* types used in front end */
// types[TNIL] got set early in lexinit // types[TNIL] got set early in lexinit
......
...@@ -53,7 +53,6 @@ char *sysimport = ...@@ -53,7 +53,6 @@ char *sysimport =
"func sys.newchan (elemsize int, elemalg int, hint int) (hchan chan any)\n" "func sys.newchan (elemsize int, elemalg int, hint int) (hchan chan any)\n"
"func sys.chanrecv1 (hchan <-chan any) (elem any)\n" "func sys.chanrecv1 (hchan <-chan any) (elem any)\n"
"func sys.chanrecv2 (hchan <-chan any) (elem any, pres bool)\n" "func sys.chanrecv2 (hchan <-chan any) (elem any, pres bool)\n"
"func sys.chanrecv3 (hchan <-chan any, elem *any) (pres bool)\n"
"func sys.chansend1 (hchan chan<- any, elem any)\n" "func sys.chansend1 (hchan chan<- any, elem any)\n"
"func sys.chansend2 (hchan chan<- any, elem any) (pres bool)\n" "func sys.chansend2 (hchan chan<- any, elem any) (pres bool)\n"
"func sys.closechan (hchan any)\n" "func sys.closechan (hchan any)\n"
......
...@@ -22,16 +22,13 @@ dflag(void) ...@@ -22,16 +22,13 @@ dflag(void)
* append ODCL nodes to *init * append ODCL nodes to *init
*/ */
void void
dodclvar(Node *n, Type *t, Node **init) dodclvar(Node *n, Type *t, NodeList **init)
{ {
if(n == N) if(n == N)
return; return;
if(t != T && (t->etype == TIDEAL || t->etype == TNIL)) if(t != T && (t->etype == TIDEAL || t->etype == TNIL))
fatal("dodclvar %T", t); fatal("dodclvar %T", t);
for(; n->op == OLIST; n = n->right)
dodclvar(n->left, t, init);
dowidth(t); dowidth(t);
// in case of type checking error, // in case of type checking error,
...@@ -51,10 +48,6 @@ dodclconst(Node *n, Node *e) ...@@ -51,10 +48,6 @@ dodclconst(Node *n, Node *e)
{ {
if(n == N) if(n == N)
return; return;
for(; n->op == OLIST; n=n->right)
dodclconst(n, e);
addconst(n, e, dclcontext); addconst(n, e, dclcontext);
autoexport(n->sym); autoexport(n->sym);
} }
...@@ -179,18 +172,6 @@ updatetype(Type *n, Type *t) ...@@ -179,18 +172,6 @@ updatetype(Type *n, Type *t)
/* /*
* return nelem of list * return nelem of list
*/ */
int
listcount(Node *n)
{
int v;
Iter s;
v = 0;
for(n = listfirst(&s, &n); n != N; n = listnext(&s))
v++;
return v;
}
int int
structcount(Type *t) structcount(Type *t)
{ {
...@@ -208,19 +189,24 @@ structcount(Type *t) ...@@ -208,19 +189,24 @@ structcount(Type *t)
* into a type * into a type
*/ */
Type* Type*
functype(Node *this, Node *in, Node *out) functype(Node *this, NodeList *in, NodeList *out)
{ {
Type *t; Type *t;
NodeList *rcvr;
t = typ(TFUNC); t = typ(TFUNC);
t->type = dostruct(this, TFUNC); rcvr = nil;
if(this)
rcvr = list1(this);
t->type = dostruct(rcvr, TFUNC);
t->type->down = dostruct(out, TFUNC); t->type->down = dostruct(out, TFUNC);
t->type->down->down = dostruct(in, TFUNC); t->type->down->down = dostruct(in, TFUNC);
t->thistuple = listcount(this); if(this)
t->outtuple = listcount(out); t->thistuple = 1;
t->intuple = listcount(in); t->outtuple = count(out);
t->intuple = count(in);
checkwidth(t); checkwidth(t);
return t; return t;
...@@ -367,9 +353,9 @@ addmethod(Node *n, Type *t, int local) ...@@ -367,9 +353,9 @@ addmethod(Node *n, Type *t, int local)
} }
if(d == T) if(d == T)
stotype(n, 0, &pa->method); stotype(list1(n), 0, &pa->method);
else else
stotype(n, 0, &d->down); stotype(list1(n), 0, &d->down);
if(dflag()) if(dflag())
print("method %S of type %T\n", sf, pa); print("method %S of type %T\n", sf, pa);
...@@ -545,13 +531,14 @@ funclit0(Type *t) ...@@ -545,13 +531,14 @@ funclit0(Type *t)
} }
Node* Node*
funclit1(Type *type, Node *body) funclit1(Type *type, NodeList *body)
{ {
Node *func; Node *func;
Node *a, *d, *f, *n, *args, *clos, *in, *out; Node *a, *d, *f, *n, *clos;
Type *ft, *t; Type *ft, *t;
Iter save; Iter save;
int narg, shift; int narg, shift;
NodeList *args, *l, *in, *out;
popdcl(); popdcl();
func = funclit; func = funclit;
...@@ -559,15 +546,15 @@ funclit1(Type *type, Node *body) ...@@ -559,15 +546,15 @@ funclit1(Type *type, Node *body)
// build up type of func f that we're going to compile. // build up type of func f that we're going to compile.
// as we referred to variables from the outer function, // as we referred to variables from the outer function,
// we accumulated a list of PHEAP names in func. // we accumulated a list of PHEAP names in func->cvars.
//
narg = 0; narg = 0;
if(func->cvars == N) if(func->cvars == nil)
ft = type; ft = type;
else { else {
// add PHEAP versions as function arguments. // add PHEAP versions as function arguments.
in = N; in = nil;
for(a=listfirst(&save, &func->cvars); a; a=listnext(&save)) { for(l=func->cvars; l; l=l->next) {
a = l->n;
d = nod(ODCLFIELD, a, N); d = nod(ODCLFIELD, a, N);
d->type = ptrto(a->type); d->type = ptrto(a->type);
in = list(in, d); in = list(in, d);
...@@ -612,10 +599,9 @@ funclit1(Type *type, Node *body) ...@@ -612,10 +599,9 @@ funclit1(Type *type, Node *body)
a->xoffset += shift; a->xoffset += shift;
} }
} }
in = rev(in);
// out arguments // out arguments
out = N; out = nil;
for(t=structfirst(&save, getoutarg(type)); t; t=structnext(&save)) { for(t=structfirst(&save, getoutarg(type)); t; t=structnext(&save)) {
d = nod(ODCLFIELD, t->nname, N); d = nod(ODCLFIELD, t->nname, N);
d->type = t->type; d->type = t->type;
...@@ -628,7 +614,6 @@ funclit1(Type *type, Node *body) ...@@ -628,7 +614,6 @@ funclit1(Type *type, Node *body)
a->xoffset += shift; a->xoffset += shift;
} }
} }
out = rev(out);
ft = functype(N, in, out); ft = functype(N, in, out);
ft->outnamed = type->outnamed; ft->outnamed = type->outnamed;
...@@ -645,35 +630,35 @@ funclit1(Type *type, Node *body) ...@@ -645,35 +630,35 @@ funclit1(Type *type, Node *body)
n = nod(ODCLFUNC, N, N); n = nod(ODCLFUNC, N, N);
n->nname = f; n->nname = f;
n->type = ft; n->type = ft;
if(body == N) if(body == nil)
body = nod(ORETURN, N, N); body = list1(nod(ORETURN, N, N));
n->nbody = body; n->nbody = body;
compile(n); compile(n);
funcdepth--; funcdepth--;
autodcl = func->dcl; autodcl = func->dcl;
// if there's no closure, we can use f directly // if there's no closure, we can use f directly
if(func->cvars == N) if(func->cvars == nil)
return f; return f;
// build up type for this instance of the closure func. // build up type for this instance of the closure func.
in = N; in = nil;
d = nod(ODCLFIELD, N, N); // siz d = nod(ODCLFIELD, N, N); // siz
d->type = types[TINT]; d->type = types[TINT];
in = list(in, d); in = list(in, d);
d = nod(ODCLFIELD, N, N); // f d = nod(ODCLFIELD, N, N); // f
d->type = ft; d->type = ft;
in = list(in, d); in = list(in, d);
for(a=listfirst(&save, &func->cvars); a; a=listnext(&save)) { for(l=func->cvars; l; l=l->next) {
a = l->n;
d = nod(ODCLFIELD, N, N); // arg d = nod(ODCLFIELD, N, N); // arg
d->type = ptrto(a->type); d->type = ptrto(a->type);
in = list(in, d); in = list(in, d);
} }
in = rev(in);
d = nod(ODCLFIELD, N, N); d = nod(ODCLFIELD, N, N);
d->type = type; d->type = type;
out = d; out = list1(d);
clos = syslook("closure", 1); clos = syslook("closure", 1);
clos->type = functype(N, in, out); clos->type = functype(N, in, out);
...@@ -681,47 +666,42 @@ funclit1(Type *type, Node *body) ...@@ -681,47 +666,42 @@ funclit1(Type *type, Node *body)
// literal expression is sys.closure(siz, f, arg0, arg1, ...) // literal expression is sys.closure(siz, f, arg0, arg1, ...)
// which builds a function that calls f after filling in arg0, // which builds a function that calls f after filling in arg0,
// arg1, ... for the PHEAP arguments above. // arg1, ... for the PHEAP arguments above.
args = N; args = nil;
if(narg*widthptr > 100) if(narg*widthptr > 100)
yyerror("closure needs too many variables; runtime will reject it"); yyerror("closure needs too many variables; runtime will reject it");
a = nodintconst(narg*widthptr); a = nodintconst(narg*widthptr);
args = list(args, a); // siz args = list(args, a); // siz
args = list(args, f); // f args = list(args, f); // f
for(a=listfirst(&save, &func->cvars); a; a=listnext(&save)) { for(l=func->cvars; l; l=l->next) {
a = l->n;
d = oldname(a->sym); d = oldname(a->sym);
addrescapes(d); addrescapes(d);
args = list(args, nod(OADDR, d, N)); args = list(args, nod(OADDR, d, N));
} }
args = rev(args);
return nod(OCALL, clos, args); n = nod(OCALL, clos, N);
n->list = args;
return n;
} }
/* /*
* turn a parsed struct into a type * turn a parsed struct into a type
*/ */
Type** Type**
stotype(Node *n, int et, Type **t) stotype(NodeList *l, int et, Type **t)
{ {
Type *f, *t1; Type *f, *t1;
Iter save;
Strlit *note; Strlit *note;
int lno; int lno;
Node *init; NodeList *init;
Node *n;
init = N; init = nil;
lno = lineno; lno = lineno;
for(n = listfirst(&save, &n); n != N; n = listnext(&save)) { for(; l; l=l->next) {
note = nil; n = l->n;
lineno = n->lineno; lineno = n->lineno;
if(n->op == OLIST) { note = nil;
// recursive because it can be lists of lists
t = stotype(n, et, t);
continue;
}
if(n->op != ODCLFIELD) if(n->op != ODCLFIELD)
fatal("stotype: oops %N\n", n); fatal("stotype: oops %N\n", n);
...@@ -803,7 +783,7 @@ stotype(Node *n, int et, Type **t) ...@@ -803,7 +783,7 @@ stotype(Node *n, int et, Type **t)
} }
Type* Type*
dostruct(Node *n, int et) dostruct(NodeList *l, int et)
{ {
Type *t; Type *t;
int funarg; int funarg;
...@@ -820,7 +800,7 @@ dostruct(Node *n, int et) ...@@ -820,7 +800,7 @@ dostruct(Node *n, int et)
} }
t = typ(et); t = typ(et);
t->funarg = funarg; t->funarg = funarg;
stotype(n, et, &t->type); stotype(l, et, &t->type);
if(!funarg) if(!funarg)
checkwidth(t); checkwidth(t);
return t; return t;
...@@ -1218,7 +1198,7 @@ oldname(Sym *s) ...@@ -1218,7 +1198,7 @@ oldname(Sym *s)
n->closure = c; n->closure = c;
c->closure = n; c->closure = n;
if(funclit != N) if(funclit != N)
funclit->cvars = list(c, funclit->cvars); funclit->cvars = list(funclit->cvars, c);
} }
// return ref to closure var, not original // return ref to closure var, not original
return n->closure; return n->closure;
...@@ -1265,45 +1245,15 @@ oldtype(Sym *s) ...@@ -1265,45 +1245,15 @@ oldtype(Sym *s)
} }
/* /*
* n is a node with a name (or a reversed list of them). * n is a node with a name.
* make it an anonymous declaration of that name's type.
*/
Node*
nametoanondcl(Node *na)
{
Node **l, *n;
Type *t;
for(l=&na; (n=*l)->op == OLIST; l=&n->left)
n->right = nametoanondcl(n->right);
n = n->sym->def;
if(n == N || n->op != OTYPE || (t = n->type) == T) {
yyerror("%S is not a type", n->sym);
t = typ(TINT32);
}
n = nod(ODCLFIELD, N, N);
n->type = t;
*l = n;
return na;
}
/*
* n is a node with a name (or a reversed list of them).
* make it a declaration of the given type. * make it a declaration of the given type.
*/ */
Node* Node*
nametodcl(Node *na, Type *t) nametodcl(Node *n, Type *t)
{ {
Node **l, *n;
for(l=&na; (n=*l)->op == OLIST; l=&n->left)
n->right = nametodcl(n->right, t);
n = nod(ODCLFIELD, n, N); n = nod(ODCLFIELD, n, N);
n->type = t; n->type = t;
*l = n; return n;
return na;
} }
/* /*
...@@ -1320,22 +1270,16 @@ anondcl(Type *t) ...@@ -1320,22 +1270,16 @@ anondcl(Type *t)
} }
static Node* static Node*
findtype(Node *n) findtype(NodeList *l)
{ {
Node *r; for(; l; l=l->next)
if(l->n->op == OKEY)
for(r=n; r->op==OLIST; r=r->right) return l->n->right;
if(r->left->op == OKEY)
return r->left->right;
if(r->op == OKEY)
return r->right;
if(n->op == OLIST)
n = n->left;
return N; return N;
} }
static Node* static Node*
xanondcl(Node *nt, int dddok) xanondcl(Node *nt)
{ {
Node *n; Node *n;
Type *t; Type *t;
...@@ -1347,13 +1291,11 @@ xanondcl(Node *nt, int dddok) ...@@ -1347,13 +1291,11 @@ xanondcl(Node *nt, int dddok)
} }
n = nod(ODCLFIELD, N, N); n = nod(ODCLFIELD, N, N);
n->type = t; n->type = t;
if(!dddok && t->etype == TDDD)
yyerror("only last argument can have type ...");
return n; return n;
} }
static Node* static Node*
namedcl(Node *nn, Node *nt, int dddok) namedcl(Node *nn, Node *nt)
{ {
Node *n; Node *n;
Type *t; Type *t;
...@@ -1362,7 +1304,7 @@ namedcl(Node *nn, Node *nt, int dddok) ...@@ -1362,7 +1304,7 @@ namedcl(Node *nn, Node *nt, int dddok)
nn = nn->left; nn = nn->left;
if(nn->op == OTYPE && nn->sym == S) { if(nn->op == OTYPE && nn->sym == S) {
yyerror("cannot mix anonymous %T with named arguments", nn->type); yyerror("cannot mix anonymous %T with named arguments", nn->type);
return xanondcl(nn, dddok); return xanondcl(nn);
} }
t = types[TINT32]; t = types[TINT32];
if(nt == N) if(nt == N)
...@@ -1373,41 +1315,39 @@ namedcl(Node *nn, Node *nt, int dddok) ...@@ -1373,41 +1315,39 @@ namedcl(Node *nn, Node *nt, int dddok)
t = nt->type; t = nt->type;
n = nod(ODCLFIELD, newname(nn->sym), N); n = nod(ODCLFIELD, newname(nn->sym), N);
n->type = t; n->type = t;
if(!dddok && t->etype == TDDD)
yyerror("only last argument can have type ...");
return n; return n;
} }
/* /*
* check that the list of declarations is either all anonymous or all named * check that the list of declarations is either all anonymous or all named
*/ */
Node* NodeList*
checkarglist(Node *n) checkarglist(NodeList *all)
{ {
int named;
Node *r; Node *r;
Node **l; NodeList *l;
// check for all anonymous
for(r=n; r->op==OLIST; r=r->right)
if(r->left->op == OKEY)
goto named;
if(r->op == OKEY)
goto named;
// all anonymous - add names
for(l=&n; (r=*l)->op==OLIST; l=&r->right)
r->left = xanondcl(r->left, 0);
*l = xanondcl(r, 1);
return n;
named = 0;
for(l=all; l; l=l->next) {
if(l->n->op == OKEY) {
named = 1;
break;
}
}
named: for(l=all; l; l=l->next) {
// otherwise, each run of names ends in a type. if(named)
// add a type to each one that needs one. l->n = namedcl(l->n, findtype(l));
for(l=&n; (r=*l)->op==OLIST; l=&r->right) else
r->left = namedcl(r->left, findtype(r), 0); l->n = xanondcl(l->n);
*l = namedcl(r, findtype(r), 1); if(l->next != nil) {
return n; r = l->n;
if(r != N && r->type != T && r->type->etype == TDDD)
yyerror("only last argument can have type ...");
}
}
return all;
} }
/* /*
...@@ -1429,13 +1369,13 @@ named: ...@@ -1429,13 +1369,13 @@ named:
* } * }
*/ */
int int
anyinit(Node *n) anyinit(NodeList *n)
{ {
uint32 h; uint32 h;
Sym *s; Sym *s;
// are there any init statements // are there any init statements
if(n != N) if(n != nil)
return 1; return 1;
// is this main // is this main
...@@ -1463,10 +1403,11 @@ anyinit(Node *n) ...@@ -1463,10 +1403,11 @@ anyinit(Node *n)
} }
void void
fninit(Node *n) fninit(NodeList *n)
{ {
Node *gatevar; Node *gatevar;
Node *a, *b, *fn, *r; Node *a, *b, *fn;
NodeList *r;
uint32 h; uint32 h;
Sym *s, *initsym; Sym *s, *initsym;
...@@ -1478,7 +1419,7 @@ fninit(Node *n) ...@@ -1478,7 +1419,7 @@ fninit(Node *n)
if(!anyinit(n)) if(!anyinit(n))
return; return;
r = N; r = nil;
// (1) // (1)
snprint(namebuf, sizeof(namebuf), "initdone·%s", filename); snprint(namebuf, sizeof(namebuf), "initdone·%s", filename);
...@@ -1500,7 +1441,7 @@ fninit(Node *n) ...@@ -1500,7 +1441,7 @@ fninit(Node *n)
fn = nod(ODCLFUNC, N, N); fn = nod(ODCLFUNC, N, N);
initsym = lookup(namebuf); initsym = lookup(namebuf);
fn->nname = newname(initsym); fn->nname = newname(initsym);
fn->type = functype(N, N, N); fn->type = functype(N, nil, nil);
funchdr(fn); funchdr(fn);
// (3) // (3)
...@@ -1511,8 +1452,8 @@ fninit(Node *n) ...@@ -1511,8 +1452,8 @@ fninit(Node *n)
// (4) // (4)
b = nod(OIF, N, N); b = nod(OIF, N, N);
b->ntest = nod(OEQ, gatevar, nodintconst(2)); b->ntest = nod(OEQ, gatevar, nodintconst(2));
b->nbody = nod(ORETURN, N, N); b->nbody = list1(nod(ORETURN, N, N));
a->nbody = b; a->nbody = list1(b);
// (5) // (5)
b = syslook("throwinit", 0); b = syslook("throwinit", 0);
...@@ -1540,7 +1481,7 @@ fninit(Node *n) ...@@ -1540,7 +1481,7 @@ fninit(Node *n)
} }
// (8) // (8)
r = list(r, initfix(n)); r = concat(r, initfix(n));
// (9) // (9)
// could check that it is fn of no args/returns // could check that it is fn of no args/returns
...@@ -1562,7 +1503,7 @@ fninit(Node *n) ...@@ -1562,7 +1503,7 @@ fninit(Node *n)
exportsym(fn->nname->sym); exportsym(fn->nname->sym);
fn->nbody = rev(r); fn->nbody = r;
//dump("b", fn); //dump("b", fn);
//dump("r", fn->nbody); //dump("r", fn->nbody);
...@@ -1679,26 +1620,28 @@ embedded(Sym *s) ...@@ -1679,26 +1620,28 @@ embedded(Sym *s)
* declare variables from grammar * declare variables from grammar
* new_name_list (type | [type] = expr_list) * new_name_list (type | [type] = expr_list)
*/ */
Node* NodeList*
variter(Node *vv, Type *t, Node *ee) variter(NodeList *vl, Type *t, NodeList *el)
{ {
Iter viter, eiter; int doexpr;
Node *v, *e, *r, *a; Node *v, *e, *a;
Type *tv; Type *tv;
NodeList *r;
r = nil;
doexpr = el != nil;
for(; vl; vl=vl->next) {
if(doexpr) {
if(el == nil) {
yyerror("missing expr in var dcl");
break;
}
e = el->n;
el = el->next;
} else
e = N;
vv = rev(vv); v = vl->n;
ee = rev(ee);
v = listfirst(&viter, &vv);
e = listfirst(&eiter, &ee);
r = N;
while(v != N) {
if(ee != N && e == N) {
yyerror("missing expr in var dcl");
break;
}
a = N; a = N;
if(e != N || funcdepth > 0) if(e != N || funcdepth > 0)
a = nod(OAS, v, e); a = nod(OAS, v, e);
...@@ -1709,15 +1652,12 @@ variter(Node *vv, Type *t, Node *ee) ...@@ -1709,15 +1652,12 @@ variter(Node *vv, Type *t, Node *ee)
tv = e->type; tv = e->type;
} }
dodclvar(v, tv, &r); dodclvar(v, tv, &r);
r = list(r, a); if(a != N)
r = list(r, a);
v = listnext(&viter);
if(ee != N)
e = listnext(&eiter);
} }
if(e != N) if(el != nil)
yyerror("extra expr in var dcl"); yyerror("extra expr in var dcl");
return rev(r); return r;
} }
/* /*
...@@ -1725,56 +1665,51 @@ variter(Node *vv, Type *t, Node *ee) ...@@ -1725,56 +1665,51 @@ variter(Node *vv, Type *t, Node *ee)
* new_name_list [[type] = expr_list] * new_name_list [[type] = expr_list]
*/ */
void void
constiter(Node *vv, Type *t, Node *cc) constiter(NodeList *vl, Type *t, NodeList *cl)
{ {
Iter viter, citer; Node *v, *c;
Node *v, *c, *init; NodeList *init;
if(cc == N) { if(cl == nil) {
if(t != T) if(t != T)
yyerror("constdcl cannot have type without expr"); yyerror("constdcl cannot have type without expr");
cc = lastconst; cl = lastconst;
t = lasttype; t = lasttype;
} else {
lastconst = cl;
lasttype = t;
} }
lastconst = cc; cl = listtreecopy(cl);
lasttype = t;
vv = rev(vv);
cc = rev(treecopy(cc));
v = listfirst(&viter, &vv);
c = listfirst(&citer, &cc);
loop:
if(v == N && c == N) {
iota += 1;
return;
}
if(v == N || c == N) { for(; vl; vl=vl->next) {
yyerror("shape error in const dcl"); if(cl == nil) {
iota += 1; yyerror("missing expr in const dcl");
return; break;
} }
c = cl->n;
cl = cl->next;
init = nil;
gettype(c, &init);
if(init != nil) {
// the expression had extra code to run.
// dodclconst is going to print an error
// because the expression isn't constant,
// but out of paranoia, bump nerrors so
// that compile cannot succeed accidentally
nerrors++;
}
if(t != T)
convlit(c, t);
if(t == T)
lasttype = c->type;
init = N; v = vl->n;
gettype(c, &init); dodclconst(v, c);
if(init != N) {
// the expression had extra code to run.
// dodclconst is going to print an error
// because the expression isn't constant,
// but out of paranoia, bump nerrors so
// that compile cannot succeed accidentally
nerrors++;
} }
if(t != T) if(cl != nil)
convlit(c, t); yyerror("extra expr in const dcl");
if(t == T) iota += 1;
lasttype = c->type;
dodclconst(v, c);
v = listnext(&viter);
c = listnext(&citer);
goto loop;
} }
/* /*
...@@ -1784,27 +1719,28 @@ loop: ...@@ -1784,27 +1719,28 @@ loop:
* rewrite with a constant * rewrite with a constant
*/ */
Node* Node*
unsafenmagic(Node *l, Node *r) unsafenmagic(Node *fn, NodeList *args)
{ {
Node *n, *init; Node *r, *n;
Sym *s; Sym *s;
Type *t, *tr; Type *t, *tr;
long v; long v;
Val val; Val val;
if(l == N || r == N) if(fn == N || fn->op != ONAME || (s = fn->sym) == S)
goto no;
if(l->op != ONAME)
goto no;
s = l->sym;
if(s == S)
goto no; goto no;
if(strcmp(s->package, "unsafe") != 0) if(strcmp(s->package, "unsafe") != 0)
goto no; goto no;
init = N; if(args == nil) {
yyerror("missing argument for %S", s);
goto no;
}
r = args->n;
n = nod(OLITERAL, N, N);
if(strcmp(s->name, "Sizeof") == 0) { if(strcmp(s->name, "Sizeof") == 0) {
walkexpr(r, Erv, &init); walkexpr(r, Erv, &n->ninit);
tr = r->type; tr = r->type;
if(r->op == OLITERAL && r->val.ctype == CTSTR) if(r->op == OLITERAL && r->val.ctype == CTSTR)
tr = types[TSTRING]; tr = types[TSTRING];
...@@ -1816,12 +1752,12 @@ unsafenmagic(Node *l, Node *r) ...@@ -1816,12 +1752,12 @@ unsafenmagic(Node *l, Node *r)
if(strcmp(s->name, "Offsetof") == 0) { if(strcmp(s->name, "Offsetof") == 0) {
if(r->op != ODOT && r->op != ODOTPTR) if(r->op != ODOT && r->op != ODOTPTR)
goto no; goto no;
walkexpr(r, Erv, &init); walkexpr(r, Erv, &n->ninit);
v = r->xoffset; v = r->xoffset;
goto yes; goto yes;
} }
if(strcmp(s->name, "Alignof") == 0) { if(strcmp(s->name, "Alignof") == 0) {
walkexpr(r, Erv, &init); walkexpr(r, Erv, &n->ninit);
tr = r->type; tr = r->type;
if(r->op == OLITERAL && r->val.ctype == CTSTR) if(r->op == OLITERAL && r->val.ctype == CTSTR)
tr = types[TSTRING]; tr = types[TSTRING];
...@@ -1846,6 +1782,8 @@ no: ...@@ -1846,6 +1782,8 @@ no:
return N; return N;
yes: yes:
if(args->next != nil)
yyerror("extra arguments for %S", s);
// any side effects disappear; ignore init // any side effects disappear; ignore init
val.ctype = CTINT; val.ctype = CTINT;
val.u.xval = mal(sizeof(*n->val.u.xval)); val.u.xval = mal(sizeof(*n->val.u.xval));
......
...@@ -127,6 +127,13 @@ findlab(Sym *s) ...@@ -127,6 +127,13 @@ findlab(Sym *s)
/* /*
* compile statements * compile statements
*/ */
void
genlist(NodeList *l)
{
for(; l; l=l->next)
gen(l->n);
}
void void
gen(Node *n) gen(Node *n)
{ {
...@@ -137,13 +144,12 @@ gen(Node *n) ...@@ -137,13 +144,12 @@ gen(Node *n)
lno = setlineno(n); lno = setlineno(n);
loop:
if(n == N) if(n == N)
goto ret; goto ret;
p3 = pc; // save pc for loop labels p3 = pc; // save pc for loop labels
if(n->ninit) if(n->ninit)
gen(n->ninit); genlist(n->ninit);
setlineno(n); setlineno(n);
...@@ -152,11 +158,6 @@ loop: ...@@ -152,11 +158,6 @@ loop:
fatal("gen: unknown op %N", n); fatal("gen: unknown op %N", n);
break; break;
case OLIST:
gen(n->left);
n = n->right;
goto loop;
case OCASE: case OCASE:
case OFALL: case OFALL:
case OXCASE: case OXCASE:
...@@ -164,6 +165,10 @@ loop: ...@@ -164,6 +165,10 @@ loop:
case OEMPTY: case OEMPTY:
break; break;
case OBLOCK:
genlist(n->list);
break;
case OLABEL: case OLABEL:
newlab(OLABEL, n->left->sym); newlab(OLABEL, n->left->sym);
break; break;
...@@ -232,10 +237,10 @@ loop: ...@@ -232,10 +237,10 @@ loop:
gen(n->nincr); // contin: incr gen(n->nincr); // contin: incr
patch(p1, pc); // test: patch(p1, pc); // test:
if(n->ntest != N) if(n->ntest != N)
if(n->ntest->ninit != N) if(n->ntest->ninit != nil)
gen(n->ntest->ninit); genlist(n->ntest->ninit);
bgen(n->ntest, 0, breakpc); // if(!test) goto break bgen(n->ntest, 0, breakpc); // if(!test) goto break
gen(n->nbody); // body genlist(n->nbody); // body
gjmp(continpc); gjmp(continpc);
patch(breakpc, pc); // done: patch(breakpc, pc); // done:
continpc = scontin; continpc = scontin;
...@@ -247,13 +252,13 @@ loop: ...@@ -247,13 +252,13 @@ loop:
p2 = gjmp(P); // p2: goto else p2 = gjmp(P); // p2: goto else
patch(p1, pc); // test: patch(p1, pc); // test:
if(n->ntest != N) if(n->ntest != N)
if(n->ntest->ninit != N) if(n->ntest->ninit != nil)
gen(n->ntest->ninit); genlist(n->ntest->ninit);
bgen(n->ntest, 0, p2); // if(!test) goto p2 bgen(n->ntest, 0, p2); // if(!test) goto p2
gen(n->nbody); // then genlist(n->nbody); // then
p3 = gjmp(P); // goto done p3 = gjmp(P); // goto done
patch(p2, pc); // else: patch(p2, pc); // else:
gen(n->nelse); // else genlist(n->nelse); // else
patch(p3, pc); // done: patch(p3, pc); // done:
break; break;
...@@ -272,7 +277,7 @@ loop: ...@@ -272,7 +277,7 @@ loop:
} }
patch(p1, pc); // test: patch(p1, pc); // test:
gen(n->nbody); // switch(test) body genlist(n->nbody); // switch(test) body
patch(breakpc, pc); // done: patch(breakpc, pc); // done:
breakpc = sbreak; breakpc = sbreak;
break; break;
...@@ -292,7 +297,7 @@ loop: ...@@ -292,7 +297,7 @@ loop:
} }
patch(p1, pc); // test: patch(p1, pc); // test:
gen(n->nbody); // select() body genlist(n->nbody); // select() body
patch(breakpc, pc); // done: patch(breakpc, pc); // done:
breakpc = sbreak; breakpc = sbreak;
break; break;
...@@ -432,12 +437,6 @@ cgen_as(Node *nl, Node *nr) ...@@ -432,12 +437,6 @@ cgen_as(Node *nl, Node *nr)
iszer = 0; iszer = 0;
if(nr == N || isnil(nr)) { if(nr == N || isnil(nr)) {
if(nl->op == OLIST) {
cgen_as(nl->left, nr);
cgen_as(nl->right, nr);
return;
}
// externals and heaps should already be clear // externals and heaps should already be clear
if(nr == N) { if(nr == N) {
if(nl->class == PEXTERN) if(nl->class == PEXTERN)
......
...@@ -129,6 +129,7 @@ struct Val ...@@ -129,6 +129,7 @@ struct Val
typedef struct Sym Sym; typedef struct Sym Sym;
typedef struct Node Node; typedef struct Node Node;
typedef struct NodeList NodeList;
typedef struct Type Type; typedef struct Type Type;
typedef struct Dcl Dcl; typedef struct Dcl Dcl;
...@@ -198,24 +199,26 @@ struct Node ...@@ -198,24 +199,26 @@ struct Node
Node* left; Node* left;
Node* right; Node* right;
Type* type; Type* type;
NodeList* list;
NodeList* rlist;
// for-body // for-body
Node* ninit; NodeList* ninit;
Node* ntest; Node* ntest;
Node* nincr; Node* nincr;
Node* nbody; NodeList* nbody;
// if-body // if-body
Node* nelse; NodeList* nelse;
// cases // cases
Node* ncase; Node* ncase;
// func // func
Node* nname; Node* nname;
Node* enter; NodeList* enter;
Node* exit; NodeList* exit;
Node* cvars; // closure params NodeList* cvars; // closure params
Dcl* dcl; // outer autodcl Dcl* dcl; // outer autodcl
// OLITERAL/OREGISTER // OLITERAL/OREGISTER
...@@ -242,6 +245,13 @@ struct Node ...@@ -242,6 +245,13 @@ struct Node
}; };
#define N ((Node*)0) #define N ((Node*)0)
struct NodeList
{
Node* n;
NodeList* next;
NodeList* end;
};
struct Sym struct Sym
{ {
ushort block; // blocknumber to catch redeclaration ushort block; // blocknumber to catch redeclaration
...@@ -308,12 +318,12 @@ enum ...@@ -308,12 +318,12 @@ enum
ODCL, ODCL,
ODOT, ODOTPTR, ODOTMETH, ODOTINTER, ODOT, ODOTPTR, ODOTMETH, ODOTINTER,
ODCLFUNC, ODCLFIELD, ODCLARG, ODCLFUNC, ODCLFIELD, ODCLARG,
OLIST, OCMP, OPTR, OARRAY, ORANGE, OCMP, OPTR, OARRAY, ORANGE,
ORETURN, OFOR, OIF, OSWITCH, ODEFER, ORETURN, OFOR, OIF, OSWITCH, ODEFER,
OAS, OASOP, OCASE, OXCASE, OFALL, OXFALL, OAS, OAS2, OASOP, OCASE, OXCASE, OFALL, OXFALL,
OGOTO, OPROC, OMAKE, ONEW, OEMPTY, OSELECT, OGOTO, OPROC, OMAKE, ONEW, OEMPTY, OSELECT,
OLEN, OCAP, OPANIC, OPANICN, OPRINT, OPRINTN, OTYPEOF, OLEN, OCAP, OPANIC, OPANICN, OPRINT, OPRINTN, OTYPEOF,
OCLOSE, OCLOSED, OCLOSE, OCLOSED, OBLOCK,
OOROR, OOROR,
OANDAND, OANDAND,
...@@ -590,7 +600,7 @@ EXTERN int statuniqgen; // name generator for static temps ...@@ -590,7 +600,7 @@ EXTERN int statuniqgen; // name generator for static temps
EXTERN int loophack; EXTERN int loophack;
EXTERN uint32 iota; EXTERN uint32 iota;
EXTERN Node* lastconst; EXTERN NodeList* lastconst;
EXTERN Type* lasttype; EXTERN Type* lasttype;
EXTERN int32 vargen; EXTERN int32 vargen;
EXTERN int32 exportgen; EXTERN int32 exportgen;
...@@ -605,7 +615,6 @@ EXTERN int maxround; ...@@ -605,7 +615,6 @@ EXTERN int maxround;
EXTERN int widthptr; EXTERN int widthptr;
EXTERN Node* retnil; EXTERN Node* retnil;
EXTERN Node* fskel;
EXTERN Node* typeswvar; EXTERN Node* typeswvar;
...@@ -726,15 +735,12 @@ void linehist(char*, int32, int); ...@@ -726,15 +735,12 @@ void linehist(char*, int32, int);
int32 setlineno(Node*); int32 setlineno(Node*);
Node* nod(int, Node*, Node*); Node* nod(int, Node*, Node*);
Node* nodlit(Val); Node* nodlit(Val);
Node* list(Node*, Node*);
Type* typ(int); Type* typ(int);
Dcl* dcl(void); Dcl* dcl(void);
int algtype(Type*); int algtype(Type*);
Node* rev(Node*);
Node* unrev(Node*);
Node* appendr(Node*, Node*);
void dodump(Node*, int); void dodump(Node*, int);
void dump(char*, Node*); void dump(char*, Node*);
void dumplist(char*, NodeList*);
Type* aindex(Node*, Type*); Type* aindex(Node*, Type*);
int isnil(Node*); int isnil(Node*);
int isptrto(Type*, int); int isptrto(Type*, int);
...@@ -762,17 +768,23 @@ Node* nodbool(int); ...@@ -762,17 +768,23 @@ Node* nodbool(int);
void ullmancalc(Node*); void ullmancalc(Node*);
void badtype(int, Type*, Type*); void badtype(int, Type*, Type*);
Type* ptrto(Type*); Type* ptrto(Type*);
Node* cleanidlist(Node*); NodeList* cleanidlist(NodeList*);
Node* syslook(char*, int); Node* syslook(char*, int);
Node* treecopy(Node*); Node* treecopy(Node*);
NodeList* listtreecopy(NodeList*);
int isselect(Node*); int isselect(Node*);
void tempname(Node*, Type*); void tempname(Node*, Type*);
Node* staticname(Type*); Node* staticname(Type*);
int iscomposite(Type*); int iscomposite(Type*);
Node* callnew(Type*); Node* callnew(Type*);
Node* saferef(Node*, Node**); Node* saferef(Node*, NodeList**);
int is64(Type*); int is64(Type*);
int noconv(Type*, Type*); int noconv(Type*, Type*);
NodeList* list1(Node*);
NodeList* list(NodeList*, Node*);
NodeList* concat(NodeList*, NodeList*);
int count(NodeList*);
Node* liststmt(NodeList*);
Type** getthis(Type*); Type** getthis(Type*);
Type** getoutarg(Type*); Type** getoutarg(Type*);
...@@ -782,8 +794,6 @@ Type* getthisx(Type*); ...@@ -782,8 +794,6 @@ Type* getthisx(Type*);
Type* getoutargx(Type*); Type* getoutargx(Type*);
Type* getinargx(Type*); Type* getinargx(Type*);
Node* listfirst(Iter*, Node**);
Node* listnext(Iter*);
Type* structfirst(Iter*, Type**); Type* structfirst(Iter*, Type**);
Type* structnext(Iter*); Type* structnext(Iter*);
Type* funcfirst(Iter*, Type*); Type* funcfirst(Iter*, Type*);
...@@ -817,18 +827,17 @@ int simsimtype(Type*); ...@@ -817,18 +827,17 @@ int simsimtype(Type*);
/* /*
* dcl.c * dcl.c
*/ */
void dodclvar(Node*, Type*, Node**); void dodclvar(Node*, Type*, NodeList**);
Type* dodcltype(Type*); Type* dodcltype(Type*);
void updatetype(Type*, Type*); void updatetype(Type*, Type*);
void dodclconst(Node*, Node*); void dodclconst(Node*, Node*);
void defaultlit(Node*, Type*); void defaultlit(Node*, Type*);
void defaultlit2(Node*, Node*); void defaultlit2(Node*, Node*);
int listcount(Node*);
int structcount(Type*); int structcount(Type*);
void addmethod(Node*, Type*, int); void addmethod(Node*, Type*, int);
Node* methodname(Node*, Type*); Node* methodname(Node*, Type*);
Sym* methodsym(Sym*, Type*); Sym* methodsym(Sym*, Type*);
Type* functype(Node*, Node*, Node*); Type* functype(Node*, NodeList*, NodeList*);
char* thistypenam(Node*); char* thistypenam(Node*);
void funcnam(Type*, char*); void funcnam(Type*, char*);
Node* renameinit(Node*); Node* renameinit(Node*);
...@@ -836,8 +845,8 @@ void funchdr(Node*); ...@@ -836,8 +845,8 @@ void funchdr(Node*);
void funcargs(Type*); void funcargs(Type*);
void funcbody(Node*); void funcbody(Node*);
Node* typenod(Type*); Node* typenod(Type*);
Type* dostruct(Node*, int); Type* dostruct(NodeList*, int);
Type** stotype(Node*, int, Type**); Type** stotype(NodeList*, int, Type**);
Type* sortinter(Type*); Type* sortinter(Type*);
void markdcl(void); void markdcl(void);
void popdcl(void); void popdcl(void);
...@@ -855,27 +864,26 @@ Node* newname(Sym*); ...@@ -855,27 +864,26 @@ Node* newname(Sym*);
Node* oldname(Sym*); Node* oldname(Sym*);
Type* newtype(Sym*); Type* newtype(Sym*);
Type* oldtype(Sym*); Type* oldtype(Sym*);
void fninit(Node*); void fninit(NodeList*);
Node* nametoanondcl(Node*);
Node* nametodcl(Node*, Type*); Node* nametodcl(Node*, Type*);
Node* anondcl(Type*); Node* anondcl(Type*);
Node* checkarglist(Node*); NodeList* checkarglist(NodeList*);
void checkwidth(Type*); void checkwidth(Type*);
void defercheckwidth(void); void defercheckwidth(void);
void resumecheckwidth(void); void resumecheckwidth(void);
Node* embedded(Sym*); Node* embedded(Sym*);
Node* variter(Node*, Type*, Node*); NodeList* variter(NodeList*, Type*, NodeList*);
void constiter(Node*, Type*, Node*); void constiter(NodeList*, Type*, NodeList*);
void funclit0(Type*); void funclit0(Type*);
Node* funclit1(Type*, Node*); Node* funclit1(Type*, NodeList*);
Node* unsafenmagic(Node*, Node*); Node* unsafenmagic(Node*, NodeList*);
/* /*
* sinit.c * sinit.c
*/ */
Node* initfix(Node*); NodeList* initfix(NodeList*);
/* /*
* export.c * export.c
...@@ -912,30 +920,33 @@ Type* pkgtype(Sym*); ...@@ -912,30 +920,33 @@ Type* pkgtype(Sym*);
/* /*
* walk.c * walk.c
*/ */
void gettype(Node*, Node**); void gettype(Node*, NodeList**);
void walk(Node*); void walk(Node*);
void walkstmt(Node*); void walkstmt(Node*);
void walkexpr(Node*, int, Node**); void walkstmtlist(NodeList*);
void walkconv(Node*, Node**); void walkexpr(Node*, int, NodeList**);
void walkdottype(Node*, Node**); void walkexprlist(NodeList*, int, NodeList**);
void walkconv(Node*, NodeList**);
void walkdottype(Node*, NodeList**);
void walkas(Node*); void walkas(Node*);
void walkbool(Node*); void walkbool(Node*);
void walkswitch(Node*); void walkswitch(Node*);
void walkselect(Node*); void walkselect(Node*);
void walkdot(Node*, Node**); void walkdot(Node*, NodeList**);
Node* ascompatee(int, Node**, Node**, Node**); Node* ascompatee1(int, Node*, Node*, NodeList**);
Node* ascompatet(int, Node**, Type**, int, Node**); NodeList* ascompatee(int, NodeList*, NodeList*, NodeList**);
Node* ascompatte(int, Type**, Node**, int, Node**); NodeList* ascompatet(int, NodeList*, Type**, int, NodeList**);
NodeList* ascompatte(int, Type**, NodeList*, int, NodeList**);
int ascompat(Type*, Type*); int ascompat(Type*, Type*);
Node* prcompat(Node*, int); Node* prcompat(NodeList*, int, int);
Node* nodpanic(int32); Node* nodpanic(int32);
Node* newcompat(Node*); Node* newcompat(Node*);
Node* makecompat(Node*); Node* makecompat(Node*);
Node* stringop(Node*, int, Node**); Node* stringop(Node*, int, NodeList**);
Type* fixmap(Type*); Type* fixmap(Type*);
Node* mapop(Node*, int, Node**); Node* mapop(Node*, int, NodeList**);
Type* fixchan(Type*); Type* fixchan(Type*);
Node* chanop(Node*, int, Node**); Node* chanop(Node*, int, NodeList**);
Node* arrayop(Node*, int); Node* arrayop(Node*, int);
Node* ifacecvt(Type*, Node*, int); Node* ifacecvt(Type*, Node*, int);
Node* ifaceop(Node*); Node* ifaceop(Node*);
...@@ -943,18 +954,18 @@ int ifaceas(Type*, Type*, int); ...@@ -943,18 +954,18 @@ int ifaceas(Type*, Type*, int);
int ifaceas1(Type*, Type*, int); int ifaceas1(Type*, Type*, int);
void ifacecheck(Type*, Type*, int, int); void ifacecheck(Type*, Type*, int, int);
void runifacechecks(void); void runifacechecks(void);
Node* convas(Node*, Node**); Node* convas(Node*, NodeList**);
void arrayconv(Type*, Node*); void arrayconv(Type*, Node*);
Node* colas(Node*, Node*, Node**); Node* colas(NodeList*, NodeList*);
Node* dorange(Node*); Node* dorange(Node*);
Node* reorder1(Node*); NodeList* reorder1(NodeList*);
Node* reorder3(Node*); NodeList* reorder3(NodeList*);
Node* reorder4(Node*); NodeList* reorder4(NodeList*);
Node* structlit(Node*, Node*, Node**); Node* structlit(Node*, Node*, NodeList**);
Node* arraylit(Node*, Node*, Node**); Node* arraylit(Node*, Node*, NodeList**);
Node* maplit(Node*, Node*, Node**); Node* maplit(Node*, Node*, NodeList**);
Node* selectas(Node*, Node*, Node**); Node* selectas(Node*, Node*, NodeList**);
Node* old2new(Node*, Type*, Node**); Node* old2new(Node*, Type*, NodeList**);
void addrescapes(Node*); void addrescapes(Node*);
void heapmoves(void); void heapmoves(void);
...@@ -1044,6 +1055,7 @@ void cgen_proc(Node *n, int proc); ...@@ -1044,6 +1055,7 @@ void cgen_proc(Node *n, int proc);
void checklabels(void); void checklabels(void);
Label* findlab(Sym *s); Label* findlab(Sym *s);
void gen(Node *n); void gen(Node *n);
void genlist(NodeList *l);
void newlab(int op, Sym *s); void newlab(int op, Sym *s);
Node* sysfunc(char *name); Node* sysfunc(char *name);
Plist* newplist(void); Plist* newplist(void);
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
%} %}
%union { %union {
Node* node; Node* node;
NodeList* list;
Type* type; Type* type;
Sym* sym; Sym* sym;
struct Val val; struct Val val;
...@@ -55,23 +56,26 @@ ...@@ -55,23 +56,26 @@
%type <val> oliteral %type <val> oliteral
%type <node> stmt ntype %type <node> stmt ntype
%type <node> arg_type arg_type_list %type <node> arg_type
%type <node> arg_type_list_r braced_keyexpr_list case caseblock %type <node> case caseblock
%type <node> caseblock_list_r common_dcl %type <node> compound_stmt dotname embed expr
%type <node> compound_stmt dotname embed expr expr_list %type <node> expr_or_type
%type <node> expr_list_r expr_or_type expr_or_type_list %type <node> fndcl fnliteral
%type <node> expr_or_type_list_r fnbody fndcl fnliteral fnres
%type <node> for_body for_header for_stmt if_header if_stmt %type <node> for_body for_header for_stmt if_header if_stmt
%type <node> interfacedcl interfacedcl1 interfacedcl_list_r %type <node> keyval labelname name
%type <node> keyval keyval_list_r labelname loop_body name %type <node> name_or_type
%type <node> name_list name_list_r name_or_type new_field %type <node> new_name oexpr
%type <node> new_name oarg_type_list ocaseblock_list oexpr %type <node> onew_name
%type <node> oexpr_list oexpr_or_type_list onew_name %type <node> osimple_stmt pexpr
%type <node> osimple_stmt ostmt_list oxdcl_list pexpr
%type <node> pseudocall range_stmt select_stmt %type <node> pseudocall range_stmt select_stmt
%type <node> simple_stmt stmt_list_r structdcl structdcl_list_r %type <node> simple_stmt
%type <node> switch_body switch_stmt uexpr vardcl vardcl_list_r %type <node> switch_stmt uexpr
%type <node> xdcl xdcl_list_r xfndcl %type <node> xfndcl
%type <list> xdcl fnbody common_dcl fnres switch_body loop_body
%type <list> name_list expr_list keyval_list braced_keyval_list expr_or_type_list xdcl_list
%type <list> oexpr_list oexpr_or_type_list caseblock_list stmt_list oarg_type_list arg_type_list
%type <list> interfacedcl_list interfacedcl vardcl vardcl_list structdcl structdcl_list
%type <type> type %type <type> type
%type <node> convtype dotdotdot %type <node> convtype dotdotdot
...@@ -81,13 +85,13 @@ ...@@ -81,13 +85,13 @@
%type <sym> hidden_importsym hidden_pkg_importsym %type <sym> hidden_importsym hidden_pkg_importsym
%type <node> hidden_constant hidden_dcl hidden_funarg_list %type <node> hidden_constant hidden_dcl hidden_interfacedcl hidden_structdcl
%type <node> hidden_funarg_list_r hidden_funres
%type <node> hidden_interfacedcl hidden_interfacedcl_list %type <list> hidden_funres
%type <node> hidden_interfacedcl_list_r hidden_structdcl %type <list> ohidden_funres
%type <node> hidden_structdcl_list hidden_structdcl_list_r %type <list> hidden_funarg_list ohidden_funarg_list
%type <node> ohidden_funarg_list ohidden_funres %type <list> hidden_interfacedcl_list ohidden_interfacedcl_list
%type <node> ohidden_interfacedcl_list ohidden_structdcl_list %type <list> hidden_structdcl_list ohidden_structdcl_list
%type <type> hidden_type hidden_type1 hidden_type2 %type <type> hidden_type hidden_type1 hidden_type2
...@@ -125,7 +129,7 @@ file: ...@@ -125,7 +129,7 @@ file:
loadsys loadsys
package package
imports imports
oxdcl_list xdcl_list
{ {
if(debug['f']) if(debug['f'])
frame(1); frame(1);
...@@ -165,12 +169,16 @@ imports: ...@@ -165,12 +169,16 @@ imports:
import: import:
LIMPORT import_stmt LIMPORT import_stmt
| LIMPORT '(' import_stmt_list_r osemi ')' | LIMPORT '(' import_stmt_list osemi ')'
| LIMPORT '(' ')' | LIMPORT '(' ')'
import_stmt: import_stmt:
import_here import_package import_there import_done import_here import_package import_there import_done
import_stmt_list:
import_stmt
| import_stmt_list ';' import_stmt
import_here: import_here:
LLITERAL LLITERAL
{ {
...@@ -202,13 +210,22 @@ import_package: ...@@ -202,13 +210,22 @@ import_package:
} }
import_there: import_there:
{
defercheckwidth();
}
hidden_import_list '$' '$' hidden_import_list '$' '$'
{ {
resumecheckwidth();
checkimports(); checkimports();
unimportfile(); unimportfile();
} }
| LIMPORT '$' '$' hidden_import_list '$' '$' | LIMPORT '$' '$'
{ {
defercheckwidth();
}
hidden_import_list '$' '$'
{
resumecheckwidth();
checkimports(); checkimports();
} }
...@@ -251,15 +268,6 @@ import_done: ...@@ -251,15 +268,6 @@ import_done:
my->def->sym = import; my->def->sym = import;
} }
hidden_import_list:
{
defercheckwidth();
}
hidden_import_list_r
{
resumecheckwidth();
}
/* /*
* declarations * declarations
*/ */
...@@ -273,11 +281,11 @@ xdcl: ...@@ -273,11 +281,11 @@ xdcl:
{ {
if($1 != N && $1->nname != N && $1->type->thistuple == 0) if($1 != N && $1->nname != N && $1->type->thistuple == 0)
autoexport($1->nname->sym); autoexport($1->nname->sym);
$$ = N; $$ = nil;
} }
| ';' | ';'
{ {
$$ = N; $$ = nil;
} }
| error xdcl | error xdcl
{ {
...@@ -291,55 +299,55 @@ common_dcl: ...@@ -291,55 +299,55 @@ common_dcl:
if(yylast == LSEMIBRACE) if(yylast == LSEMIBRACE)
yyoptsemi(0); yyoptsemi(0);
} }
| LVAR '(' vardcl_list_r osemi ')' | LVAR '(' vardcl_list osemi ')'
{ {
$$ = rev($3); $$ = $3;
yyoptsemi(0); yyoptsemi(0);
} }
| LVAR '(' ')' | LVAR '(' ')'
{ {
$$ = N; $$ = nil;
yyoptsemi(0); yyoptsemi(0);
} }
| LCONST constdcl | LCONST constdcl
{ {
$$ = N; $$ = nil;
iota = 0; iota = 0;
lastconst = N; lastconst = nil;
} }
| LCONST '(' constdcl osemi ')' | LCONST '(' constdcl osemi ')'
{ {
$$ = nil;
iota = 0; iota = 0;
lastconst = N; lastconst = nil;
$$ = N;
yyoptsemi(0); yyoptsemi(0);
} }
| LCONST '(' constdcl ';' constdcl_list_r osemi ')' | LCONST '(' constdcl ';' constdcl_list osemi ')'
{ {
$$ = nil;
iota = 0; iota = 0;
lastconst = N; lastconst = nil;
$$ = N;
yyoptsemi(0); yyoptsemi(0);
} }
| LCONST '(' ')' | LCONST '(' ')'
{ {
$$ = N; $$ = nil;
yyoptsemi(0); yyoptsemi(0);
} }
| LTYPE typedcl | LTYPE typedcl
{ {
$$ = N; $$ = nil;
if(yylast == LSEMIBRACE) if(yylast == LSEMIBRACE)
yyoptsemi(0); yyoptsemi(0);
} }
| LTYPE '(' typedcl_list_r osemi ')' | LTYPE '(' typedcl_list osemi ')'
{ {
$$ = N; $$ = nil;
yyoptsemi(0); yyoptsemi(0);
} }
| LTYPE '(' ')' | LTYPE '(' ')'
{ {
$$ = N; $$ = nil;
yyoptsemi(0); yyoptsemi(0);
} }
...@@ -352,7 +360,7 @@ varoptsemi: ...@@ -352,7 +360,7 @@ varoptsemi:
vardcl: vardcl:
name_list type varoptsemi name_list type varoptsemi
{ {
$$ = variter($1, $2, N); $$ = variter($1, $2, nil);
} }
| name_list type varoptsemi '=' expr_list | name_list type varoptsemi '=' expr_list
{ {
...@@ -377,11 +385,11 @@ constdcl1: ...@@ -377,11 +385,11 @@ constdcl1:
constdcl constdcl
| name_list type | name_list type
{ {
constiter($1, $2, N); constiter($1, $2, nil);
} }
| name_list | name_list
{ {
constiter($1, T, N); constiter($1, T, nil);
} }
typedclname: typedclname:
...@@ -420,21 +428,27 @@ simple_stmt: ...@@ -420,21 +428,27 @@ simple_stmt:
} }
| expr_list '=' expr_list | expr_list '=' expr_list
{ {
$$ = nod(OAS, $$, $3); if($1->next == nil && $3->next == nil) {
// simple
$$ = nod(OAS, $1->n, $3->n);
break;
}
// multiple
$$ = nod(OAS2, N, N);
$$->list = $1;
$$->rlist = $3;
} }
| expr_list LCOLAS expr_list | expr_list LCOLAS expr_list
{ {
Node *top; if($3->n->op == OTYPESW) {
if($3->next != nil)
if($3->op == OTYPESW) { yyerror("expr.(type) must be alone in list");
$$ = nod(OTYPESW, $1, $3->left); else if($1->next != nil)
yyerror("argument count mismatch: %d = %d", count($1), 1);
$$ = nod(OTYPESW, $1->n, $3->n->left);
break; break;
} }
top = N; $$ = colas($1, $3);
$$ = colas($$, $3, &top);
$$ = nod(OAS, $$, $3);
$$->colas = 1;
$$->ninit = top;
} }
| expr LINC | expr LINC
{ {
...@@ -450,28 +464,31 @@ simple_stmt: ...@@ -450,28 +464,31 @@ simple_stmt:
case: case:
LCASE expr_list ':' LCASE expr_list ':'
{ {
Node *top; int e;
Node *n;
// will be converted to OCASE // will be converted to OCASE
// right will point to next case // right will point to next case
// done in casebody() // done in casebody()
top = N;
poptodcl(); poptodcl();
$$ = nod(OXCASE, N, N);
if(typeswvar != N && typeswvar->right != N) { if(typeswvar != N && typeswvar->right != N) {
int e; // type switch
if($2->op == OLITERAL && $2->val.ctype == CTNIL) { n = $2->n;
// this version in type switch case nil if($2->next != nil)
$$ = nod(OTYPESW, N, N); yyerror("type switch case cannot be list");
$$ = nod(OXCASE, $$, N); if(n->op == OLITERAL && n->val.ctype == CTNIL) {
// case nil
$$->list = list1(nod(OTYPESW, N, N));
break; break;
} }
// TODO: move
e = nerrors; e = nerrors;
walkexpr($2, Etype | Erv, &top); walkexpr(n, Etype | Erv, &$$->ninit);
if($2->op == OTYPE) { if(n->op == OTYPE) {
$$ = old2new(typeswvar->right, $2->type, &top); n = old2new(typeswvar->right, n->type, &$$->ninit);
$$ = nod(OTYPESW, $$, N); $$->list = list1(nod(OTYPESW, n, N));
$$ = nod(OXCASE, $$, N);
$$->ninit = top;
break; break;
} }
// maybe walkexpr found problems that keep // maybe walkexpr found problems that keep
...@@ -479,26 +496,25 @@ case: ...@@ -479,26 +496,25 @@ case:
// only complain if walkexpr didn't print new errors. // only complain if walkexpr didn't print new errors.
if(nerrors == e) if(nerrors == e)
yyerror("non-type case in type switch"); yyerror("non-type case in type switch");
$$ = nod(OXCASE, N, N);
$$->diag = 1; $$->diag = 1;
break; } else {
// expr switch
$$->list = $2;
} }
$$ = nod(OXCASE, $2, N); break;
} }
| LCASE type ':' | LCASE type ':'
{ {
Node *top; Node *n;
top = N; $$ = nod(OXCASE, N, N);
poptodcl(); poptodcl();
if(typeswvar == N || typeswvar->right == N) { if(typeswvar == N || typeswvar->right == N) {
yyerror("type case not in a type switch"); yyerror("type case not in a type switch");
$$ = N; n = N;
} else } else
$$ = old2new(typeswvar->right, $2, &top); n = old2new(typeswvar->right, $2, &$$->ninit);
$$ = nod(OTYPESW, $$, N); $$->list = list1(nod(OTYPESW, n, N));
$$ = nod(OXCASE, $$, N);
$$->ninit = top;
} }
| LCASE name '=' expr ':' | LCASE name '=' expr ':'
{ {
...@@ -506,21 +522,17 @@ case: ...@@ -506,21 +522,17 @@ case:
// right will point to next case // right will point to next case
// done in casebody() // done in casebody()
poptodcl(); poptodcl();
$$ = nod(OAS, $2, $4); $$ = nod(OXCASE, N, N);
$$ = nod(OXCASE, $$, N); $$->list = list1(nod(OAS, $2, $4));
} }
| LCASE name LCOLAS expr ':' | LCASE name LCOLAS expr ':'
{ {
Node *top;
// will be converted to OCASE // will be converted to OCASE
// right will point to next case // right will point to next case
// done in casebody() // done in casebody()
poptodcl(); poptodcl();
top = N; $$ = nod(OXCASE, N, N);
$$ = nod(OAS, selectas($2, $4, &top), $4); $$->list = list1(nod(OAS, selectas($2, $4, &$$->ninit), $4));
$$ = nod(OXCASE, $$, N);
$$->ninit = top;
} }
| LDEFAULT ':' | LDEFAULT ':'
{ {
...@@ -533,11 +545,9 @@ compound_stmt: ...@@ -533,11 +545,9 @@ compound_stmt:
{ {
markdcl(); markdcl();
} }
ostmt_list '}' stmt_list '}'
{ {
$$ = $3; $$ = liststmt($3);
if($$ == N)
$$ = nod(OEMPTY, N, N);
popdcl(); popdcl();
yyoptsemi(0); yyoptsemi(0);
} }
...@@ -547,27 +557,27 @@ switch_body: ...@@ -547,27 +557,27 @@ switch_body:
{ {
markdcl(); markdcl();
} }
ocaseblock_list '}' caseblock_list '}'
{ {
$$ = $3; $$ = $3;
if($$ == N)
$$ = nod(OEMPTY, N, N);
popdcl(); popdcl();
yyoptsemi(0); yyoptsemi(0);
} }
caseblock: caseblock:
case ostmt_list case stmt_list
{ {
$$ = $1; $$ = $1;
$$->nbody = $2; $$->nbody = $2;
} }
caseblock_list_r: caseblock_list:
caseblock
| caseblock_list_r caseblock
{ {
$$ = nod(OLIST, $1, $2); $$ = nil;
}
| caseblock_list caseblock
{
$$ = list($1, $2);
} }
loop_body: loop_body:
...@@ -575,23 +585,23 @@ loop_body: ...@@ -575,23 +585,23 @@ loop_body:
{ {
markdcl(); markdcl();
} }
ostmt_list '}' stmt_list '}'
{ {
$$ = $3; $$ = $3;
if($$ == N)
$$ = nod(OEMPTY, N, N);
popdcl(); popdcl();
} }
range_stmt: range_stmt:
expr_list '=' LRANGE expr expr_list '=' LRANGE expr
{ {
$$ = nod(ORANGE, $1, $4); $$ = nod(ORANGE, N, $4);
$$->list = $1;
$$->etype = 0; // := flag $$->etype = 0; // := flag
} }
| expr_list LCOLAS LRANGE expr | expr_list LCOLAS LRANGE expr
{ {
$$ = nod(ORANGE, $1, $4); $$ = nod(ORANGE, N, $4);
$$->list = $1;
$$->etype = 1; $$->etype = 1;
} }
...@@ -602,7 +612,8 @@ for_header: ...@@ -602,7 +612,8 @@ for_header:
if($5 != N && $5->colas != 0) if($5 != N && $5->colas != 0)
yyerror("cannot declare in the for-increment"); yyerror("cannot declare in the for-increment");
$$ = nod(OFOR, N, N); $$ = nod(OFOR, N, N);
$$->ninit = $1; if($1 != N)
$$->ninit = list1($1);
$$->ntest = $3; $$->ntest = $3;
$$->nincr = $5; $$->nincr = $5;
} }
...@@ -610,9 +621,7 @@ for_header: ...@@ -610,9 +621,7 @@ for_header:
{ {
// normal test // normal test
$$ = nod(OFOR, N, N); $$ = nod(OFOR, N, N);
$$->ninit = N;
$$->ntest = $1; $$->ntest = $1;
$$->nincr = N;
} }
| range_stmt | range_stmt
{ {
...@@ -623,7 +632,7 @@ for_body: ...@@ -623,7 +632,7 @@ for_body:
for_header loop_body for_header loop_body
{ {
$$ = $1; $$ = $1;
$$->nbody = list($$->nbody, $2); $$->nbody = concat($$->nbody, $2);
yyoptsemi(0); yyoptsemi(0);
} }
...@@ -643,14 +652,14 @@ if_header: ...@@ -643,14 +652,14 @@ if_header:
{ {
// test // test
$$ = nod(OIF, N, N); $$ = nod(OIF, N, N);
$$->ninit = N;
$$->ntest = $1; $$->ntest = $1;
} }
| osimple_stmt ';' osimple_stmt | osimple_stmt ';' osimple_stmt
{ {
// init ; test // init ; test
$$ = nod(OIF, N, N); $$ = nod(OIF, N, N);
$$->ninit = $1; if($1 != N)
$$->ninit = list1($1);
$$->ntest = $3; $$->ntest = $3;
} }
...@@ -680,13 +689,13 @@ switch_stmt: ...@@ -680,13 +689,13 @@ switch_stmt:
n = n->left; n = n->left;
else else
n = N; n = N;
typeswvar = nod(OLIST, typeswvar, n); typeswvar = nod(OXXX, typeswvar, n);
} }
switch_body switch_body
{ {
$$ = $3; $$ = $3;
$$->op = OSWITCH; $$->op = OSWITCH;
$$->nbody = $5; $$->list = $5;
typeswvar = typeswvar->left; typeswvar = typeswvar->left;
popdcl(); popdcl();
} }
...@@ -698,7 +707,8 @@ select_stmt: ...@@ -698,7 +707,8 @@ select_stmt:
} }
switch_body switch_body
{ {
$$ = nod(OSELECT, $3, N); $$ = nod(OSELECT, N, N);
$$->list = $3;
popdcl(); popdcl();
} }
...@@ -826,7 +836,7 @@ uexpr: ...@@ -826,7 +836,7 @@ uexpr:
/* /*
* call-like statements that * call-like statements that
* can be preceeded by 'defer' and 'go' * can be preceded by 'defer' and 'go'
*/ */
pseudocall: pseudocall:
pexpr '(' oexpr_or_type_list ')' pexpr '(' oexpr_or_type_list ')'
...@@ -834,7 +844,8 @@ pseudocall: ...@@ -834,7 +844,8 @@ pseudocall:
$$ = unsafenmagic($1, $3); $$ = unsafenmagic($1, $3);
if($$) if($$)
break; break;
$$ = nod(OCALL, $1, $3); $$ = nod(OCALL, $1, N);
$$->list = $3;
} }
pexpr: pexpr:
...@@ -878,15 +889,14 @@ pexpr: ...@@ -878,15 +889,14 @@ pexpr:
| convtype '(' expr ')' | convtype '(' expr ')'
{ {
// conversion // conversion
$$ = nod(OCALL, $1, $3); $$ = nod(OCALL, $1, N);
$$->list = list1($3);
} }
| convtype lbrace braced_keyexpr_list '}' | convtype lbrace braced_keyval_list '}'
{ {
// composite expression // composite expression
$$ = rev($3); $$ = nod(OCOMPOS, N, $1);
if($$ == N) $$->list = $3;
$$ = nod(OEMPTY, N, N);
$$ = nod(OCOMPOS, $$, $1);
// If the opening brace was an LBODY, // If the opening brace was an LBODY,
// set up for another one now that we're done. // set up for another one now that we're done.
...@@ -894,13 +904,11 @@ pexpr: ...@@ -894,13 +904,11 @@ pexpr:
if($2 == LBODY) if($2 == LBODY)
loophack = 1; loophack = 1;
} }
| pexpr '{' braced_keyexpr_list '}' | pexpr '{' braced_keyval_list '}'
{ {
// composite expression // composite expression
$$ = rev($3); $$ = nod(OCOMPOS, N, $1);
if($$ == N) $$->list = $3;
$$ = nod(OEMPTY, N, N);
$$ = nod(OCOMPOS, $$, $1);
} }
| fnliteral | fnliteral
...@@ -936,12 +944,6 @@ new_name: ...@@ -936,12 +944,6 @@ new_name:
$$ = newname($1); $$ = newname($1);
} }
new_field:
sym
{
$$ = newname($1);
}
new_type: new_type:
sym sym
{ {
...@@ -1002,9 +1004,9 @@ dotdotdot: ...@@ -1002,9 +1004,9 @@ dotdotdot:
type: type:
ntype ntype
{ {
Node *init; NodeList *init;
init = N; init = nil;
walkexpr($1, Etype, &init); walkexpr($1, Etype, &init);
// init can only be set if this was not a type; ignore // init can only be set if this was not a type; ignore
...@@ -1081,9 +1083,10 @@ chantype: ...@@ -1081,9 +1083,10 @@ chantype:
} }
structtype: structtype:
LSTRUCT '{' structdcl_list_r osemi '}' LSTRUCT '{' structdcl_list osemi '}'
{ {
$$ = nod(OTSTRUCT, rev($3), N); $$ = nod(OTSTRUCT, N, N);
$$->list = $3;
// Distinguish closing brace in struct from // Distinguish closing brace in struct from
// other closing braces by explicitly marking it. // other closing braces by explicitly marking it.
// Used above (yylast == LSEMIBRACE). // Used above (yylast == LSEMIBRACE).
...@@ -1096,9 +1099,10 @@ structtype: ...@@ -1096,9 +1099,10 @@ structtype:
} }
interfacetype: interfacetype:
LINTERFACE '{' interfacedcl_list_r osemi '}' LINTERFACE '{' interfacedcl_list osemi '}'
{ {
$$ = nod(OTINTER, rev($3), N); $$ = nod(OTINTER, N, N);
$$->list = $3;
yylast = LSEMIBRACE; yylast = LSEMIBRACE;
} }
| LINTERFACE '{' '}' | LINTERFACE '{' '}'
...@@ -1136,28 +1140,29 @@ fndcl: ...@@ -1136,28 +1140,29 @@ fndcl:
b0stack = dclstack; // mark base for fn literals b0stack = dclstack; // mark base for fn literals
$$ = nod(ODCLFUNC, N, N); $$ = nod(ODCLFUNC, N, N);
$$->nname = $1; $$->nname = $1;
if($3 == N && $5 == N) if($3 == nil && $5 == nil)
$$->nname = renameinit($1); $$->nname = renameinit($1);
$$->type = functype(N, $3, $5); $$->type = functype(N, $3, $5);
funchdr($$); funchdr($$);
} }
| '(' oarg_type_list ')' new_name '(' oarg_type_list ')' fnres | '(' oarg_type_list ')' new_name '(' oarg_type_list ')' fnres
{ {
Node *rcvr;
rcvr = $2->n;
if($2->next != nil || $2->n->op != ODCLFIELD) {
yyerror("bad receiver in method");
rcvr = N;
}
b0stack = dclstack; // mark base for fn literals b0stack = dclstack; // mark base for fn literals
$$ = nod(ODCLFUNC, N, N); $$ = nod(ODCLFUNC, N, N);
if(listcount($2) == 1) { $$->nname = $4;
$$->nname = $4; $$->nname = methodname($4, rcvr->type);
$$->nname = methodname($4, $2->type); $$->type = functype(rcvr, $6, $8);
$$->type = functype($2, $6, $8); funchdr($$);
funchdr($$); if(rcvr != N)
addmethod($4, $$->type, 1); addmethod($4, $$->type, 1);
} else {
/* declare it as a function */
yyerror("unknown method receiver");
$$->nname = $4;
$$->type = functype(N, $6, $8);
funchdr($$);
}
} }
fntype: fntype:
...@@ -1175,32 +1180,31 @@ fnlitdcl: ...@@ -1175,32 +1180,31 @@ fnlitdcl:
} }
fnliteral: fnliteral:
fnlitdcl '{' ostmt_list '}' fnlitdcl '{' stmt_list '}'
{ {
$$ = funclit1($1, $3); $$ = funclit1($1, $3);
} }
fnbody: fnbody:
'{' ostmt_list '}' {
$$ = nil;
}
| '{' stmt_list '}'
{ {
$$ = $2; $$ = $2;
if($$ == N) if($$ == nil)
$$ = nod(ORETURN, N, N); $$ = list1(nod(ORETURN, N, N));
yyoptsemi(0); yyoptsemi(0);
} }
| {
$$ = N;
}
fnres: fnres:
%prec NotParen %prec NotParen
{ {
$$ = N; $$ = nil;
} }
| non_fn_type | non_fn_type
{ {
$$ = nod(ODCLFIELD, N, $1); $$ = list1(nod(ODCLFIELD, N, $1));
$$ = cleanidlist($$);
} }
| '(' oarg_type_list ')' | '(' oarg_type_list ')'
{ {
...@@ -1213,71 +1217,64 @@ fnres: ...@@ -1213,71 +1217,64 @@ fnres:
* to conserve yacc stack. they need to * to conserve yacc stack. they need to
* be reversed to interpret correctly * be reversed to interpret correctly
*/ */
xdcl_list_r: xdcl_list:
xdcl
| xdcl_list_r xdcl
{ {
$$ = list($1, $2); $$ = nil;
}
| xdcl_list xdcl
{
$$ = concat($1, $2);
} }
vardcl_list_r: vardcl_list:
vardcl vardcl
| vardcl_list_r ';' vardcl | vardcl_list ';' vardcl
{ {
$$ = nod(OLIST, $1, $3); $$ = concat($1, $3);
} }
constdcl_list_r: constdcl_list:
constdcl1 constdcl1
| constdcl_list_r ';' constdcl1 | constdcl_list ';' constdcl1
typedcl_list_r: typedcl_list:
typedcl typedcl
| typedcl_list_r ';' typedcl | typedcl_list ';' typedcl
structdcl_list_r: structdcl_list:
structdcl structdcl
| structdcl_list ';' structdcl
{ {
$$ = cleanidlist($1); $$ = concat($1, $3);
}
| structdcl_list_r ';' structdcl
{
$$ = cleanidlist($3);
$$ = nod(OLIST, $1, $$);
} }
interfacedcl_list_r: interfacedcl_list:
interfacedcl interfacedcl
| interfacedcl_list ';' interfacedcl
{ {
$$ = cleanidlist($1); $$ = concat($1, $3);
}
| interfacedcl_list_r ';' interfacedcl
{
$$ = cleanidlist($3);
$$ = nod(OLIST, $1, $$);
} }
structdcl: structdcl:
new_field ',' structdcl name_list ntype oliteral
{
$$ = nod(ODCLFIELD, $1, N);
$$ = nod(OLIST, $$, $3);
}
| new_field ntype oliteral
{ {
$$ = nod(ODCLFIELD, $1, $2); NodeList *l;
$$->val = $3;
for(l=$1; l; l=l->next) {
l->n = nod(ODCLFIELD, l->n, $2);
l->n->val = $3;
}
} }
| embed oliteral | embed oliteral
{ {
$$ = $1; $1->val = $2;
$$->val = $2; $$ = list1($1);
} }
| '*' embed oliteral | '*' embed oliteral
{ {
$$ = $2; $2->right = nod(OIND, $2->right, N);
$$->right = nod(OIND, $$->right, N); $2->val = $3;
$$->val = $3; $$ = list1($2);
} }
packname: packname:
...@@ -1300,22 +1297,18 @@ embed: ...@@ -1300,22 +1297,18 @@ embed:
$$ = embedded($1); $$ = embedded($1);
} }
interfacedcl1: interfacedcl:
new_name ',' interfacedcl1 name_list indcl
{
$$ = nod(ODCLFIELD, $1, N);
$$ = nod(OLIST, $$, $3);
}
| new_name indcl
{ {
$$ = nod(ODCLFIELD, $1, $2); NodeList *l;
}
interfacedcl: for(l=$1; l; l=l->next)
interfacedcl1 l->n = nod(ODCLFIELD, l->n, $2);
$$ = $1;
}
| packname | packname
{ {
$$ = nod(ODCLFIELD, N, typenod(oldtype($1))); $$ = list1(nod(ODCLFIELD, N, typenod(oldtype($1))));
} }
indcl: indcl:
...@@ -1350,18 +1343,23 @@ arg_type: ...@@ -1350,18 +1343,23 @@ arg_type:
} }
| dotdotdot | dotdotdot
arg_type_list_r: arg_type_list:
arg_type arg_type
| arg_type_list_r ',' arg_type
{ {
$$ = nod(OLIST, $1, $3); $$ = list1($1);
}
| arg_type_list ',' arg_type
{
$$ = list($1, $3);
} }
arg_type_list: oarg_type_list:
arg_type_list_r {
$$ = nil;
}
| arg_type_list
{ {
$$ = rev($1); $$ = checkarglist($1);
$$ = checkarglist($$);
} }
/* /*
...@@ -1374,6 +1372,9 @@ stmt: ...@@ -1374,6 +1372,9 @@ stmt:
| simple_stmt | simple_stmt
| compound_stmt | compound_stmt
| common_dcl | common_dcl
{
$$ = liststmt($1);
}
| for_stmt | for_stmt
| switch_stmt | switch_stmt
| select_stmt | select_stmt
...@@ -1386,7 +1387,7 @@ stmt: ...@@ -1386,7 +1387,7 @@ stmt:
{ {
popdcl(); popdcl();
$$ = $1; $$ = $1;
$$->nelse = $3; $$->nelse = list1($3);
} }
| error | error
{ {
...@@ -1394,7 +1395,12 @@ stmt: ...@@ -1394,7 +1395,12 @@ stmt:
} }
| labelname ':' stmt | labelname ':' stmt
{ {
$$ = nod(OLIST, nod(OLABEL, $1, N), $3); NodeList *l;
l = list1(nod(OLABEL, $1, N));
if($3)
l = list(l, $3);
$$ = liststmt(l);
} }
| LFALL | LFALL
{ {
...@@ -1423,137 +1429,84 @@ stmt: ...@@ -1423,137 +1429,84 @@ stmt:
} }
| LRETURN oexpr_list | LRETURN oexpr_list
{ {
$$ = nod(ORETURN, $2, N); $$ = nod(ORETURN, N, N);
$$->list = $2;
} }
stmt_list_r: stmt_list:
stmt stmt
| stmt_list_r ';' stmt
{
$$ = list($1, $3);
}
name_list_r:
name
{
$$ = newname($1->sym);
}
| name_list_r ',' name
{
$$ = nod(OLIST, $1, newname($3->sym));
}
expr_list_r:
expr
| expr_list_r ',' expr
{ {
$$ = nod(OLIST, $1, $3); $$ = nil;
if($1 != N)
$$ = list1($1);
} }
| stmt_list ';' stmt
expr_or_type_list_r:
expr_or_type
| expr_or_type_list_r ',' expr_or_type
{ {
$$ = nod(OLIST, $1, $3); $$ = $1;
if($3 != N)
$$ = list($$, $3);
} }
import_stmt_list_r: name_list:
import_stmt name
| import_stmt_list_r ';' import_stmt
hidden_import_list_r:
| hidden_import_list_r hidden_import
hidden_funarg_list_r:
hidden_dcl
| hidden_funarg_list_r ',' hidden_dcl
{ {
$$ = nod(OLIST, $1, $3); $$ = list1(newname($1->sym));
} }
| name_list ',' name
hidden_funarg_list:
hidden_funarg_list_r
{ {
$$ = rev($1); $$ = list($1, newname($3->sym));
} }
hidden_structdcl_list_r: expr_list:
hidden_structdcl expr
| hidden_structdcl_list_r ';' hidden_structdcl
{ {
$$ = nod(OLIST, $1, $3); $$ = list1($1);
} }
| expr_list ',' expr
hidden_structdcl_list:
hidden_structdcl_list_r
{ {
$$ = rev($1); $$ = list($1, $3);
} }
hidden_interfacedcl_list_r: expr_or_type_list:
hidden_interfacedcl expr_or_type
| hidden_interfacedcl_list_r ';' hidden_interfacedcl
{ {
$$ = nod(OLIST, $1, $3); $$ = list1($1);
} }
| expr_or_type_list ',' expr_or_type
hidden_interfacedcl_list:
hidden_interfacedcl_list_r
{ {
$$ = rev($1); $$ = list($1, $3);
} }
/* /*
* list of combo of keyval and val * list of combo of keyval and val
*/ */
keyval_list_r: keyval_list:
keyval keyval
| expr
| keyval_list_r ',' keyval
{
$$ = nod(OLIST, $1, $3);
}
| keyval_list_r ',' expr
{ {
$$ = nod(OLIST, $1, $3); $$ = list1($1);
} }
| expr
/*
* have to spell this out using _r lists to avoid yacc conflict
*/
braced_keyexpr_list:
{ {
$$ = N; $$ = list1($1);
} }
| keyval_list_r ocomma | keyval_list ',' keyval
{ {
$$ = rev($1); $$ = list($1, $3);
} }
| keyval_list ',' expr
/*
* the one compromise of a
* non-reversed list
*/
expr_list:
expr_list_r
{ {
$$ = rev($1); $$ = list($1, $3);
} }
expr_or_type_list: braced_keyval_list:
expr_or_type_list_r
{ {
$$ = rev($1); $$ = nil;
} }
| keyval_list ocomma
name_list:
name_list_r
{ {
$$ = rev($1); $$ = $1;
} }
/* /*
* optional things * optional things
*/ */
...@@ -1571,13 +1524,13 @@ oexpr: ...@@ -1571,13 +1524,13 @@ oexpr:
oexpr_list: oexpr_list:
{ {
$$ = N; $$ = nil;
} }
| expr_list | expr_list
oexpr_or_type_list: oexpr_or_type_list:
{ {
$$ = N; $$ = nil;
} }
| expr_or_type_list | expr_or_type_list
...@@ -1587,51 +1540,21 @@ osimple_stmt: ...@@ -1587,51 +1540,21 @@ osimple_stmt:
} }
| simple_stmt | simple_stmt
ostmt_list:
stmt_list_r
{
$$ = rev($1);
}
ocaseblock_list:
{
$$ = N;
}
| caseblock_list_r
{
$$ = rev($1);
}
oxdcl_list:
{
$$ = N;
}
| xdcl_list_r
{
$$ = rev($1);
}
oarg_type_list:
{
$$ = N;
}
| arg_type_list
ohidden_funarg_list: ohidden_funarg_list:
{ {
$$ = N; $$ = nil;
} }
| hidden_funarg_list | hidden_funarg_list
ohidden_structdcl_list: ohidden_structdcl_list:
{ {
$$ = N; $$ = nil;
} }
| hidden_structdcl_list | hidden_structdcl_list
ohidden_interfacedcl_list: ohidden_interfacedcl_list:
{ {
$$ = N; $$ = nil;
} }
| hidden_interfacedcl_list | hidden_interfacedcl_list
...@@ -1678,11 +1601,11 @@ hidden_import: ...@@ -1678,11 +1601,11 @@ hidden_import:
} }
| LFUNC '(' hidden_funarg_list ')' sym '(' ohidden_funarg_list ')' ohidden_funres | LFUNC '(' hidden_funarg_list ')' sym '(' ohidden_funarg_list ')' ohidden_funres
{ {
if($3->op != ODCLFIELD) { if($3->next != nil || $3->n->op != ODCLFIELD) {
yyerror("bad receiver in method"); yyerror("bad receiver in method");
YYERROR; YYERROR;
} }
importmethod($5, functype($3, $7, $9)); importmethod($5, functype($3->n, $7, $9));
} }
hidden_type: hidden_type:
...@@ -1749,7 +1672,7 @@ hidden_type2: ...@@ -1749,7 +1672,7 @@ hidden_type2:
} }
| LFUNC '(' ohidden_funarg_list ')' ohidden_funres | LFUNC '(' ohidden_funarg_list ')' ohidden_funres
{ {
$$ = functype(N, $3, $5); $$ = functype(nil, $3, $5);
} }
hidden_dcl: hidden_dcl:
...@@ -1788,7 +1711,7 @@ hidden_interfacedcl: ...@@ -1788,7 +1711,7 @@ hidden_interfacedcl:
ohidden_funres: ohidden_funres:
{ {
$$ = N; $$ = nil;
} }
| hidden_funres | hidden_funres
...@@ -1799,8 +1722,11 @@ hidden_funres: ...@@ -1799,8 +1722,11 @@ hidden_funres:
} }
| hidden_type1 | hidden_type1
{ {
$$ = nod(ODCLFIELD, N, N); Node *n;
$$->type = $1;
n = nod(ODCLFIELD, N, N);
n->type = $1;
$$ = list1(n);
} }
hidden_constant: hidden_constant:
...@@ -1842,4 +1768,35 @@ hidden_pkg_importsym: ...@@ -1842,4 +1768,35 @@ hidden_pkg_importsym:
structpkg = $$->package; structpkg = $$->package;
} }
hidden_import_list:
| hidden_import_list hidden_import
hidden_funarg_list:
hidden_dcl
{
$$ = list1($1);
}
| hidden_funarg_list ',' hidden_dcl
{
$$ = list($1, $3);
}
hidden_structdcl_list:
hidden_structdcl
{
$$ = list1($1);
}
| hidden_structdcl_list ';' hidden_structdcl
{
$$ = list($1, $3);
}
hidden_interfacedcl_list:
hidden_interfacedcl
{
$$ = list1($1);
}
| hidden_interfacedcl_list ';' hidden_interfacedcl
{
$$ = list($1, $3);
}
...@@ -94,12 +94,6 @@ main(int argc, char *argv[]) ...@@ -94,12 +94,6 @@ main(int argc, char *argv[])
typelist = mal(sizeof(*typelist)); typelist = mal(sizeof(*typelist));
typelist->back = typelist; typelist->back = typelist;
// function field skeleton
fskel = nod(OLIST, N, nod(OLIST, N, N));
fskel->left = nod(ODCLFIELD, N, N);
fskel->right->left = nod(ODCLFIELD, N, N);
fskel->right->right = nod(ODCLFIELD, N, N);
nerrors = 0; nerrors = 0;
yyparse(); yyparse();
runifacechecks(); runifacechecks();
......
...@@ -90,10 +90,11 @@ lsort(Sig *l, int(*f)(Sig*, Sig*)) ...@@ -90,10 +90,11 @@ lsort(Sig *l, int(*f)(Sig*, Sig*))
static Type* static Type*
methodfunc(Type *f) methodfunc(Type *f)
{ {
Node *in, *out, *d; NodeList *in, *out;
Node *d;
Type *t; Type *t;
in = N; in = nil;
if(!isifacemethod(f)) { if(!isifacemethod(f)) {
d = nod(ODCLFIELD, N, N); d = nod(ODCLFIELD, N, N);
d->type = getthisx(f->type)->type->type; d->type = getthisx(f->type)->type->type;
...@@ -105,14 +106,14 @@ methodfunc(Type *f) ...@@ -105,14 +106,14 @@ methodfunc(Type *f)
in = list(in, d); in = list(in, d);
} }
out = N; out = nil;
for(t=getoutargx(f->type)->type; t; t=t->down) { for(t=getoutargx(f->type)->type; t; t=t->down) {
d = nod(ODCLFIELD, N, N); d = nod(ODCLFIELD, N, N);
d->type = t->type; d->type = t->type;
out = list(out, d); out = list(out, d);
} }
return functype(N, rev(in), rev(out)); return functype(N, in, out);
} }
/* /*
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
static struct static struct
{ {
Node* list; NodeList* list;
Node* mapname; Node* mapname;
Type* type; Type* type;
} xxx; } xxx;
...@@ -59,35 +59,25 @@ typeclass(Type *t) ...@@ -59,35 +59,25 @@ typeclass(Type *t)
} }
void void
initlin(Node* n) initlin(NodeList *l)
{ {
Node *n;
loop: for(; l; l=l->next) {
if(n == N) n = l->n;
return; initlin(n->ninit);
initlin(n->ninit); n->ninit = nil;
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
n->ninit = N;
xxx.list = list(xxx.list, n); xxx.list = list(xxx.list, n);
break; switch(n->op) {
default:
case OAS: print("o = %O\n", n->op);
n->ninit = N; break;
xxx.list = list(xxx.list, n);
break; case OCALL:
// call to mapassign1
case OLIST: case OAS:
initlin(n->left); break;
n = n->right; }
goto loop;
} }
} }
...@@ -115,23 +105,22 @@ sametmp(Node *n1, Node *n2) ...@@ -115,23 +105,22 @@ sametmp(Node *n1, Node *n2)
Node* Node*
findarg(Node *n, char *arg, char *fn) findarg(Node *n, char *arg, char *fn)
{ {
Iter param;
Node *a; Node *a;
NodeList *l;
if(n == N || n->op != OCALL || if(n == N || n->op != OCALL ||
n->left == N || n->left->sym == S || n->left == N || n->left->sym == S ||
strcmp(n->left->sym->name, fn) != 0) strcmp(n->left->sym->name, fn) != 0)
return N; return N;
a = listfirst(&param, &n->right); for(l=n->list; l; l=l->next) {
while(a != N) { a = l->n;
if(a->op == OAS && if(a->op == OAS &&
a->left != N && a->right != N && a->left != N && a->right != N &&
a->left->op == OINDREG && a->left->op == OINDREG &&
a->left->sym != S) a->left->sym != S)
if(strcmp(a->left->sym->name, arg) == 0) if(strcmp(a->left->sym->name, arg) == 0)
return a->right; return a->right;
a = listnext(&param);
} }
return N; return N;
} }
...@@ -226,7 +215,7 @@ no: ...@@ -226,7 +215,7 @@ no:
Node* Node*
mapindex(Node *n) mapindex(Node *n)
{ {
Node *index, *val, *key, *a, *b; Node *index, *val, *key, *a, *b, *r;
// pull all the primatives // pull all the primatives
key = findarg(n, "key", "mapassign1"); key = findarg(n, "key", "mapassign1");
...@@ -248,10 +237,9 @@ mapindex(Node *n) ...@@ -248,10 +237,9 @@ mapindex(Node *n)
b = nod(ODOT, b, newname(lookup("val"))); b = nod(ODOT, b, newname(lookup("val")));
b = nod(OAS, b, val); b = nod(OAS, b, val);
a = nod(OLIST, a, b); r = liststmt(list(list1(a), b));
walkexpr(a, Etop, nil); walkstmt(r);
return r;
return a;
} }
// for a copy out reference, A = B, // for a copy out reference, A = B,
...@@ -261,8 +249,8 @@ mapindex(Node *n) ...@@ -261,8 +249,8 @@ mapindex(Node *n)
void void
initsub(Node *n, Node *nam) initsub(Node *n, Node *nam)
{ {
Iter iter;
Node *r, *w, *c; Node *r, *w, *c;
NodeList *l;
int class, state; int class, state;
// we could probably get a little more // we could probably get a little more
...@@ -287,7 +275,8 @@ initsub(Node *n, Node *nam) ...@@ -287,7 +275,8 @@ initsub(Node *n, Node *nam)
return; return;
str: str:
for(r=listfirst(&iter, &xxx.list); r != N; r = listnext(&iter)) { for(l=xxx.list; l; l=l->next) {
r = l->n;
if(r->op != OAS && r->op != OEMPTY) if(r->op != OAS && r->op != OEMPTY)
continue; continue;
...@@ -326,7 +315,8 @@ str: ...@@ -326,7 +315,8 @@ str:
return; return;
ary: ary:
for(r=listfirst(&iter, &xxx.list); r != N; r = listnext(&iter)) { for(l=xxx.list; l; l=l->next) {
r = l->n;
if(r->op != OAS && r->op != OEMPTY) if(r->op != OAS && r->op != OEMPTY)
continue; continue;
...@@ -366,7 +356,8 @@ ary: ...@@ -366,7 +356,8 @@ ary:
sli: sli:
w = N; w = N;
for(r=listfirst(&iter, &xxx.list); r != N; r = listnext(&iter)) { for(l=xxx.list; l; l=l->next) {
r = l->n;
if(r->op != OAS && r->op != OEMPTY) if(r->op != OAS && r->op != OEMPTY)
continue; continue;
...@@ -411,7 +402,8 @@ sli: ...@@ -411,7 +402,8 @@ sli:
map: map:
return; return;
w = N; w = N;
for(r=listfirst(&iter, &xxx.list); r != N; r = listnext(&iter)) { for(l=xxx.list; l; l=l->next) {
r = l->n;
if(r->op == OCALL) { if(r->op == OCALL) {
// middle usage "(CALL mapassign1 key, val, map)" // middle usage "(CALL mapassign1 key, val, map)"
c = mapindex(r); c = mapindex(r);
...@@ -454,27 +446,23 @@ return; ...@@ -454,27 +446,23 @@ return;
} }
Node* NodeList*
initfix(Node* n) initfix(NodeList *l)
{ {
Iter iter;
Node *r; Node *r;
xxx.list = N; xxx.list = nil;
initlin(n); initlin(l);
xxx.list = rev(xxx.list);
if(0) if(0)
return xxx.list; return xxx.list;
// look for the copy-out reference // look for the copy-out reference
r = listfirst(&iter, &xxx.list); for(l=xxx.list; l; l=l->next) {
while(r != N) { r = l->n;
if(r->op == OAS) if(r->op == OAS)
if(inittmp(r->right)) { if(inittmp(r->right))
initsub(r->left, r->right); initsub(r->left, r->right);
}
r = listnext(&iter);
} }
return xxx.list; return xxx.list;
} }
...@@ -215,7 +215,7 @@ restrictlookup(char *name, char *pkg) ...@@ -215,7 +215,7 @@ restrictlookup(char *name, char *pkg)
yyerror("cannot refer to %s.%s", pkg, name); yyerror("cannot refer to %s.%s", pkg, name);
return pkglookup(name, pkg); return pkglookup(name, pkg);
} }
// find all the exported symbols in package opkg // find all the exported symbols in package opkg
// and make them available in the current package // and make them available in the current package
...@@ -381,16 +381,6 @@ iskeytype(Type *t) ...@@ -381,16 +381,6 @@ iskeytype(Type *t)
return algtype(t) != ANOEQ; return algtype(t) != ANOEQ;
} }
Node*
list(Node *a, Node *b)
{
if(a == N)
return b;
if(b == N)
return a;
return nod(OLIST, a, b);
}
Type* Type*
typ(int et) typ(int et)
{ {
...@@ -461,80 +451,16 @@ nodbool(int b) ...@@ -461,80 +451,16 @@ nodbool(int b)
return c; return c;
} }
Node*
rev(Node *na)
{
Node *i, *n;
/*
* since yacc wants to build lists
* stacked down on the left -
* this routine converts them to
* stack down on the right -
* in memory without recursion
*/
if(na == N || na->op != OLIST)
return na;
i = na;
for(n = na->left; n != N; n = n->left) {
if(n->op != OLIST)
break;
i->left = n->right;
n->right = i;
i = n;
}
i->left = n;
return i;
}
Node*
unrev(Node *na)
{
Node *i, *n;
/*
* this restores a reverse list
*/
if(na == N || na->op != OLIST)
return na;
i = na;
for(n = na->right; n != N; n = n->right) {
if(n->op != OLIST)
break;
i->right = n->left;
n->left = i;
i = n;
}
i->right = n;
return i;
}
/*
* na and nb are reversed lists.
* append them into one big reversed list.
*/
Node*
appendr(Node *na, Node *nb)
{
Node **l, *n;
for(l=&nb; (n=*l)->op == OLIST; l=&n->left)
;
*l = nod(OLIST, na, *l);
return nb;
}
Type* Type*
aindex(Node *b, Type *t) aindex(Node *b, Type *t)
{ {
Node *top; NodeList *init;
Type *r; Type *r;
int bound; int bound;
bound = -1; // open bound bound = -1; // open bound
top = N; init = nil;
walkexpr(b, Erv, &top); walkexpr(b, Erv, &init);
if(b != nil) { if(b != nil) {
switch(consttype(b)) { switch(consttype(b)) {
default: default:
...@@ -566,38 +492,35 @@ indent(int dep) ...@@ -566,38 +492,35 @@ indent(int dep)
} }
void void
dodump(Node *n, int dep) dodumplist(NodeList *l, int dep)
{ {
for(; l; l=l->next)
dodump(l->n, dep);
}
loop: void
dodump(Node *n, int dep)
{
if(n == N) if(n == N)
return; return;
switch(n->op) {
case OLIST:
if(n->left != N && n->left->op == OLIST)
dodump(n->left, dep+1);
else
dodump(n->left, dep);
n = n->right;
goto loop;
}
indent(dep); indent(dep);
if(dep > 10) { if(dep > 10) {
print("...\n"); print("...\n");
return; return;
} }
if(n->ninit != N) { if(n->ninit != nil) {
print("%O-init\n", n->op); print("%O-init\n", n->op);
dodump(n->ninit, dep+1); dodumplist(n->ninit, dep+1);
indent(dep); indent(dep);
} }
switch(n->op) { switch(n->op) {
default: default:
print("%N\n", n); print("%N\n", n);
dodump(n->left, dep+1);
dodump(n->right, dep+1);
break; break;
case OTYPE: case OTYPE:
...@@ -607,32 +530,32 @@ loop: ...@@ -607,32 +530,32 @@ loop:
case OIF: case OIF:
print("%O%J\n", n->op, n); print("%O%J\n", n->op, n);
dodump(n->ntest, dep+1); dodump(n->ntest, dep+1);
if(n->nbody != N) { if(n->nbody != nil) {
indent(dep); indent(dep);
print("%O-then\n", n->op); print("%O-then\n", n->op);
dodump(n->nbody, dep+1); dodumplist(n->nbody, dep+1);
} }
if(n->nelse != N) { if(n->nelse != nil) {
indent(dep); indent(dep);
print("%O-else\n", n->op); print("%O-else\n", n->op);
dodump(n->nelse, dep+1); dodumplist(n->nelse, dep+1);
} }
return; break;
case OSELECT: case OSELECT:
print("%O%J\n", n->op, n); print("%O%J\n", n->op, n);
dodump(n->nbody, dep+1); dodumplist(n->nbody, dep+1);
return; break;
case OSWITCH: case OSWITCH:
case OFOR: case OFOR:
print("%O%J\n", n->op, n); print("%O%J\n", n->op, n);
dodump(n->ntest, dep+1); dodump(n->ntest, dep+1);
if(n->nbody != N) { if(n->nbody != nil) {
indent(dep); indent(dep);
print("%O-body\n", n->op); print("%O-body\n", n->op);
dodump(n->nbody, dep+1); dodumplist(n->nbody, dep+1);
} }
if(n->nincr != N) { if(n->nincr != N) {
...@@ -640,7 +563,7 @@ loop: ...@@ -640,7 +563,7 @@ loop:
print("%O-incr\n", n->op); print("%O-incr\n", n->op);
dodump(n->nincr, dep+1); dodump(n->nincr, dep+1);
} }
return; break;
case OCASE: case OCASE:
// the right side points to label of the body // the right side points to label of the body
...@@ -649,13 +572,26 @@ loop: ...@@ -649,13 +572,26 @@ loop:
else else
print("%O%J\n", n->op, n); print("%O%J\n", n->op, n);
dodump(n->left, dep+1); dodump(n->left, dep+1);
return; break;
} }
dodump(n->left, dep+1); if(n->list != nil) {
n = n->right; indent(dep);
dep++; print("%O-list\n", n->op);
goto loop; dodumplist(n->list, dep+1);
}
if(n->rlist != nil) {
indent(dep);
print("%O-rlist\n", n->op);
dodumplist(n->rlist, dep+1);
}
}
void
dumplist(char *s, NodeList *l)
{
print("%s\n", s);
dodumplist(l, 1);
} }
void void
...@@ -687,7 +623,9 @@ opnames[] = ...@@ -687,7 +623,9 @@ opnames[] =
[OARRAY] = "ARRAY", [OARRAY] = "ARRAY",
[OASOP] = "ASOP", [OASOP] = "ASOP",
[OAS] = "AS", [OAS] = "AS",
[OAS2] = "AS2",
[OBAD] = "BAD", [OBAD] = "BAD",
[OBLOCK] = "BLOCK",
[OBREAK] = "BREAK", [OBREAK] = "BREAK",
[OCALLINTER] = "CALLINTER", [OCALLINTER] = "CALLINTER",
[OCALLMETH] = "CALLMETH", [OCALLMETH] = "CALLMETH",
...@@ -735,7 +673,6 @@ opnames[] = ...@@ -735,7 +673,6 @@ opnames[] =
[OLABEL] = "LABEL", [OLABEL] = "LABEL",
[OLEN] = "LEN", [OLEN] = "LEN",
[OLE] = "LE", [OLE] = "LE",
[OLIST] = "LIST",
[OLITERAL] = "LITERAL", [OLITERAL] = "LITERAL",
[OLSH] = "LSH", [OLSH] = "LSH",
[OLT] = "LT", [OLT] = "LT",
...@@ -1422,6 +1359,7 @@ treecopy(Node *n) ...@@ -1422,6 +1359,7 @@ treecopy(Node *n)
*m = *n; *m = *n;
m->left = treecopy(n->left); m->left = treecopy(n->left);
m->right = treecopy(n->right); m->right = treecopy(n->right);
m->list = listtreecopy(n->list);
break; break;
case OLITERAL: case OLITERAL:
...@@ -2154,34 +2092,6 @@ badtype(int o, Type *tl, Type *tr) ...@@ -2154,34 +2092,6 @@ badtype(int o, Type *tl, Type *tr)
} }
} }
/*
* this routine gets called to propagate the type
* of the last decl up to the arguments before it.
* (a,b,c int) comes out (a int, b int, c int).
*/
Node*
cleanidlist(Node *na)
{
Node *last, *n;
if(na->op != OLIST) {
if(na->op != ODCLFIELD)
fatal("cleanidlist: %O", na->op);
if(na->right == N)
fatal("cleanidlist: no type");
return na;
}
for(last=na; last->op == OLIST; last=last->right)
;
for(n=na; n->op == OLIST; n=n->right) {
n->left->right = last->right;
n->left->val = last->val;
}
return na;
}
/* /*
* iterator to walk a structure declaration * iterator to walk a structure declaration
*/ */
...@@ -2285,63 +2195,6 @@ funcnext(Iter *s) ...@@ -2285,63 +2195,6 @@ funcnext(Iter *s)
return fp; return fp;
} }
/*
* iterator to walk a list
*/
Node*
listfirst(Iter *s, Node **nn)
{
Node *n;
n = *nn;
if(n == N) {
s->done = 1;
s->an = &s->n;
s->n = N;
return N;
}
if(n->op == OLIST) {
s->done = 0;
s->n = n;
s->an = &n->left;
return n->left;
}
s->done = 1;
s->an = nn;
return n;
}
Node*
listnext(Iter *s)
{
Node *n, *r;
if(s->done) {
s->an = &s->n;
s->n = N;
return N;
}
n = s->n;
r = n->right;
if(r == N) {
s->an = &s->n;
s->n = N;
return N;
}
if(r->op == OLIST) {
s->n = r;
s->an = &r->left;
return r->left;
}
s->done = 1;
s->an = &n->right;
return n->right;
}
Type** Type**
getthis(Type *t) getthis(Type *t)
{ {
...@@ -2475,7 +2328,7 @@ staticname(Type *t) ...@@ -2475,7 +2328,7 @@ staticname(Type *t)
* return side effect-free n, appending side effects to init. * return side effect-free n, appending side effects to init.
*/ */
Node* Node*
saferef(Node *n, Node **init) saferef(Node *n, NodeList **init)
{ {
Node *l; Node *l;
Node *r; Node *r;
...@@ -2657,13 +2510,13 @@ out: ...@@ -2657,13 +2510,13 @@ out:
Node* Node*
adddot(Node *n) adddot(Node *n)
{ {
Node *top; NodeList *init;
Type *t; Type *t;
Sym *s; Sym *s;
int c, d; int c, d;
top = N; init = nil;
walkexpr(n->left, Erv, &top); walkexpr(n->left, Erv, &init);
t = n->left->type; t = n->left->type;
if(t == T) if(t == T)
goto ret; goto ret;
...@@ -2691,8 +2544,7 @@ out: ...@@ -2691,8 +2544,7 @@ out:
n->left->right = newname(dotlist[c].field->sym); n->left->right = newname(dotlist[c].field->sym);
} }
ret: ret:
if(top != N) n->ninit = concat(init, n->ninit);
n->ninit = list(top, n->ninit);
return n; return n;
} }
...@@ -2847,16 +2699,17 @@ expandmeth(Sym *s, Type *t) ...@@ -2847,16 +2699,17 @@ expandmeth(Sym *s, Type *t)
/* /*
* Given funarg struct list, return list of ODCLFIELD Node fn args. * Given funarg struct list, return list of ODCLFIELD Node fn args.
*/ */
Node* NodeList*
structargs(Type **tl, int mustname) structargs(Type **tl, int mustname)
{ {
Iter savet; Iter savet;
Node *args, *a; Node *a;
NodeList *args;
Type *t; Type *t;
char nam[100]; char nam[100];
int n; int n;
args = N; args = nil;
n = 0; n = 0;
for(t = structfirst(&savet, tl); t != T; t = structnext(&savet)) { for(t = structfirst(&savet, tl); t != T; t = structnext(&savet)) {
if(t->sym) if(t->sym)
...@@ -2869,7 +2722,6 @@ structargs(Type **tl, int mustname) ...@@ -2869,7 +2722,6 @@ structargs(Type **tl, int mustname)
a = anondcl(t->type); a = anondcl(t->type);
args = list(args, a); args = list(args, a);
} }
args = rev(args);
return args; return args;
} }
...@@ -2899,9 +2751,8 @@ structargs(Type **tl, int mustname) ...@@ -2899,9 +2751,8 @@ structargs(Type **tl, int mustname)
void void
genwrapper(Type *rcvr, Type *method, Sym *newnam) genwrapper(Type *rcvr, Type *method, Sym *newnam)
{ {
Node *this, *in, *out, *fn, *args, *call; Node *this, *fn, *call, *n;
Node *l; NodeList *l, *args, *in, *out;
Iter savel;
if(debug['r']) if(debug['r'])
print("genwrapper rcvrtype=%T method=%T newnam=%S\n", print("genwrapper rcvrtype=%T method=%T newnam=%S\n",
...@@ -2920,19 +2771,22 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam) ...@@ -2920,19 +2771,22 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam)
funchdr(fn); funchdr(fn);
// arg list // arg list
args = N; args = nil;
for(l = listfirst(&savel, &in); l; l = listnext(&savel)) for(l=in; l; l=l->next)
args = list(args, l->left); args = list(args, l->n->left);
args = rev(args);
// generate call // generate call
call = nod(OCALL, adddot(nod(ODOT, this->left, newname(method->sym))), args); call = nod(OCALL, adddot(nod(ODOT, this->left, newname(method->sym))), N);
fn->nbody = call; call->list = args;
if(method->type->outtuple > 0) fn->nbody = list1(call);
fn->nbody = nod(ORETURN, call, N); if(method->type->outtuple > 0) {
n = nod(ORETURN, N, N);
n->list = fn->nbody;
fn->nbody = list1(n);
}
if(debug['r']) if(debug['r'])
dump("genwrapper body", fn->nbody); dumplist("genwrapper body", fn->nbody);
funcbody(fn); funcbody(fn);
} }
...@@ -3137,3 +2991,71 @@ simsimtype(Type *t) ...@@ -3137,3 +2991,71 @@ simsimtype(Type *t)
return et; return et;
} }
NodeList*
concat(NodeList *a, NodeList *b)
{
if(a == nil)
return b;
if(b == nil)
return a;
a->end->next = b;
a->end = b->end;
b->end = nil;
return a;
}
NodeList*
list1(Node *n)
{
NodeList *l;
if(n == nil)
return nil;
if(n->op == OBLOCK && n->ninit == nil)
return n->list;
l = mal(sizeof *l);
l->n = n;
l->end = l;
return l;
}
NodeList*
list(NodeList *l, Node *n)
{
return concat(l, list1(n));
}
NodeList*
listtreecopy(NodeList *l)
{
NodeList *out;
out = nil;
for(; l; l=l->next)
out = list(out, treecopy(l->n));
return out;
}
Node*
liststmt(NodeList *l)
{
Node *n;
n = nod(OBLOCK, N, N);
n->list = l;
if(l)
n->lineno = l->n->lineno;
return n;
}
int
count(NodeList *l)
{
int n;
n = 0;
for(; l; l=l->next)
n++;
return n;
}
...@@ -305,33 +305,27 @@ sw3(Node *c, Type *place, int arg) ...@@ -305,33 +305,27 @@ sw3(Node *c, Type *place, int arg)
Type* Type*
walkcases(Node *sw, Type*(*call)(Node*, Type*, int arg), int arg) walkcases(Node *sw, Type*(*call)(Node*, Type*, int arg), int arg)
{ {
Iter save;
Node *n; Node *n;
NodeList *l;
Type *place; Type *place;
int32 lno; int32 lno;
lno = setlineno(sw); lno = setlineno(sw);
place = call(sw->ntest, T, arg); place = call(sw->ntest, T, arg);
n = listfirst(&save, &sw->nbody->left); for(l=sw->list; l; l=l->next) {
if(n == N || n->op == OEMPTY) n = l->n;
return T;
loop: if(n->op != OCASE)
if(n == N) { fatal("walkcases: not case %O\n", n->op);
lineno = lno;
return place;
}
if(n->op != OCASE) if(n->left != N && !n->diag) {
fatal("walkcases: not case %O\n", n->op); setlineno(n);
place = call(n->left, place, arg);
if(n->left != N && !n->diag) { }
setlineno(n);
place = call(n->left, place, arg);
} }
n = listnext(&save); lineno = lno;
goto loop; return place;
} }
Node* Node*
...@@ -352,35 +346,32 @@ newlabel(void) ...@@ -352,35 +346,32 @@ newlabel(void)
void void
casebody(Node *sw) casebody(Node *sw)
{ {
Iter save, save1; Node *os, *oc, *n, *c, *last;
Node *os, *oc, *n, *n1, *c; Node *def;
Node *cas, *stat, *def; NodeList *cas, *stat, *l, *lc;
Node *go, *br; Node *go, *br;
int32 lno; int32 lno;
lno = setlineno(sw); lno = setlineno(sw);
n = listfirst(&save, &sw->nbody); if(sw->list == nil)
if(n == N || n->op == OEMPTY) {
sw->nbody = nod(OLIST, N, N);
return; return;
}
cas = N; // cases cas = nil; // cases
stat = N; // statements stat = nil; // statements
def = N; // defaults def = N; // defaults
os = N; // last statement os = N; // last statement
oc = N; // last case oc = N; // last case
br = nod(OBREAK, N, N); br = nod(OBREAK, N, N);
for(; n != N; n = listnext(&save)) { for(l=sw->list; l; l=l->next) {
n = l->n;
lno = setlineno(n); lno = setlineno(n);
if(n->op != OXCASE) if(n->op != OXCASE)
fatal("casebody %O", n->op); fatal("casebody %O", n->op);
n->op = OCASE; n->op = OCASE;
go = nod(OGOTO, newlabel(), N); go = nod(OGOTO, newlabel(), N);
c = n->left; if(n->list == nil) {
if(c == N) {
if(def != N) if(def != N)
yyerror("more than one default case"); yyerror("more than one default case");
// reuse original default case // reuse original default case
...@@ -388,105 +379,97 @@ casebody(Node *sw) ...@@ -388,105 +379,97 @@ casebody(Node *sw)
def = n; def = n;
} }
// expand multi-valued cases if(n->list != nil && n->list->next == nil) {
for(; c!=N; c=c->right) { // one case - reuse OCASE node.
if(c->op != OLIST) { c = n->list->n;
// reuse original case n->left = c;
n->left = c; n->right = go;
n->right = go; n->list = nil;
cas = list(cas, n); cas = list(cas, n);
break; } else {
// expand multi-valued cases
for(lc=n->list; lc; lc=lc->next) {
c = lc->n;
cas = list(cas, nod(OCASE, c, go));
} }
cas = list(cas, nod(OCASE, c->left, go));
} }
stat = list(stat, nod(OLABEL, go->left, N)); stat = list(stat, nod(OLABEL, go->left, N));
stat = concat(stat, n->nbody);
os = N;
for(n1 = listfirst(&save1, &n->nbody); n1 != N; n1 = listnext(&save1)) {
os = n1;
stat = list(stat, n1);
}
// botch - shouldnt fall thru declaration // botch - shouldnt fall thru declaration
if(os != N && os->op == OXFALL) last = stat->end->n;
os->op = OFALL; if(last->op == OXFALL)
last->op = OFALL;
else else
stat = list(stat, br); stat = list(stat, br);
} }
stat = list(stat, br); stat = list(stat, br);
cas = list(cas, def); if(def)
cas = list(cas, def);
sw->nbody = nod(OLIST, rev(cas), rev(stat)); sw->list = cas;
//dump("case", sw->nbody->left); sw->nbody = stat;
//dump("stat", sw->nbody->right);
lineno = lno; lineno = lno;
} }
Case* Case*
mkcaselist(Node *sw, int arg) mkcaselist(Node *sw, int arg)
{ {
Iter save;
Node *n; Node *n;
Case *c, *c1; Case *c, *c1;
NodeList *l;
int ord; int ord;
c = C; c = C;
ord = 0; ord = 0;
n = listfirst(&save, &sw->nbody->left); for(l=sw->list; l; l=l->next) {
n = l->n;
loop: c1 = mal(sizeof(*c1));
if(n == N) c1->link = c;
goto done; c = c1;
c1 = mal(sizeof(*c1));
c1->link = c;
c = c1;
ord++; ord++;
c->ordinal = ord; c->ordinal = ord;
c->node = n; c->node = n;
if(n->left == N) { if(n->left == N) {
c->type = Tdefault; c->type = Tdefault;
goto next; continue;
}
switch(arg) {
case Stype:
c->hash = 0;
if(n->left->left == N) {
c->type = Ttypenil;
goto next;
}
if(istype(n->left->left->type, TINTER)) {
c->type = Ttypevar;
goto next;
} }
c->hash = typehash(n->left->left->type, 1, 0); switch(arg) {
c->type = Ttypeconst; case Stype:
goto next; c->hash = 0;
if(n->left->left == N) {
c->type = Ttypenil;
continue;
}
if(istype(n->left->left->type, TINTER)) {
c->type = Ttypevar;
continue;
}
case Snorm: c->hash = typehash(n->left->left->type, 1, 0);
case Strue: c->type = Ttypeconst;
case Sfalse: continue;
c->type = Texprvar;
switch(consttype(n->left)) { case Snorm:
case CTFLT: case Strue:
case CTINT: case Sfalse:
case CTSTR: c->type = Texprvar;
c->type = Texprconst; switch(consttype(n->left)) {
case CTFLT:
case CTINT:
case CTSTR:
c->type = Texprconst;
}
continue;
} }
goto next;
} }
next:
n = listnext(&save);
goto loop;
done:
if(c == C) if(c == C)
return C; return C;
...@@ -528,12 +511,12 @@ static Node* exprname; ...@@ -528,12 +511,12 @@ static Node* exprname;
Node* Node*
exprbsw(Case *c0, int ncase, int arg) exprbsw(Case *c0, int ncase, int arg)
{ {
Node *cas; NodeList *cas;
Node *a, *n; Node *a, *n;
Case *c; Case *c;
int i, half, lno; int i, half, lno;
cas = N; cas = nil;
if(ncase < Ncase) { if(ncase < Ncase) {
for(i=0; i<ncase; i++) { for(i=0; i<ncase; i++) {
n = c0->node; n = c0->node;
...@@ -543,19 +526,19 @@ exprbsw(Case *c0, int ncase, int arg) ...@@ -543,19 +526,19 @@ exprbsw(Case *c0, int ncase, int arg)
case Strue: case Strue:
a = nod(OIF, N, N); a = nod(OIF, N, N);
a->ntest = n->left; // if val a->ntest = n->left; // if val
a->nbody = n->right; // then goto l a->nbody = list1(n->right); // then goto l
break; break;
case Sfalse: case Sfalse:
a = nod(OIF, N, N); a = nod(OIF, N, N);
a->ntest = nod(ONOT, n->left, N); // if !val a->ntest = nod(ONOT, n->left, N); // if !val
a->nbody = n->right; // then goto l a->nbody = list1(n->right); // then goto l
break; break;
default: default:
a = nod(OIF, N, N); a = nod(OIF, N, N);
a->ntest = nod(OEQ, exprname, n->left); // if name == val a->ntest = nod(OEQ, exprname, n->left); // if name == val
a->nbody = n->right; // then goto l a->nbody = list1(n->right); // then goto l
break; break;
} }
...@@ -563,7 +546,7 @@ exprbsw(Case *c0, int ncase, int arg) ...@@ -563,7 +546,7 @@ exprbsw(Case *c0, int ncase, int arg)
c0 = c0->link; c0 = c0->link;
lineno = lno; lineno = lno;
} }
return cas; return liststmt(cas);
} }
// find the middle and recur // find the middle and recur
...@@ -573,8 +556,8 @@ exprbsw(Case *c0, int ncase, int arg) ...@@ -573,8 +556,8 @@ exprbsw(Case *c0, int ncase, int arg)
c = c->link; c = c->link;
a = nod(OIF, N, N); a = nod(OIF, N, N);
a->ntest = nod(OLE, exprname, c->node->left); a->ntest = nod(OLE, exprname, c->node->left);
a->nbody = exprbsw(c0, half, arg); a->nbody = list1(exprbsw(c0, half, arg));
a->nelse = exprbsw(c->link, ncase-half, arg); a->nelse = list1(exprbsw(c->link, ncase-half, arg));
return a; return a;
} }
...@@ -585,7 +568,8 @@ exprbsw(Case *c0, int ncase, int arg) ...@@ -585,7 +568,8 @@ exprbsw(Case *c0, int ncase, int arg)
void void
exprswitch(Node *sw) exprswitch(Node *sw)
{ {
Node *def, *cas; Node *def;
NodeList *cas;
Node *a; Node *a;
Case *c0, *c, *c1; Case *c0, *c, *c1;
Type *t; Type *t;
...@@ -620,11 +604,11 @@ exprswitch(Node *sw) ...@@ -620,11 +604,11 @@ exprswitch(Node *sw)
* convert the switch into OIF statements * convert the switch into OIF statements
*/ */
exprname = N; exprname = N;
cas = N; cas = nil;
if(arg != Strue && arg != Sfalse) { if(arg != Strue && arg != Sfalse) {
exprname = nod(OXXX, N, N); exprname = nod(OXXX, N, N);
tempname(exprname, sw->ntest->type); tempname(exprname, sw->ntest->type);
cas = nod(OAS, exprname, sw->ntest); cas = list1(nod(OAS, exprname, sw->ntest));
} }
c0 = mkcaselist(sw, arg); c0 = mkcaselist(sw, arg);
...@@ -638,8 +622,9 @@ exprswitch(Node *sw) ...@@ -638,8 +622,9 @@ exprswitch(Node *sw)
loop: loop:
if(c0 == C) { if(c0 == C) {
cas = list(cas, def); cas = list(cas, def);
sw->nbody->left = rev(cas); sw->nbody = concat(cas, sw->nbody);
walkstmt(sw->nbody); sw->list = nil;
walkstmtlist(sw->nbody);
return; return;
} }
...@@ -680,34 +665,36 @@ static Node* boolname; ...@@ -680,34 +665,36 @@ static Node* boolname;
Node* Node*
typeone(Node *t) typeone(Node *t)
{ {
Node *a, *b, *dcl; NodeList *init;
Node *a, *b, *var;
a = t->left->left; // var
dcl = nod(ODCL, a, N);
a = nod(OLIST, a, boolname); // var,bool var = t->left->left;
init = list1(nod(ODCL, var, N));
a = nod(OAS2, N, N);
a->list = list(list1(var), boolname); // var,bool =
b = nod(ODOTTYPE, facename, N); b = nod(ODOTTYPE, facename, N);
b->type = t->left->left->type; // interface.(type) b->type = t->left->left->type; // interface.(type)
a->rlist = list1(b);
a = nod(OAS, a, b); // var,bool = interface.(type) init = list(init, a);
b = nod(OIF, N, N); b = nod(OIF, N, N);
b->ntest = boolname; b->ntest = boolname;
b->nbody = t->right; // if bool { goto l } b->nbody = list1(t->right); // if bool { goto l }
return list(list(dcl, a), b); a = liststmt(list(init, b));
return a;
} }
Node* Node*
typebsw(Case *c0, int ncase) typebsw(Case *c0, int ncase)
{ {
Node *cas; NodeList *cas;
Node *a, *n; Node *a, *n;
Case *c; Case *c;
int i, half; int i, half;
Val v; Val v;
cas = N; cas = nil;
if(ncase < Ncase) { if(ncase < Ncase) {
for(i=0; i<ncase; i++) { for(i=0; i<ncase; i++) {
...@@ -719,7 +706,7 @@ typebsw(Case *c0, int ncase) ...@@ -719,7 +706,7 @@ typebsw(Case *c0, int ncase)
v.ctype = CTNIL; v.ctype = CTNIL;
a = nod(OIF, N, N); a = nod(OIF, N, N);
a->ntest = nod(OEQ, facename, nodlit(v)); a->ntest = nod(OEQ, facename, nodlit(v));
a->nbody = n->right; // if i==nil { goto l } a->nbody = list1(n->right); // if i==nil { goto l }
cas = list(cas, a); cas = list(cas, a);
break; break;
...@@ -731,13 +718,13 @@ typebsw(Case *c0, int ncase) ...@@ -731,13 +718,13 @@ typebsw(Case *c0, int ncase)
case Ttypeconst: case Ttypeconst:
a = nod(OIF, N, N); a = nod(OIF, N, N);
a->ntest = nod(OEQ, hashname, nodintconst(c0->hash)); a->ntest = nod(OEQ, hashname, nodintconst(c0->hash));
a->nbody = rev(typeone(n)); a->nbody = list1(typeone(n));
cas = list(cas, a); cas = list(cas, a);
break; break;
} }
c0 = c0->link; c0 = c0->link;
} }
return cas; return liststmt(cas);
} }
// find the middle and recur // find the middle and recur
...@@ -747,8 +734,8 @@ typebsw(Case *c0, int ncase) ...@@ -747,8 +734,8 @@ typebsw(Case *c0, int ncase)
c = c->link; c = c->link;
a = nod(OIF, N, N); a = nod(OIF, N, N);
a->ntest = nod(OLE, hashname, nodintconst(c->hash)); a->ntest = nod(OLE, hashname, nodintconst(c->hash));
a->nbody = typebsw(c0, half); a->nbody = list1(typebsw(c0, half));
a->nelse = typebsw(c->link, ncase-half); a->nelse = list1(typebsw(c->link, ncase-half));
return a; return a;
} }
...@@ -760,7 +747,8 @@ typebsw(Case *c0, int ncase) ...@@ -760,7 +747,8 @@ typebsw(Case *c0, int ncase)
void void
typeswitch(Node *sw) typeswitch(Node *sw)
{ {
Node *cas, *def; Node *def;
NodeList *cas;
Node *a; Node *a;
Case *c, *c0, *c1; Case *c, *c0, *c1;
int ncase; int ncase;
...@@ -779,7 +767,7 @@ typeswitch(Node *sw) ...@@ -779,7 +767,7 @@ typeswitch(Node *sw)
return; return;
} }
walkcases(sw, sw0, Stype); walkcases(sw, sw0, Stype);
cas = N; cas = nil;
/* /*
* predeclare temporary variables * predeclare temporary variables
...@@ -802,7 +790,8 @@ typeswitch(Node *sw) ...@@ -802,7 +790,8 @@ typeswitch(Node *sw)
else else
a = syslook("ifacethash", 1); a = syslook("ifacethash", 1);
argtype(a, t); argtype(a, t);
a = nod(OCALL, a, facename); a = nod(OCALL, a, N);
a->list = list1(facename);
a = nod(OAS, hashname, a); a = nod(OAS, hashname, a);
cas = list(cas, a); cas = list(cas, a);
...@@ -817,8 +806,9 @@ typeswitch(Node *sw) ...@@ -817,8 +806,9 @@ typeswitch(Node *sw)
loop: loop:
if(c0 == C) { if(c0 == C) {
cas = list(cas, def); cas = list(cas, def);
sw->nbody->left = rev(cas); sw->nbody = concat(cas, sw->nbody);
walkstmt(sw->nbody); sw->list = nil;
walkstmtlist(sw->nbody);
return; return;
} }
...@@ -860,7 +850,7 @@ walkswitch(Node *sw) ...@@ -860,7 +850,7 @@ walkswitch(Node *sw)
* cases have OGOTO into statements. * cases have OGOTO into statements.
* both have inserted OBREAK statements * both have inserted OBREAK statements
*/ */
walkstmt(sw->ninit); walkstmtlist(sw->ninit);
if(sw->ntest == N) if(sw->ntest == N)
sw->ntest = nodbool(1); sw->ntest = nodbool(1);
casebody(sw); casebody(sw);
......
...@@ -67,7 +67,6 @@ func mapiter2(hiter *any) (key any, val any); ...@@ -67,7 +67,6 @@ func mapiter2(hiter *any) (key any, val any);
func newchan(elemsize int, elemalg int, hint int) (hchan chan any); func newchan(elemsize int, elemalg int, hint int) (hchan chan any);
func chanrecv1(hchan <-chan any) (elem any); func chanrecv1(hchan <-chan any) (elem any);
func chanrecv2(hchan <-chan any) (elem any, pres bool); func chanrecv2(hchan <-chan any) (elem any, pres bool);
func chanrecv3(hchan <-chan any, elem *any) (pres bool);
func chansend1(hchan chan<- any, elem any); func chansend1(hchan chan<- any, elem any);
func chansend2(hchan chan<- any, elem any) (pres bool); func chansend2(hchan chan<- any, elem any) (pres bool);
func closechan(hchan any); func closechan(hchan any);
......
...@@ -30,22 +30,23 @@ enum ...@@ -30,22 +30,23 @@ enum
// without an undcontitional RETURN // without an undcontitional RETURN
// this is hard, so it is conservative // this is hard, so it is conservative
int int
walkret(Node *n) walkret(NodeList *l)
{ {
Node *n;
loop: loop:
if(n != N) while(l && l->next)
switch(n->op) { l = l->next;
case OLIST: if(l == nil)
if(n->right == N) { return 1;
n = n->left;
goto loop;
}
n = n->right;
goto loop;
// at this point, we have the last // at this point, we have the last
// statement of the function // statement of the function
n = l->n;
switch(n->op) {
case OBLOCK:
l = n->list;
goto loop;
case OGOTO: case OGOTO:
case ORETURN: case ORETURN:
...@@ -75,25 +76,25 @@ walk(Node *fn) ...@@ -75,25 +76,25 @@ walk(Node *fn)
curfn = fn; curfn = fn;
if(debug['W']) { if(debug['W']) {
snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym); snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
dump(s, curfn->nbody); dumplist(s, curfn->nbody);
} }
if(curfn->type->outtuple) if(curfn->type->outtuple)
if(walkret(curfn->nbody)) if(walkret(curfn->nbody))
yyerror("function ends without a return statement"); yyerror("function ends without a return statement");
walkstmt(curfn->nbody); walkstmtlist(curfn->nbody);
if(debug['W']) { if(debug['W']) {
snprint(s, sizeof(s), "after walk %S", curfn->nname->sym); snprint(s, sizeof(s), "after walk %S", curfn->nname->sym);
dump(s, curfn->nbody); dumplist(s, curfn->nbody);
} }
heapmoves(); heapmoves();
if(debug['W'] && curfn->enter != N) { if(debug['W'] && curfn->enter != nil) {
snprint(s, sizeof(s), "enter %S", curfn->nname->sym); snprint(s, sizeof(s), "enter %S", curfn->nname->sym);
dump(s, curfn->enter); dumplist(s, curfn->enter);
} }
} }
void void
gettype(Node *n, Node **init) gettype(Node *n, NodeList **init)
{ {
if(debug['W']) if(debug['W'])
dump("\nbefore gettype", n); dump("\nbefore gettype", n);
...@@ -102,16 +103,20 @@ gettype(Node *n, Node **init) ...@@ -102,16 +103,20 @@ gettype(Node *n, Node **init)
dump("after gettype", n); dump("after gettype", n);
} }
void
walkstmtlist(NodeList *l)
{
for(; l; l=l->next)
walkstmt(l->n);
}
void void
walkstmt(Node *n) walkstmt(Node *n)
{ {
Node *init, *l; NodeList *init;
NodeList *ll;
int lno; int lno;
while(n != N && n->op == OLIST) {
walkstmt(n->left);
n = n->right;
}
if(n == N) if(n == N)
return; return;
...@@ -121,13 +126,14 @@ walkstmt(Node *n) ...@@ -121,13 +126,14 @@ walkstmt(Node *n)
switch(n->op) { switch(n->op) {
default: default:
if(n->op == ONAME) if(n->op == ONAME)
yyerror("walkstmt: %S not a top level statement", n->sym); yyerror("%S is not a top level statement", n->sym);
else else
yyerror("walkstmt: %O not a top level statement", n->op); yyerror("%O is not a top level statement", n->op);
break; break;
case OASOP: case OASOP:
case OAS: case OAS:
case OAS2:
case OCLOSE: case OCLOSE:
case OCLOSED: case OCLOSED:
case OCALLMETH: case OCALLMETH:
...@@ -140,9 +146,9 @@ walkstmt(Node *n) ...@@ -140,9 +146,9 @@ walkstmt(Node *n)
case OPANIC: case OPANIC:
case OPANICN: case OPANICN:
case OEMPTY: case OEMPTY:
init = N; init = nil;
walkexpr(n, Etop, &init); walkexpr(n, Etop, &init);
n->ninit = list(n->ninit, init); n->ninit = concat(n->ninit, init);
break; break;
case OBREAK: case OBREAK:
...@@ -153,6 +159,10 @@ walkstmt(Node *n) ...@@ -153,6 +159,10 @@ walkstmt(Node *n)
case OLABEL: case OLABEL:
break; break;
case OBLOCK:
walkstmtlist(n->list);
break;
case OXCASE: case OXCASE:
yyerror("case statement out of place"); yyerror("case statement out of place");
n->op = OCASE; n->op = OCASE;
...@@ -166,17 +176,17 @@ walkstmt(Node *n) ...@@ -166,17 +176,17 @@ walkstmt(Node *n)
break; break;
case OFOR: case OFOR:
walkstmt(n->ninit); walkstmtlist(n->ninit);
walkbool(n->ntest); walkbool(n->ntest);
walkstmt(n->nincr); walkstmt(n->nincr);
walkstmt(n->nbody); walkstmtlist(n->nbody);
break; break;
case OIF: case OIF:
walkstmt(n->ninit); walkstmtlist(n->ninit);
walkbool(n->ntest); walkbool(n->ntest);
walkstmt(n->nbody); walkstmtlist(n->nbody);
walkstmt(n->nelse); walkstmtlist(n->nelse);
break; break;
case OPROC: case OPROC:
...@@ -184,14 +194,13 @@ walkstmt(Node *n) ...@@ -184,14 +194,13 @@ walkstmt(Node *n)
break; break;
case ORETURN: case ORETURN:
walkexpr(n->left, Erv, &n->ninit); walkexprlist(n->list, Erv, &n->ninit);
if(curfn->type->outnamed && n->left == N) { if(curfn->type->outnamed && n->list == nil) {
// print("special return\n"); // print("special return\n");
break; break;
} }
l = ascompatte(n->op, getoutarg(curfn->type), &n->left, 1, &n->ninit); ll = ascompatte(n->op, getoutarg(curfn->type), n->list, 1, &n->ninit);
if(l != N) n->list = reorder4(ll);
n->left = reorder4(l);
break; break;
case OSELECT: case OSELECT:
...@@ -244,10 +253,19 @@ implicitstar(Node **nn) ...@@ -244,10 +253,19 @@ implicitstar(Node **nn)
* compile-time constants are evaluated. * compile-time constants are evaluated.
* complex side effects like statements are appended to init * complex side effects like statements are appended to init
*/ */
void void
walkexpr(Node *n, int top, Node **init) walkexprlist(NodeList *l, int top, NodeList **init)
{
for(; l; l=l->next)
walkexpr(l->n, top, init);
}
void
walkexpr(Node *n, int top, NodeList **init)
{ {
Node *r, *l; Node *r, *l;
NodeList *ll, *lr;
Type *t; Type *t;
Sym *s; Sym *s;
int et, cl, cr, typeok; int et, cl, cr, typeok;
...@@ -265,7 +283,7 @@ loop: ...@@ -265,7 +283,7 @@ loop:
setlineno(n); setlineno(n);
if(debug['w'] > 1 && top == Etop && n->op != OLIST) if(debug['w'] > 1 && top == Etop)
dump("walk-before", n); dump("walk-before", n);
reswitch: reswitch:
...@@ -340,16 +358,15 @@ reswitch: ...@@ -340,16 +358,15 @@ reswitch:
case OTSTRUCT: case OTSTRUCT:
n->op = OTYPE; n->op = OTYPE;
n->type = dostruct(n->left, TSTRUCT); n->type = dostruct(n->list, TSTRUCT);
goto ret; goto ret;
case OTINTER: case OTINTER:
n->op = OTYPE; n->op = OTYPE;
n->type = dostruct(n->left, TINTER); n->type = dostruct(n->list, TINTER);
n->type = sortinter(n->type); n->type = sortinter(n->type);
goto ret; goto ret;
case OLIST:
case OKEY: case OKEY:
walkexpr(n->left, top | typeok, init); walkexpr(n->left, top | typeok, init);
n = n->right; n = n->right;
...@@ -358,29 +375,29 @@ reswitch: ...@@ -358,29 +375,29 @@ reswitch:
case OPRINT: case OPRINT:
if(top != Etop) if(top != Etop)
goto nottop; goto nottop;
walkexpr(n->left, Erv, init); walkexprlist(n->list, Erv, init);
indir(n, prcompat(n->left, 0)); indir(n, prcompat(n->list, 0, 0));
goto ret; goto ret;
case OPRINTN: case OPRINTN:
if(top != Etop) if(top != Etop)
goto nottop; goto nottop;
walkexpr(n->left, Erv, init); walkexprlist(n->list, Erv, init);
indir(n, prcompat(n->left, 1)); indir(n, prcompat(n->list, 1, 0));
goto ret; goto ret;
case OPANIC: case OPANIC:
if(top != Etop) if(top != Etop)
goto nottop; goto nottop;
walkexpr(n->left, Erv, init); walkexprlist(n->list, Erv, init);
indir(n, list(prcompat(n->left, 0), nodpanic(n->lineno))); indir(n, prcompat(n->list, 0, 1));
goto ret; goto ret;
case OPANICN: case OPANICN:
if(top != Etop) if(top != Etop)
goto nottop; goto nottop;
walkexpr(n->left, Erv, init); walkexprlist(n->list, Erv, init);
indir(n, list(prcompat(n->left, 2), nodpanic(n->lineno))); indir(n, prcompat(n->list, 2, 1));
goto ret; goto ret;
case OLITERAL: case OLITERAL:
...@@ -433,8 +450,7 @@ reswitch: ...@@ -433,8 +450,7 @@ reswitch:
if(n->left->op == ONAME && n->left->etype != 0) { if(n->left->op == ONAME && n->left->etype != 0) {
// builtin OLEN, OCAP, etc. // builtin OLEN, OCAP, etc.
n->op = n->left->etype; n->op = n->left->etype;
n->left = n->right; n->left = N;
n->right = N;
goto reswitch; goto reswitch;
} }
...@@ -455,8 +471,16 @@ reswitch: ...@@ -455,8 +471,16 @@ reswitch:
goto nottop; goto nottop;
// turn CALL(type, arg) into CONV(arg) w/ type. // turn CALL(type, arg) into CONV(arg) w/ type.
n->type = n->left->type; n->type = n->left->type;
n->left = n->right; if(n->list == nil) {
n->right = N; yyerror("missing argument in type conversion");
goto ret;
}
if(n->list->next != nil) {
yyerror("too many arguments in type conversion");
goto ret;
}
n->left = n->list->n;
n->list = nil;
goto reswitch; goto reswitch;
} }
...@@ -481,36 +505,36 @@ reswitch: ...@@ -481,36 +505,36 @@ reswitch:
break; break;
} }
walkexpr(n->right, Erv, init); walkexprlist(n->list, Erv, init);
switch(n->op) { switch(n->op) {
default: default:
fatal("walk: op: %O", n->op); fatal("walk: op: %O", n->op);
case OCALLINTER: case OCALLINTER:
l = ascompatte(n->op, getinarg(t), &n->right, 0, init); ll = ascompatte(n->op, getinarg(t), n->list, 0, init);
n->right = reorder1(l); n->list = reorder1(ll);
break; break;
case OCALL: case OCALL:
l = ascompatte(n->op, getinarg(t), &n->right, 0, init); ll = ascompatte(n->op, getinarg(t), n->list, 0, init);
n->right = reorder1(l); n->list = reorder1(ll);
if(isselect(n)) { if(isselect(n)) {
// clear output bool - special prob with selectsend // clear output bool - special prob with selectsend
Node *b; Node *b;
b = nodbool(0); b = nodbool(0);
r = ascompatte(n->op, getoutarg(t), &b, 0, init); lr = ascompatte(n->op, getoutarg(t), list1(b), 0, init);
n->right = list(n->right, r); n->list = concat(n->list, lr);
} }
break; break;
case OCALLMETH: case OCALLMETH:
l = ascompatte(n->op, getinarg(t), &n->right, 0, init); ll = ascompatte(n->op, getinarg(t), n->list, 0, init);
r = ascompatte(n->op, getthis(t), &n->left->left, 0, init); lr = ascompatte(n->op, getthis(t), list1(n->left->left), 0, init);
l = list(r, l); ll = concat(ll, lr);
n->left->left = N; n->left->left = N;
ullmancalc(n->left); ullmancalc(n->left);
n->right = reorder1(l); n->list = reorder1(ll);
break; break;
} }
goto ret; goto ret;
...@@ -518,30 +542,41 @@ reswitch: ...@@ -518,30 +542,41 @@ reswitch:
case OAS: case OAS:
if(top != Etop) if(top != Etop)
goto nottop; goto nottop;
*init = concat(*init, n->ninit);
*init = list(*init, n->ninit); n->ninit = nil;
n->ninit = N;
l = n->left; l = n->left;
r = n->right; r = n->right;
walkexpr(l, Elv, init); walkexpr(l, Elv, init);
if(l == N || r == N) if(l == N || r == N)
goto ret; goto ret;
walkexpr(r, Erv, init);
indir(n, ascompatee1(n->op, n->left, n->right, init));
goto ret;
cl = listcount(l); case OAS2:
cr = listcount(r); if(top != Etop)
goto nottop;
*init = concat(*init, n->ninit);
n->ninit = nil;
walkexprlist(n->list, Elv, init);
cl = count(n->list);
cr = count(n->rlist);
if(cl == cr) { if(cl == cr) {
simpleas: multias:
walkexpr(r, Erv, init); walkexprlist(n->rlist, Erv, init);
l = ascompatee(n->op, &n->left, &n->right, init); ll = ascompatee(OAS, n->list, n->rlist, init);
if(l != N) ll = reorder3(ll);
indir(n, reorder3(l)); indir(n, liststmt(ll));
goto ret; goto ret;
} }
switch(r->op) { l = n->list->n;
r = n->rlist->n;
// count mismatch - special cases
switch(r->op) {
case OCALLMETH: case OCALLMETH:
case OCALLINTER: case OCALLINTER:
case OCALL: case OCALL:
...@@ -550,9 +585,8 @@ reswitch: ...@@ -550,9 +585,8 @@ reswitch:
walkexpr(r, Erv, init); walkexpr(r, Erv, init);
if(r->type == T || r->type->etype != TSTRUCT) if(r->type == T || r->type->etype != TSTRUCT)
break; break;
l = ascompatet(n->op, &n->left, &r->type, 0, init); ll = ascompatet(n->op, n->list, &r->type, 0, init);
if(l != N) indir(n, liststmt(concat(list1(r), ll)));
indir(n, list(r, l));
goto ret; goto ret;
} }
break; break;
...@@ -596,11 +630,11 @@ reswitch: ...@@ -596,11 +630,11 @@ reswitch:
switch(et) { switch(et) {
case I2Isame: case I2Isame:
case E2Esame: case E2Esame:
n->right = nod(OLIST, r->left, nodbool(1)); n->rlist = list(list1(r->left), nodbool(1));
goto simpleas; goto multias;
case I2E: case I2E:
n->right = nod(OLIST, n->right, nodbool(1)); n->list = list(list1(n->right), nodbool(1));
goto simpleas; goto multias;
case I2T: case I2T:
et = I2T2; et = I2T2;
break; break;
...@@ -620,9 +654,8 @@ reswitch: ...@@ -620,9 +654,8 @@ reswitch:
if(et == Inone) if(et == Inone)
break; break;
r = ifacecvt(r->type, r->left, et); r = ifacecvt(r->type, r->left, et);
l = ascompatet(n->op, &n->left, &r->type, 0, init); ll = ascompatet(n->op, n->list, &r->type, 0, init);
if(l != N) indir(n, liststmt(concat(list1(r), ll)));
indir(n, list(r, l));
goto ret; goto ret;
} }
break; break;
...@@ -675,10 +708,6 @@ reswitch: ...@@ -675,10 +708,6 @@ reswitch:
if(t == T) if(t == T)
goto ret; goto ret;
l = n->left;
if(l == N)
goto ret;
switch(t->etype) { switch(t->etype) {
default: default:
yyerror("invalid type for composite literal: %T", t); yyerror("invalid type for composite literal: %T", t);
...@@ -830,11 +859,16 @@ reswitch: ...@@ -830,11 +859,16 @@ reswitch:
case OLEN: case OLEN:
if(top != Erv) if(top != Erv)
goto nottop; goto nottop;
walkexpr(n->left, Erv, init);
if(n->left == N) { if(n->left == N) {
yyerror("missing argument to len"); if(n->list == nil) {
goto ret; yyerror("missing argument to len");
goto ret;
}
if(n->list->next)
yyerror("too many arguments to len");
n->left = n->list->n;
} }
walkexpr(n->left, Erv, init);
defaultlit(n->left, T); defaultlit(n->left, T);
implicitstar(&n->left); implicitstar(&n->left);
t = n->left->type; t = n->left->type;
...@@ -860,6 +894,15 @@ reswitch: ...@@ -860,6 +894,15 @@ reswitch:
case OCAP: case OCAP:
if(top != Erv) if(top != Erv)
goto nottop; goto nottop;
if(n->left == N) {
if(n->list == nil) {
yyerror("missing argument to cap");
goto ret;
}
if(n->list->next)
yyerror("too many arguments to cap");
n->left = n->list->n;
}
walkexpr(n->left, Erv, init); walkexpr(n->left, Erv, init);
defaultlit(n->left, T); defaultlit(n->left, T);
implicitstar(&n->left); implicitstar(&n->left);
...@@ -1095,24 +1138,21 @@ reswitch: ...@@ -1095,24 +1138,21 @@ reswitch:
case OMAKE: case OMAKE:
if(top != Erv) if(top != Erv)
goto nottop; goto nottop;
l = n->left;
if(l == N) {
yyerror("missing argument to make");
goto ret;
}
indir(n, makecompat(n)); indir(n, makecompat(n));
goto ret; goto ret;
case ONEW: case ONEW:
if(top != Erv) if(top != Erv)
goto nottop; goto nottop;
l = n->left; if(n->list == nil) {
walkexpr(l, Etype, init);
if(l == N)
yyerror("missing argument to new"); yyerror("missing argument to new");
else if(n->right != N) goto ret;
}
l = n->list->n;
if(n->list->next)
yyerror("too many arguments to new"); yyerror("too many arguments to new");
else if((t = l->type) == T) walkexpr(l, Etype, init);
if((t = l->type) == T)
; ;
else else
indir(n, callnew(t)); indir(n, callnew(t));
...@@ -1234,7 +1274,8 @@ reswitch: ...@@ -1234,7 +1274,8 @@ reswitch:
n->left->type = types[et]; n->left->type = types[et];
n->right = nod(OCONV, n->right, N); n->right = nod(OCONV, n->right, N);
n->right->type = types[et]; n->right->type = types[et];
r = nod(OCALL, l, list(n->left, n->right)); r = nod(OCALL, l, N);
r->list = list(list1(n->left), n->right);
r = nod(OCONV, r, N); r = nod(OCONV, r, N);
r->type = n->left->left->type; r->type = n->left->left->type;
walkexpr(r, Erv, init); walkexpr(r, Erv, init);
...@@ -1331,7 +1372,7 @@ walkbool(Node *n) ...@@ -1331,7 +1372,7 @@ walkbool(Node *n)
} }
void void
walkdottype(Node *n, Node **init) walkdottype(Node *n, NodeList **init)
{ {
walkexpr(n->left, Erv, init); walkexpr(n->left, Erv, init);
if(n->left == N) if(n->left == N)
...@@ -1347,7 +1388,7 @@ walkdottype(Node *n, Node **init) ...@@ -1347,7 +1388,7 @@ walkdottype(Node *n, Node **init)
} }
void void
walkconv(Node *n, Node **init) walkconv(Node *n, NodeList **init)
{ {
int et; int et;
char *what; char *what;
...@@ -1475,20 +1516,18 @@ bad: ...@@ -1475,20 +1516,18 @@ bad:
what = "conversion"; what = "conversion";
if(l->type != T) if(l->type != T)
yyerror("invalid %s: %T to %T", what, l->type, t); yyerror("invalid %s: %T to %T", what, l->type, t);
else
if(n->left->op == OLIST)
yyerror("invalid type for composite literal: %T", t);
} }
Node* Node*
selcase(Node *n, Node *var, Node **init) selcase(Node *n, Node *var, NodeList **init)
{ {
Node *a, *r, *on, *c; Node *a, *r, *on, *c;
Type *t; Type *t;
NodeList *args;
if(n->left == N) if(n->list == nil)
goto dflt; goto dflt;
c = n->left; c = n->list->n;
if(c->op == ORECV) if(c->op == ORECV)
goto recv; goto recv;
...@@ -1515,13 +1554,12 @@ selcase(Node *n, Node *var, Node **init) ...@@ -1515,13 +1554,12 @@ selcase(Node *n, Node *var, Node **init)
argtype(on, t->type); argtype(on, t->type);
argtype(on, t->type); argtype(on, t->type);
a = c->right; // elem
r = a;
a = c->left; // chan
r = list(a, r);
a = var; // sel-var a = var; // sel-var
r = list(a, r); args = list1(a);
a = c->left; // chan
args = list(args, a);
a = c->right; // elem
args = list(args, a);
goto out; goto out;
recv: recv:
...@@ -1544,16 +1582,17 @@ recv: ...@@ -1544,16 +1582,17 @@ recv:
argtype(on, t->type); argtype(on, t->type);
argtype(on, t->type); argtype(on, t->type);
a = var; // sel-var
args = list1(a);
a = c->left; // chan
args = list(args, a);
a = c->left; // nil elem a = c->left; // nil elem
a = nod(OLITERAL, N, N); a = nod(OLITERAL, N, N);
a->val.ctype = CTNIL; a->val.ctype = CTNIL;
a->type = types[TNIL]; a->type = types[TNIL];
args = list(args, a);
r = a;
a = c->left; // chan
r = list(a, r);
a = var; // sel-var
r = list(a, r);
goto out; goto out;
recv2: recv2:
...@@ -1568,7 +1607,7 @@ recv2: ...@@ -1568,7 +1607,7 @@ recv2:
return N; return N;
} }
walkexpr(c->left, Elv, init); // elem walkexpr(c->left, Elv, init); // check elem
convlit(c->left, t->type); convlit(c->left, t->type);
if(!ascompat(t->type, c->left->type)) { if(!ascompat(t->type, c->left->type)) {
badtype(c->op, t->type, c->left->type); badtype(c->op, t->type, c->left->type);
...@@ -1580,24 +1619,27 @@ recv2: ...@@ -1580,24 +1619,27 @@ recv2:
argtype(on, t->type); argtype(on, t->type);
argtype(on, t->type); argtype(on, t->type);
a = var; // sel-var
args = list1(a);
a = c->right; // chan
args = list(args, a);
a = c->left; // elem a = c->left; // elem
a = nod(OADDR, a, N); a = nod(OADDR, a, N);
r = a; args = list(args, a);
a = c->right; // chan
r = list(a, r);
a = var; // sel-var
r = list(a, r);
goto out; goto out;
dflt: dflt:
// selectdefault(sel *byte); // selectdefault(sel *byte);
on = syslook("selectdefault", 0); on = syslook("selectdefault", 0);
a = var; a = var;
r = a; // sel-var args = list1(a);
goto out; goto out;
out: out:
a = nod(OCALL, on, r); a = nod(OCALL, on, N);
a->list = args;
r = nod(OIF, N, N); r = nod(OIF, N, N);
r->ntest = a; r->ntest = a;
...@@ -1610,7 +1652,7 @@ out: ...@@ -1610,7 +1652,7 @@ out:
* case v := <-chan // select and switch * case v := <-chan // select and switch
*/ */
Node* Node*
selectas(Node *name, Node *expr, Node **init) selectas(Node *name, Node *expr, NodeList **init)
{ {
Type *t; Type *t;
...@@ -1633,77 +1675,81 @@ bad: ...@@ -1633,77 +1675,81 @@ bad:
void void
walkselect(Node *sel) walkselect(Node *sel)
{ {
Iter iter, iter1; Node *n, *l, *oc, *on, *r;
Node *n, *n1, *l, *oc, *on, *r, *init; Node *var, *def;
Node *var, *bod, *nbod, *res, *def; NodeList *args, *res, *bod, *nbod, *init, *ln;
int count, op; int count, op;
int32 lno; int32 lno;
lno = setlineno(sel); lno = setlineno(sel);
init = N; init = nil;
// generate sel-struct // generate sel-struct
var = nod(OXXX, N, N); var = nod(OXXX, N, N);
tempname(var, ptrto(types[TUINT8])); tempname(var, ptrto(types[TUINT8]));
n = listfirst(&iter, &sel->left); if(sel->list == nil) {
if(n == N || n->op == OEMPTY) {
yyerror("empty select"); yyerror("empty select");
return; return;
} }
count = 0; // number of cases count = 0; // number of cases
res = N; // entire select body res = nil; // entire select body
bod = N; // body of each case bod = nil; // body of each case
oc = N; // last case oc = N; // last case
def = N; // default case def = N; // default case
for(ln=sel->list; ln; ln=ln->next) {
for(; n!=N; n=listnext(&iter)) { n = ln->n;
setlineno(n); setlineno(n);
if(n->op != OXCASE) if(n->op != OXCASE)
fatal("walkselect %O", n->op); fatal("walkselect %O", n->op);
count++; count++;
if(n->left == N) { l = N;
if(n->list == nil) {
op = ORECV; // actual value not used op = ORECV; // actual value not used
if(def != N) if(def != N)
yyerror("repeated default; first at %L", def->lineno); yyerror("repeated default; first at %L", def->lineno);
def = n; def = n;
} else } else {
op = n->left->op; l = n->list->n;
op = l->op;
if(n->list->next) {
yyerror("select cases cannot be lists");
continue;
}
}
nbod = N; nbod = nil;
switch(op) { switch(op) {
default: default:
yyerror("select cases must be send, recv or default"); yyerror("select cases must be send, recv or default %O", op);
continue; continue;
case OAS: case OAS:
// convert new syntax (a=recv(chan)) to (recv(a,chan)) // convert new syntax (a=recv(chan)) to (recv(a,chan))
l = n->left;
if(l->right == N || l->right->op != ORECV) { if(l->right == N || l->right->op != ORECV) {
yyerror("select cases must be send, recv or default"); yyerror("select cases must be send, recv or default %O", l->right->op);
break; break;
} }
r = l->right; // rcv r = l->right; // rcv
r->right = r->left; r->right = r->left;
r->left = l->left; r->left = l->left;
n->left = r; n->list->n = r;
// convert case x := foo: body // convert case x := foo: body
// to case tmp := foo: x := tmp; body. // to case tmp := foo: x := tmp; body.
// if x escapes and must be allocated // if x escapes and must be allocated
// on the heap, this delays the allocation // on the heap, this delays the allocation
// until after the select has chosen this branch. // until after the select has chosen this branch.
if(n->ninit != N && n->ninit->op == ODCL) { if(n->ninit != nil && n->ninit->n->op == ODCL) {
on = nod(OXXX, N, N); on = nod(OXXX, N, N);
tempname(on, l->left->type); tempname(on, l->left->type);
on->sym = lookup("!tmpselect!"); on->sym = lookup("!tmpselect!");
r->left = on; r->left = on;
nbod = nod(OAS, l->left, on); nbod = list(n->ninit, nod(OAS, l->left, on));
nbod->ninit = n->ninit; n->ninit = nil;
n->ninit = N;
} }
break; break;
...@@ -1712,14 +1758,13 @@ walkselect(Node *sel) ...@@ -1712,14 +1758,13 @@ walkselect(Node *sel)
break; break;
} }
for(n1 = listfirst(&iter1, &n->nbody); n1 != N; n1 = listnext(&iter1)) nbod = concat(nbod, n->nbody);
nbod = list(nbod, n1);
nbod = list(nbod, nod(OBREAK, N, N)); nbod = list(nbod, nod(OBREAK, N, N));
n->nbody = N; n->nbody = nil;
oc = selcase(n, var, &init); oc = selcase(n, var, &init);
if(oc != N) { if(oc != N) {
oc->nbody = rev(nbod); oc->nbody = nbod;
res = list(res, oc); res = list(res, oc);
} }
} }
...@@ -1727,7 +1772,8 @@ walkselect(Node *sel) ...@@ -1727,7 +1772,8 @@ walkselect(Node *sel)
// selectgo(sel *byte); // selectgo(sel *byte);
on = syslook("selectgo", 0); on = syslook("selectgo", 0);
r = nod(OCALL, on, var); // sel-var r = nod(OCALL, on, N);
r->list = list1(var); // sel-var
res = list(res, r); res = list(res, r);
// newselect(size uint32) (sel *byte); // newselect(size uint32) (sel *byte);
...@@ -1735,18 +1781,21 @@ walkselect(Node *sel) ...@@ -1735,18 +1781,21 @@ walkselect(Node *sel)
r = nod(OXXX, N, N); r = nod(OXXX, N, N);
nodconst(r, types[TINT], count); // count nodconst(r, types[TINT], count); // count
r = nod(OCALL, on, r); args = list1(r);
r = nod(OCALL, on, N);
r->list = args;
r = nod(OAS, var, r); r = nod(OAS, var, r);
sel->ninit = r; sel->ninit = list1(r);
sel->nbody = rev(res); sel->nbody = res;
sel->left = N; sel->left = N;
walkstmt(sel->ninit); // TODO(rsc): is ninit a walkstmtlist or walkexprlist?
walkstmt(sel->nbody); walkstmtlist(sel->ninit);
walkstmtlist(sel->nbody);
//dump("sel", sel); //dump("sel", sel);
sel->ninit = list(sel->ninit, init); sel->ninit = concat(sel->ninit, init);
lineno = lno; lineno = lno;
} }
...@@ -1828,14 +1877,14 @@ lookdot(Node *n, Type *t) ...@@ -1828,14 +1877,14 @@ lookdot(Node *n, Type *t)
} }
void void
walkdot(Node *n, Node **init) walkdot(Node *n, NodeList **init)
{ {
Type *t; Type *t;
walkexpr(n->ninit, Etop, init); walkexprlist(n->ninit, Etop, init);
if(n->ninit != N) { if(n->ninit != nil) {
*init = list(*init, n->ninit); *init = concat(*init, n->ninit);
n->ninit = N; n->ninit = nil;
} }
if(n->left == N || n->right == N) if(n->left == N || n->right == N)
...@@ -1873,43 +1922,46 @@ walkdot(Node *n, Node **init) ...@@ -1873,43 +1922,46 @@ walkdot(Node *n, Node **init)
} }
Node* Node*
ascompatee(int op, Node **nl, Node **nr, Node **init) ascompatee1(int op, Node *l, Node *r, NodeList **init)
{ {
Node *l, *r, *nn, *a; Node *a;
Iter savel, saver;
/* /*
* check assign expression list to * check assign expression to
* a expression list. called in * a expression. called in
* expr-list = expr-list * expr = expr
*/ */
l = listfirst(&savel, nl);
r = listfirst(&saver, nr);
nn = N;
loop:
if(l == N || r == N) {
// cannot happen: caller checked that lists had same length
if(l != r)
yyerror("error in shape across %O", op);
return rev(nn);
}
convlit(r, l->type); convlit(r, l->type);
if(!ascompat(l->type, r->type)) { if(!ascompat(l->type, r->type)) {
badtype(op, l->type, r->type); badtype(op, l->type, r->type);
return N; return nil;
} }
if(l->op == ONAME && l->class == PFUNC) if(l->op == ONAME && l->class == PFUNC)
yyerror("cannot assign to function"); yyerror("cannot assign to function");
a = nod(OAS, l, r); a = nod(OAS, l, r);
a = convas(a, init); a = convas(a, init);
nn = list(a, nn); return a;
}
l = listnext(&savel); NodeList*
r = listnext(&saver); ascompatee(int op, NodeList *nl, NodeList *nr, NodeList **init)
goto loop; {
NodeList *ll, *lr, *nn;
/*
* check assign expression list to
* a expression list. called in
* expr-list = expr-list
*/
nn = nil;
for(ll=nl, lr=nr; ll && lr; ll=ll->next, lr=lr->next)
nn = list(nn, ascompatee1(op, ll->n, lr->n, init));
// cannot happen: caller checked that lists had same length
if(ll || lr)
yyerror("error in shape across %O", op);
return nn;
} }
/* /*
...@@ -1928,68 +1980,61 @@ fncall(Node *l, Type *rt) ...@@ -1928,68 +1980,61 @@ fncall(Node *l, Type *rt)
return 1; return 1;
} }
Node* NodeList*
ascompatet(int op, Node **nl, Type **nr, int fp, Node **init) ascompatet(int op, NodeList *nl, Type **nr, int fp, NodeList **init)
{ {
Node *l, *nn, *mm, *tmp, *a; Node *l, *tmp, *a;
NodeList *ll;
Type *r; Type *r;
Iter savel, saver; Iter saver;
int ucount; int ucount;
NodeList *nn, *mm;
/* /*
* check assign type list to * check assign type list to
* a expression list. called in * a expression list. called in
* expr-list = func() * expr-list = func()
*/ */
l = listfirst(&savel, nl);
r = structfirst(&saver, nr); r = structfirst(&saver, nr);
nn = N; nn = nil;
mm = N; mm = nil;
ucount = 0; ucount = 0;
for(ll=nl; ll; ll=ll->next) {
loop: if(r == T)
if(l == N || r == T) { break;
if(l != N || r != T) l = ll->n;
yyerror("assignment count mismatch: %d = %d", if(!ascompat(l->type, r->type)) {
listcount(*nl), structcount(*nr)); badtype(op, l->type, r->type);
if(ucount) return nil;
yyerror("reorder2: too many function calls evaluating parameters");
if(mm != N) {
mm = rev(mm);
for(l=listfirst(&savel, &mm); l!=N; l=listnext(&savel))
nn = list(nn, l);
} }
return rev(nn);
}
if(!ascompat(l->type, r->type)) { // any lv that causes a fn call must be
badtype(op, l->type, r->type); // deferred until all the return arguments
return N; // have been pulled from the output arguments
} if(fncall(l, r->type)) {
tmp = nod(OXXX, N, N);
tempname(tmp, r->type);
a = nod(OAS, l, tmp);
a = convas(a, init);
mm = list(mm, a);
l = tmp;
}
// any lv that causes a fn call must be a = nod(OAS, l, nodarg(r, fp));
// deferred until all the return arguments
// have been pulled from the output arguments
if(fncall(l, r->type)) {
tmp = nod(OXXX, N, N);
tempname(tmp, r->type);
a = nod(OAS, l, tmp);
a = convas(a, init); a = convas(a, init);
mm = list(mm, a); ullmancalc(a);
l = tmp; if(a->ullman >= UINF)
ucount++;
nn = list(nn, a);
r = structnext(&saver);
} }
a = nod(OAS, l, nodarg(r, fp)); if(ll != nil || r != T)
a = convas(a, init); yyerror("assignment count mismatch: %d = %d",
ullmancalc(a); count(nl), structcount(*nr));
if(a->ullman >= UINF) if(ucount)
ucount++; yyerror("reorder2: too many function calls evaluating parameters");
nn = list(nn, a); return concat(nn, mm);
l = listnext(&savel);
r = structnext(&saver);
goto loop;
} }
/* /*
...@@ -2022,27 +2067,29 @@ sigtype(Type *st) ...@@ -2022,27 +2067,29 @@ sigtype(Type *st)
* then call the ... arg (interface) * then call the ... arg (interface)
* with a pointer to the structure. * with a pointer to the structure.
*/ */
Node* NodeList*
mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp, Node **init) mkdotargs(NodeList *lr0, NodeList *nn, Type *l, int fp, NodeList **init)
{ {
Node *r;
Type *t, *st, *ft; Type *t, *st, *ft;
Node *a, *n, *var; Node *a, *var;
Iter saven; NodeList *lr, *n;
n = N; // list of assignments n = nil; // list of assignments
st = typ(TSTRUCT); // generated structure st = typ(TSTRUCT); // generated structure
ft = T; // last field ft = T; // last field
while(r != N) { for(lr=lr0; lr; lr=lr->next) {
r = lr->n;
if(r->op == OLITERAL && r->val.ctype == CTNIL) { if(r->op == OLITERAL && r->val.ctype == CTNIL) {
if(r->type == T || r->type->etype == TNIL) { if(r->type == T || r->type->etype == TNIL) {
yyerror("inappropriate use of nil in ... argument"); yyerror("inappropriate use of nil in ... argument");
return N; return nil;
} }
} }
defaultlit(r, T); defaultlit(r, T);
if(r->type == T) // type check failed if(r->type == T) // type check failed
return N; return nil;
// generate the next structure field // generate the next structure field
t = typ(TFIELD); t = typ(TFIELD);
...@@ -2055,11 +2102,6 @@ mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp, Node **init ...@@ -2055,11 +2102,6 @@ mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp, Node **init
a = nod(OAS, N, r); a = nod(OAS, N, r);
n = list(n, a); n = list(n, a);
if(rr != N) {
r = rr;
rr = N;
} else
r = listnext(saver);
} }
// make a named type for the struct // make a named type for the struct
...@@ -2075,25 +2117,22 @@ mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp, Node **init ...@@ -2075,25 +2117,22 @@ mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp, Node **init
// use the init list so that reorder1 doesn't reorder // use the init list so that reorder1 doesn't reorder
// these assignments after the interface conversion // these assignments after the interface conversion
// below. // below.
n = rev(n);
r = listfirst(&saven, &n);
t = st->type; t = st->type;
while(r != N) { for(lr=n; lr; lr=lr->next) {
r = lr->n;
r->left = nod(OXXX, N, N); r->left = nod(OXXX, N, N);
*r->left = *var; *r->left = *var;
r->left->type = r->right->type; r->left->type = r->right->type;
r->left->xoffset += t->width; r->left->xoffset += t->width;
walkexpr(r, Etop, init); walkexpr(r, Etop, init);
*init = list(*init, r);
r = listnext(&saven);
t = t->down; t = t->down;
} }
*init = concat(*init, n);
// last thing is to put assignment // last thing is to put assignment
// of the structure to the DDD parameter // of the structure to the DDD parameter
a = nod(OAS, nodarg(l, fp), var); a = nod(OAS, nodarg(l, fp), var);
nn = list(convas(a, init), nn); nn = list(nn, convas(a, init));
return nn; return nn;
} }
...@@ -2123,15 +2162,15 @@ dumptypes(Type **nl, char *what) ...@@ -2123,15 +2162,15 @@ dumptypes(Type **nl, char *what)
} }
static void static void
dumpnodetypes(Node **nr, char *what) dumpnodetypes(NodeList *l, char *what)
{ {
int first; int first;
Node *r; Node *r;
Iter saver;
print("\t"); print("\t");
first = 1; first = 1;
for(r = listfirst(&saver, nr); r != N; r = listnext(&saver)) { for(; l; l=l->next) {
r = l->n;
if(first) if(first)
first = 0; first = 0;
else else
...@@ -2149,23 +2188,26 @@ dumpnodetypes(Node **nr, char *what) ...@@ -2149,23 +2188,26 @@ dumpnodetypes(Node **nr, char *what)
* return expr-list * return expr-list
* func(expr-list) * func(expr-list)
*/ */
Node* NodeList*
ascompatte(int op, Type **nl, Node **nr, int fp, Node **init) ascompatte(int op, Type **nl, NodeList *lr, int fp, NodeList **init)
{ {
Type *l, *ll; Type *l, *ll;
Node *r, *rr, *nn, *a; Node *r, *a;
Iter savel, saver, peekl, peekr; NodeList *nn, *lr0;
Iter savel, peekl;
lr0 = lr;
l = structfirst(&savel, nl); l = structfirst(&savel, nl);
r = listfirst(&saver, nr); r = N;
nn = N; if(lr)
r = lr->n;
nn = nil;
// 1 to many // 1 to many
peekl = savel; peekl = savel;
peekr = saver;
if(l != T && r != N if(l != T && r != N
&& structnext(&peekl) != T && structnext(&peekl) != T
&& listnext(&peekr) == N && lr->next == nil
&& eqtypenoname(r->type, *nl)) { && eqtypenoname(r->type, *nl)) {
// clumsy check for differently aligned structs. // clumsy check for differently aligned structs.
// now that output structs are aligned separately // now that output structs are aligned separately
...@@ -2174,7 +2216,7 @@ ascompatte(int op, Type **nl, Node **nr, int fp, Node **init) ...@@ -2174,7 +2216,7 @@ ascompatte(int op, Type **nl, Node **nr, int fp, Node **init)
fatal("misaligned multiple return\n\t%T\n\t%T", r->type, *nl); fatal("misaligned multiple return\n\t%T\n\t%T", r->type, *nl);
a = nodarg(*nl, fp); a = nodarg(*nl, fp);
a->type = r->type; a->type = r->type;
return convas(nod(OAS, a, r), init); return list1(convas(nod(OAS, a, r), init));
} }
loop: loop:
...@@ -2188,20 +2230,17 @@ loop: ...@@ -2188,20 +2230,17 @@ loop:
// only if we are assigning a single ddd // only if we are assigning a single ddd
// argument to a ddd parameter then it is // argument to a ddd parameter then it is
// passed thru unencapsulated // passed thru unencapsulated
rr = listnext(&saver); if(r != N && lr->next == nil && isddd(r->type)) {
if(r != N && rr == N && isddd(r->type)) {
a = nod(OAS, nodarg(l, fp), r); a = nod(OAS, nodarg(l, fp), r);
a = convas(a, init); a = convas(a, init);
nn = list(a, nn); nn = list(nn, a);
return rev(nn); return nn;
} }
// normal case -- make a structure of all // normal case -- make a structure of all
// remaining arguments and pass a pointer to // remaining arguments and pass a pointer to
// it to the ddd parameter (empty interface) // it to the ddd parameter (empty interface)
nn = mkdotargs(r, rr, &saver, nn, l, fp, init); return mkdotargs(lr, nn, l, fp, init);
return rev(nn);
} }
if(l == T || r == N) { if(l == T || r == N) {
...@@ -2211,24 +2250,25 @@ loop: ...@@ -2211,24 +2250,25 @@ loop:
else else
yyerror("too many arguments to %O", op); yyerror("too many arguments to %O", op);
dumptypes(nl, "expected"); dumptypes(nl, "expected");
dumpnodetypes(nr, "given"); dumpnodetypes(lr0, "given");
} }
return rev(nn); return nn;
} }
convlit(r, l->type); convlit(r, l->type);
if(!ascompat(l->type, r->type)) { if(!ascompat(l->type, r->type)) {
badtype(op, l->type, r->type); badtype(op, l->type, r->type);
return N; return nil;
} }
a = nod(OAS, nodarg(l, fp), r); a = nod(OAS, nodarg(l, fp), r);
a = convas(a, init); a = convas(a, init);
nn = list(a, nn); nn = list(nn, a);
l = structnext(&savel); l = structnext(&savel);
r = listnext(&saver); r = N;
lr = lr->next;
if(lr != nil)
r = lr->n;
goto loop; goto loop;
} }
...@@ -2332,106 +2372,112 @@ ascompat(Type *dst, Type *src) ...@@ -2332,106 +2372,112 @@ ascompat(Type *dst, Type *src)
// generate code for print // generate code for print
// fmt = 0: print // fmt = 0: print
// fmt = 1: println // fmt = 1: println
// fmt = 2: panicln (like println but no trailing newline)
Node* Node*
prcompat(Node *n, int fmt) prcompat(NodeList *all, int fmt, int dopanic)
{ {
Node *l, *r; Node *r;
Node *n;
NodeList *l;
Node *on; Node *on;
Type *t; Type *t;
Iter save;
int notfirst, et; int notfirst, et;
NodeList *calls;
r = N; calls = nil;
l = listfirst(&save, &n);
notfirst = 0; notfirst = 0;
loop: for(l=all; l; l=l->next) {
if(l == N) { if(notfirst) {
if(fmt == 1) { on = syslook("printsp", 0);
on = syslook("printnl", 0); calls = list(calls, nod(OCALL, on, N));
r = list(r, nod(OCALL, on, N));
} }
walkexpr(r, Etop, nil); notfirst = fmt;
return r;
} n = l->n;
walkexpr(n, Erv, nil);
if(notfirst) { if(n->op == OLITERAL) {
on = syslook("printsp", 0); switch(n->val.ctype) {
r = list(r, nod(OCALL, on, N)); case CTINT:
} defaultlit(n, types[TINT64]);
break;
walkexpr(l, Erv, nil); case CTFLT:
if(l->op == OLITERAL) { defaultlit(n, types[TFLOAT64]);
switch(l->val.ctype) { break;
case CTINT: }
defaultlit(l, types[TINT64]);
break;
case CTFLT:
defaultlit(l, types[TFLOAT64]);
break;
} }
} if(n->type == T)
if(l->type == T) continue;
goto out;
et = l->type->etype; et = n->type->etype;
if(isinter(l->type)) { if(isinter(n->type)) {
if(isnilinter(l->type)) if(isnilinter(n->type))
on = syslook("printeface", 1); on = syslook("printeface", 1);
else else
on = syslook("printiface", 1); on = syslook("printiface", 1);
argtype(on, l->type); // any-1 argtype(on, n->type); // any-1
} else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC) { } else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC) {
on = syslook("printpointer", 1); on = syslook("printpointer", 1);
argtype(on, l->type); // any-1 argtype(on, n->type); // any-1
} else if(isslice(l->type)) { } else if(isslice(n->type)) {
on = syslook("printarray", 1); on = syslook("printarray", 1);
argtype(on, l->type); // any-1 argtype(on, n->type); // any-1
} else if(isint[et]) { } else if(isint[et]) {
if(et == TUINT64) if(et == TUINT64)
on = syslook("printuint", 0); on = syslook("printuint", 0);
else else
on = syslook("printint", 0); on = syslook("printint", 0);
} else if(isfloat[et]) { } else if(isfloat[et]) {
on = syslook("printfloat", 0); on = syslook("printfloat", 0);
} else if(et == TBOOL) { } else if(et == TBOOL) {
on = syslook("printbool", 0); on = syslook("printbool", 0);
} else if(et == TSTRING) { } else if(et == TSTRING) {
on = syslook("printstring", 0); on = syslook("printstring", 0);
} else { } else {
badtype(OPRINT, l->type, T); badtype(OPRINT, n->type, T);
l = listnext(&save); continue;
goto loop; }
}
t = *getinarg(on->type); t = *getinarg(on->type);
if(t != nil) if(t != nil)
t = t->type; t = t->type;
if(t != nil) if(t != nil)
t = t->type; t = t->type;
if(!eqtype(t, l->type)) { if(!eqtype(t, n->type)) {
l = nod(OCONV, l, N); n = nod(OCONV, n, N);
l->type = t; n->type = t;
}
r = nod(OCALL, on, N);
r->list = list1(n);
calls = list(calls, r);
} }
r = list(r, nod(OCALL, on, l)); if(fmt == 1 && !dopanic) {
on = syslook("printnl", 0);
calls = list(calls, nod(OCALL, on, N));
}
walkexprlist(calls, Etop, nil);
out: if(dopanic)
notfirst = fmt; r = nodpanic(0);
l = listnext(&save); else
goto loop; r = nod(OEMPTY, N, N);
walkexpr(r, Etop, nil);
r->ninit = calls;
return r;
} }
Node* Node*
nodpanic(int32 lineno) nodpanic(int32 lineno)
{ {
Node *n, *on; Node *n, *on;
NodeList *args;
on = syslook("panicl", 0); on = syslook("panicl", 0);
n = nodintconst(lineno); n = nodintconst(lineno);
n = nod(OCALL, on, n); args = list1(n);
n = nod(OCALL, on, N);
n->list = args;
walkexpr(n, Etop, nil); walkexpr(n, Etop, nil);
return n; return n;
} }
...@@ -2440,15 +2486,18 @@ Node* ...@@ -2440,15 +2486,18 @@ Node*
makecompat(Node *n) makecompat(Node *n)
{ {
Type *t; Type *t;
Node *l, *r, *init; Node *l, *r;
NodeList *args, *init;
l = n->left; args = n->list;
r = N; if(args == nil) {
if(l->op == OLIST) { yyerror("make requires type argument");
r = l->right; return n;
l = l->left;
} }
init = N; l = args->n;
r = N;
args = args->next;
init = nil;
walkexpr(l, Etype, &init); walkexpr(l, Etype, &init);
if(l->op != OTYPE) { if(l->op != OTYPE) {
yyerror("cannot make(expr)"); yyerror("cannot make(expr)");
...@@ -2456,8 +2505,7 @@ makecompat(Node *n) ...@@ -2456,8 +2505,7 @@ makecompat(Node *n)
} }
t = l->type; t = l->type;
n->type = t; n->type = t;
n->left = r; n->list = args;
n->right = N;
if(t != T) if(t != T)
switch(t->etype) { switch(t->etype) {
...@@ -2483,20 +2531,24 @@ Node* ...@@ -2483,20 +2531,24 @@ Node*
callnew(Type *t) callnew(Type *t)
{ {
Node *r, *on; Node *r, *on;
NodeList *args;
dowidth(t); dowidth(t);
on = syslook("mal", 1); on = syslook("mal", 1);
argtype(on, t); argtype(on, t);
r = nodintconst(t->width); r = nodintconst(t->width);
r = nod(OCALL, on, r); args = list1(r);
r = nod(OCALL, on, N);
r->list = args;
walkexpr(r, Erv, nil); walkexpr(r, Erv, nil);
return r; return r;
} }
Node* Node*
stringop(Node *n, int top, Node **init) stringop(Node *n, int top, NodeList **init)
{ {
Node *r, *c, *on; Node *r, *c, *on;
NodeList *args;
switch(n->op) { switch(n->op) {
default: default:
...@@ -2512,9 +2564,12 @@ stringop(Node *n, int top, Node **init) ...@@ -2512,9 +2564,12 @@ stringop(Node *n, int top, Node **init)
on = syslook("cmpstring", 0); on = syslook("cmpstring", 0);
r = nod(OCONV, n->left, N); r = nod(OCONV, n->left, N);
r->type = types[TSTRING]; r->type = types[TSTRING];
args = list1(r);
c = nod(OCONV, n->right, N); c = nod(OCONV, n->right, N);
c->type = types[TSTRING]; c->type = types[TSTRING];
r = nod(OCALL, on, list(r, c)); args = list(args, c);
r = nod(OCALL, on, N);
r->list = args;
c = nodintconst(0); c = nodintconst(0);
r = nod(n->op, r, c); r = nod(n->op, r, c);
break; break;
...@@ -2524,9 +2579,12 @@ stringop(Node *n, int top, Node **init) ...@@ -2524,9 +2579,12 @@ stringop(Node *n, int top, Node **init)
on = syslook("catstring", 0); on = syslook("catstring", 0);
r = nod(OCONV, n->left, N); r = nod(OCONV, n->left, N);
r->type = types[TSTRING]; r->type = types[TSTRING];
args = list1(r);
c = nod(OCONV, n->right, N); c = nod(OCONV, n->right, N);
c->type = types[TSTRING]; c->type = types[TSTRING];
r = nod(OCALL, on, list(r, c)); args = list(args, c);
r = nod(OCALL, on, N);
r->list = args;
break; break;
case OASOP: case OASOP:
...@@ -2542,59 +2600,68 @@ stringop(Node *n, int top, Node **init) ...@@ -2542,59 +2600,68 @@ stringop(Node *n, int top, Node **init)
on = syslook("catstring", 0); on = syslook("catstring", 0);
r = nod(OCONV, n->left, N); r = nod(OCONV, n->left, N);
r->type = types[TSTRING]; r->type = types[TSTRING];
args = list1(r);
c = nod(OCONV, n->right, N); c = nod(OCONV, n->right, N);
c->type = types[TSTRING]; c->type = types[TSTRING];
r = nod(OCALL, on, list(r, c)); args = list(args, c);
r = nod(OCALL, on, N);
r->list = args;
r = nod(OAS, n->left, r); r = nod(OAS, n->left, r);
break; break;
} }
break; break;
case OSLICE: case OSLICE:
args = list1(n->left);
// sys_slicestring(s, lb, hb) // sys_slicestring(s, lb, hb)
r = nod(OCONV, n->right->left, N); r = nod(OCONV, n->right->left, N);
r->type = types[TINT]; r->type = types[TINT];
args = list(args, r);
c = nod(OCONV, n->right->right, N); c = nod(OCONV, n->right->right, N);
c->type = types[TINT]; c->type = types[TINT];
args = list(args, c);
r = list(r, c);
r = list(n->left, r);
on = syslook("slicestring", 0); on = syslook("slicestring", 0);
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
break; break;
case OINDEX: case OINDEX:
// sys_indexstring(s, i) // sys_indexstring(s, i)
args = list1(n->left);
r = nod(OCONV, n->right, N); r = nod(OCONV, n->right, N);
r->type = types[TINT]; r->type = types[TINT];
r = list(n->left, r); args = list(args, r);
on = syslook("indexstring", 0); on = syslook("indexstring", 0);
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
break; break;
case OCONV: case OCONV:
// sys_intstring(v) // sys_intstring(v)
r = nod(OCONV, n->left, N); r = nod(OCONV, n->left, N);
r->type = types[TINT64]; r->type = types[TINT64];
args = list1(r);
on = syslook("intstring", 0); on = syslook("intstring", 0);
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
break; break;
case OARRAY: case OARRAY:
r = n->left; r = n->left;
// arraystring([]byte) string;
on = syslook("arraystring", 0);
if(r->type != T && r->type->type != T) { if(r->type != T && r->type->type != T) {
if(istype(r->type->type, TINT) || istype(r->type->type->type, TINT)) { if(istype(r->type->type, TINT) || istype(r->type->type->type, TINT)) {
// arraystring([]byte) string; // arraystring([]byte) string;
on = syslook("arraystringi", 0); on = syslook("arraystringi", 0);
r = nod(OCALL, on, r);
break;
} }
} }
args = list1(r);
// arraystring([]byte) string; r = nod(OCALL, on, N);
on = syslook("arraystring", 0); r->list = args;
r = nod(OCALL, on, r);
break; break;
} }
...@@ -2642,12 +2709,13 @@ bad: ...@@ -2642,12 +2709,13 @@ bad:
} }
Node* Node*
mapop(Node *n, int top, Node **init) mapop(Node *n, int top, NodeList **init)
{ {
Node *r, *a; Node *r, *a, *l;
Type *t; Type *t;
Node *on; Node *on;
int cl, cr; int cl, cr;
NodeList *args;
r = n; r = n;
switch(n->op) { switch(n->op) {
...@@ -2655,7 +2723,7 @@ mapop(Node *n, int top, Node **init) ...@@ -2655,7 +2723,7 @@ mapop(Node *n, int top, Node **init)
fatal("mapop: unknown op %O", n->op); fatal("mapop: unknown op %O", n->op);
case OMAKE: case OMAKE:
cl = listcount(n->left); cl = count(n->list);
if(cl > 1) if(cl > 1)
yyerror("too many arguments to make map"); yyerror("too many arguments to make map");
...@@ -2670,26 +2738,28 @@ mapop(Node *n, int top, Node **init) ...@@ -2670,26 +2738,28 @@ mapop(Node *n, int top, Node **init)
if(t == T) if(t == T)
break; break;
a = n->left; // hint
if(cl != 1)
a = nodintconst(0);
r = a;
a = nodintconst(algtype(t->type)); // val algorithm
r = list(a, r);
a = nodintconst(algtype(t->down)); // key algorithm
r = list(a, r);
a = nodintconst(t->type->width); // val width
r = list(a, r);
a = nodintconst(t->down->width); // key width a = nodintconst(t->down->width); // key width
r = list(a, r); args = list1(a);
a = nodintconst(t->type->width); // val width
args = list(args, a);
a = nodintconst(algtype(t->down)); // key algorithm
args = list(args, a);
a = nodintconst(algtype(t->type)); // val algorithm
args = list(args, a);
if(cl == 1)
a = n->list->n; // hint
else
a = nodintconst(0);
args = list(args, a);
on = syslook("newmap", 1); on = syslook("newmap", 1);
argtype(on, t->down); // any-1 argtype(on, t->down); // any-1
argtype(on, t->type); // any-2 argtype(on, t->type); // any-2
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
walkexpr(r, top, nil); walkexpr(r, top, nil);
r->type = n->type; r->type = n->type;
break; break;
...@@ -2710,10 +2780,10 @@ mapop(Node *n, int top, Node **init) ...@@ -2710,10 +2780,10 @@ mapop(Node *n, int top, Node **init)
break; break;
} }
a = n->right; // key
r = a;
a = n->left; // map a = n->left; // map
r = list(a, r); args = list1(a);
a = n->right; // key
args = list(args, a);
on = syslook("mapaccess1", 1); on = syslook("mapaccess1", 1);
...@@ -2722,22 +2792,13 @@ mapop(Node *n, int top, Node **init) ...@@ -2722,22 +2792,13 @@ mapop(Node *n, int top, Node **init)
argtype(on, t->down); // any-3 argtype(on, t->down); // any-3
argtype(on, t->type); // any-4 argtype(on, t->type); // any-4
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
walkexpr(r, Erv, nil); walkexpr(r, Erv, nil);
r->type = t->type; r->type = t->type;
break; break;
case OAS: case OAS:
cl = listcount(n->left);
cr = listcount(n->right);
if(cl == 1 && cr == 2)
goto assign2;
if(cl == 2 && cr == 1)
goto access2;
if(cl != 1 || cr != 1)
goto shape;
// mapassign1(hmap map[any-1]any-2, key any-3, val any-4); // mapassign1(hmap map[any-1]any-2, key any-3, val any-4);
if(n->left->op != OINDEX) if(n->left->op != OINDEX)
goto shape; goto shape;
...@@ -2746,12 +2807,12 @@ mapop(Node *n, int top, Node **init) ...@@ -2746,12 +2807,12 @@ mapop(Node *n, int top, Node **init)
if(t == T) if(t == T)
break; break;
a = n->right; // val
r = a;
a = n->left->right; // key
r = list(a, r);
a = n->left->left; // map a = n->left->left; // map
r = list(a, r); args = list1(a);
a = n->left->right; // key
args = list(args, a);
a = n->right; // val
args = list(args, a);
on = syslook("mapassign1", 1); on = syslook("mapassign1", 1);
...@@ -2760,27 +2821,35 @@ mapop(Node *n, int top, Node **init) ...@@ -2760,27 +2821,35 @@ mapop(Node *n, int top, Node **init)
argtype(on, t->down); // any-3 argtype(on, t->down); // any-3
argtype(on, t->type); // any-4 argtype(on, t->type); // any-4
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
walkexpr(r, Etop, init); walkexpr(r, Etop, init);
break; break;
case OAS2:
cl = count(n->list);
cr = count(n->rlist);
if(cl == 1 && cr == 2)
goto assign2;
if(cl == 2 && cr == 1)
goto access2;
goto shape;
assign2: assign2:
// mapassign2(hmap map[any]any, key any, val any, pres bool); // mapassign2(hmap map[any]any, key any, val any, pres bool);
if(n->left->op != OINDEX) l = n->list->n;
if(l->op != OINDEX)
goto shape; goto shape;
t = fixmap(n->left->left->type); t = fixmap(l->left->type);
if(t == T) if(t == T)
break; break;
a = n->right->right; // pres args = list1(l->left); // map
r = a; args = list(args, l->right); // key
a = n->right->left; // val args = list(args, n->rlist->n); // val
r =list(a, r); args = list(args, n->rlist->next->n); // pres
a = n->left->right; // key
r = list(a, r);
a = n->left->left; // map
r = list(a, r);
on = syslook("mapassign2", 1); on = syslook("mapassign2", 1);
...@@ -2789,7 +2858,8 @@ mapop(Node *n, int top, Node **init) ...@@ -2789,7 +2858,8 @@ mapop(Node *n, int top, Node **init)
argtype(on, t->down); // any-3 argtype(on, t->down); // any-3
argtype(on, t->type); // any-4 argtype(on, t->type); // any-4
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
walkexpr(r, Etop, init); walkexpr(r, Etop, init);
break; break;
...@@ -2797,17 +2867,16 @@ mapop(Node *n, int top, Node **init) ...@@ -2797,17 +2867,16 @@ mapop(Node *n, int top, Node **init)
// mapaccess2(hmap map[any-1]any-2, key any-3) (val-4 any, pres bool); // mapaccess2(hmap map[any-1]any-2, key any-3) (val-4 any, pres bool);
//dump("access2", n); //dump("access2", n);
if(n->right->op != OINDEX) r = n->rlist->n;
if(r->op != OINDEX)
goto shape; goto shape;
t = fixmap(n->right->left->type); t = fixmap(r->left->type);
if(t == T) if(t == T)
break; break;
a = n->right->right; // key args = list1(r->left); // map
r = a; args = list(args, r->right); // key
a = n->right->left; // map
r = list(a, r);
on = syslook("mapaccess2", 1); on = syslook("mapaccess2", 1);
...@@ -2816,7 +2885,9 @@ mapop(Node *n, int top, Node **init) ...@@ -2816,7 +2885,9 @@ mapop(Node *n, int top, Node **init)
argtype(on, t->down); // any-3 argtype(on, t->down); // any-3
argtype(on, t->type); // any-4 argtype(on, t->type); // any-4
n->right = nod(OCALL, on, r); a = nod(OCALL, on, N);
a->list = args;
n->rlist = list1(a);
walkexpr(n, Etop, init); walkexpr(n, Etop, init);
r = n; r = n;
break; break;
...@@ -2824,18 +2895,20 @@ mapop(Node *n, int top, Node **init) ...@@ -2824,18 +2895,20 @@ mapop(Node *n, int top, Node **init)
case OASOP: case OASOP:
// rewrite map[index] op= right // rewrite map[index] op= right
// into tmpi := index; map[tmpi] = map[tmpi] op right // into tmpi := index; map[tmpi] = map[tmpi] op right
// TODO(rsc): does this double-evaluate map?
t = n->left->left->type; t = n->left->left->type;
a = nod(OXXX, N, N); a = nod(OXXX, N, N);
tempname(a, t->down); // tmpi tempname(a, t->down); // tmpi
r = nod(OAS, a, n->left->right); // tmpi := index r = nod(OAS, a, n->left->right); // tmpi := index
n->left->right = a; // m[tmpi] n->left->right = a; // m[tmpi]
walkexpr(r, Etop, init);
*init = list(*init, r);
a = nod(OXXX, N, N); a = nod(OXXX, N, N);
indir(a, n->left); // copy of map[tmpi] indir(a, n->left); // copy of map[tmpi]
a = nod(n->etype, a, n->right); // m[tmpi] op right a = nod(n->etype, a, n->right); // m[tmpi] op right
a = nod(OAS, n->left, a); // map[tmpi] = map[tmpi] op right r = nod(OAS, n->left, a); // map[tmpi] = map[tmpi] op right
r = nod(OLIST, r, a);
walkexpr(r, Etop, init); walkexpr(r, Etop, init);
break; break;
} }
...@@ -2852,11 +2925,11 @@ nottop: ...@@ -2852,11 +2925,11 @@ nottop:
} }
Node* Node*
chanop(Node *n, int top, Node **init) chanop(Node *n, int top, NodeList **init)
{ {
Node *r, *a; Node *r, *a, *on;
NodeList *args;
Type *t; Type *t;
Node *on;
int cl, cr; int cl, cr;
r = n; r = n;
...@@ -2865,41 +2938,57 @@ chanop(Node *n, int top, Node **init) ...@@ -2865,41 +2938,57 @@ chanop(Node *n, int top, Node **init)
fatal("chanop: unknown op %O", n->op); fatal("chanop: unknown op %O", n->op);
case OCLOSE: case OCLOSE:
cl = count(n->list);
if(cl > 1)
yyerror("too many arguments to close");
else if(cl < 1)
yyerror("missing argument to close");
n->left = n->list->n;
// closechan(hchan *chan any); // closechan(hchan *chan any);
t = fixchan(n->left->type); t = fixchan(n->left->type);
if(t == T) if(t == T)
break; break;
a = n->left; // chan a = n->left; // chan
r = a; args = list1(a);
on = syslook("closechan", 1); on = syslook("closechan", 1);
argtype(on, t); // any-1 argtype(on, t); // any-1
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
walkexpr(r, top, nil); walkexpr(r, top, nil);
r->type = n->type; r->type = n->type;
break; break;
case OCLOSED: case OCLOSED:
cl = count(n->list);
if(cl > 1)
yyerror("too many arguments to closed");
else if(cl < 1)
yyerror("missing argument to closed");
n->left = n->list->n;
// closedchan(hchan *chan any) bool; // closedchan(hchan *chan any) bool;
t = fixchan(n->left->type); t = fixchan(n->left->type);
if(t == T) if(t == T)
break; break;
a = n->left; // chan a = n->left; // chan
r = a; args = list1(a);
on = syslook("closedchan", 1); on = syslook("closedchan", 1);
argtype(on, t); // any-1 argtype(on, t); // any-1
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
walkexpr(r, top, nil); walkexpr(r, top, nil);
n->type = r->type; n->type = r->type;
break; break;
case OMAKE: case OMAKE:
cl = listcount(n->left); cl = count(n->list);
if(cl > 1) if(cl > 1)
yyerror("too many arguments to make chan"); yyerror("too many arguments to make chan");
...@@ -2910,37 +2999,38 @@ chanop(Node *n, int top, Node **init) ...@@ -2910,37 +2999,38 @@ chanop(Node *n, int top, Node **init)
if(t == T) if(t == T)
break; break;
a = nodintconst(t->type->width); // elem width
args = list1(a);
a = nodintconst(algtype(t->type)); // elem algorithm
args = list(args, a);
a = nodintconst(0); a = nodintconst(0);
if(cl == 1) { if(cl == 1) {
// async buf size // async buf size
a = nod(OCONV, n->left, N); a = nod(OCONV, n->list->n, N);
a->type = types[TINT]; a->type = types[TINT];
} }
args = list(args, a);
r = a;
a = nodintconst(algtype(t->type)); // elem algorithm
r = list(a, r);
a = nodintconst(t->type->width); // elem width
r = list(a, r);
on = syslook("newchan", 1); on = syslook("newchan", 1);
argtype(on, t->type); // any-1 argtype(on, t->type); // any-1
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
walkexpr(r, top, nil); walkexpr(r, top, nil);
r->type = n->type; r->type = n->type;
break; break;
case OAS: case OAS2:
cl = listcount(n->left); cl = count(n->list);
cr = listcount(n->right); cr = count(n->rlist);
if(cl != 2 || cr != 1 || n->right->op != ORECV) if(cl != 2 || cr != 1 || n->rlist->n->op != ORECV)
goto shape; goto shape;
// chanrecv2(hchan *chan any) (elem any, pres bool); // chanrecv2(hchan *chan any) (elem any, pres bool);
defaultlit(n->right->left, T); r = n->rlist->n;
t = fixchan(n->right->left->type); defaultlit(r->left, T);
t = fixchan(r->left->type);
if(t == T) if(t == T)
break; break;
...@@ -2949,22 +3039,26 @@ chanop(Node *n, int top, Node **init) ...@@ -2949,22 +3039,26 @@ chanop(Node *n, int top, Node **init)
break; break;
} }
a = n->right->left; // chan a = r->left; // chan
r = a; args = list1(a);
on = syslook("chanrecv2", 1); on = syslook("chanrecv2", 1);
argtype(on, t->type); // any-1 argtype(on, t->type); // any-1
argtype(on, t->type); // any-2 argtype(on, t->type); // any-2
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
n->right = r; r->list = args;
n->rlist->n = r;
r = n; r = n;
walkexpr(r, Etop, init); walkexpr(r, Etop, init);
break; break;
case ORECV: case ORECV:
if(n->right != N) // should not happen - nonblocking is OAS w/ ORECV now.
goto recv2; if(n->right != N) {
dump("recv2", n);
fatal("chanop recv2");
}
// chanrecv1(hchan *chan any) (elem any); // chanrecv1(hchan *chan any) (elem any);
defaultlit(n->left, T); defaultlit(n->left, T);
...@@ -2978,43 +3072,17 @@ chanop(Node *n, int top, Node **init) ...@@ -2978,43 +3072,17 @@ chanop(Node *n, int top, Node **init)
} }
a = n->left; // chan a = n->left; // chan
r = a; args = list1(a);
on = syslook("chanrecv1", 1); on = syslook("chanrecv1", 1);
argtype(on, t->type); // any-1 argtype(on, t->type); // any-1
argtype(on, t->type); // any-2 argtype(on, t->type); // any-2
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
walkexpr(r, Erv, nil); walkexpr(r, Erv, nil);
break; break;
recv2:
// chanrecv3(hchan *chan any, *elem any) (pres bool);
t = fixchan(n->right->type);
if(t == T)
break;
a = n->right; // chan
r = a;
a = n->left; // elem
if(a == N) {
a = nod(OLITERAL, N, N);
a->val.ctype = CTNIL;
a->type = types[TNIL];
} else
a = nod(OADDR, a, N);
on = syslook("chanrecv3", 1);
argtype(on, t->type); // any-1
argtype(on, t->type); // any-2
r = nod(OCALL, on, r);
n->right = r;
r = n;
walkexpr(r, Etop, nil);
break;
case OSEND: case OSEND:
t = fixchan(n->left->type); t = fixchan(n->left->type);
if(t == T) if(t == T)
...@@ -3028,29 +3096,31 @@ chanop(Node *n, int top, Node **init) ...@@ -3028,29 +3096,31 @@ chanop(Node *n, int top, Node **init)
goto send2; goto send2;
// chansend1(hchan *chan any, elem any); // chansend1(hchan *chan any, elem any);
a = n->right; // e
r = a;
a = n->left; // chan a = n->left; // chan
r = list(a, r); args = list1(a);
a = n->right; // e
args = list(args, a);
on = syslook("chansend1", 1); on = syslook("chansend1", 1);
argtype(on, t->type); // any-1 argtype(on, t->type); // any-1
argtype(on, t->type); // any-2 argtype(on, t->type); // any-2
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
walkexpr(r, Etop, nil); walkexpr(r, Etop, nil);
break; break;
send2: send2:
// chansend2(hchan *chan any, val any) (pres bool); // chansend2(hchan *chan any, val any) (pres bool);
a = n->right; // e
r = a;
a = n->left; // chan a = n->left; // chan
r = list(a, r); args = list1(a);
a = n->right; // e
args = list(args, a);
on = syslook("chansend2", 1); on = syslook("chansend2", 1);
argtype(on, t->type); // any-1 argtype(on, t->type); // any-1
argtype(on, t->type); // any-2 argtype(on, t->type); // any-2
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
walkexpr(r, Etop, nil); walkexpr(r, Etop, nil);
break; break;
} }
...@@ -3084,9 +3154,9 @@ Node* ...@@ -3084,9 +3154,9 @@ Node*
arrayop(Node *n, int top) arrayop(Node *n, int top)
{ {
Node *r, *a; Node *r, *a;
NodeList *args;
Type *t, *tl; Type *t, *tl;
Node *on; Node *on;
Iter save;
int cl; int cl;
r = n; r = n;
...@@ -3103,17 +3173,18 @@ arrayop(Node *n, int top) ...@@ -3103,17 +3173,18 @@ arrayop(Node *n, int top)
if(t == T || tl == T) if(t == T || tl == T)
break; break;
args = list1(n->left); // old
a = nodintconst(t->bound); // nel a = nodintconst(t->bound); // nel
a = nod(OCONV, a, N); a = nod(OCONV, a, N);
a->type = types[TINT]; a->type = types[TINT];
r = a; args = list(args, a);
r = list(n->left, r); // old
on = syslook("arrays2d", 1); on = syslook("arrays2d", 1);
argtype(on, t); // any-1 argtype(on, t); // any-1
argtype(on, tl->type); // any-2 argtype(on, tl->type); // any-2
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
n->left = r; n->left = r;
walkexpr(n, top, nil); walkexpr(n, top, nil);
return n; return n;
...@@ -3125,7 +3196,7 @@ arrayop(Node *n, int top) ...@@ -3125,7 +3196,7 @@ arrayop(Node *n, int top)
return n; return n;
case OMAKE: case OMAKE:
cl = listcount(n->left); cl = count(n->list);
if(cl > 2) if(cl > 2)
yyerror("too many arguments to make array"); yyerror("too many arguments to make array");
...@@ -3134,32 +3205,35 @@ arrayop(Node *n, int top) ...@@ -3134,32 +3205,35 @@ arrayop(Node *n, int top)
if(t == T) if(t == T)
break; break;
a = nodintconst(t->type->width); // width // nel
a = n->list->n;
if(a == N) {
yyerror("new slice must have size");
a = nodintconst(1);
}
a = nod(OCONV, a, N); a = nod(OCONV, a, N);
a->type = types[TINT]; a->type = types[TINT];
r = a; args = list1(a);
a = listfirst(&save, &n->left); // max // max
a = listnext(&save); if(cl < 2)
if(a == N)
a = nodintconst(0); a = nodintconst(0);
else
a = n->list->next->n;
a = nod(OCONV, a, N); a = nod(OCONV, a, N);
a->type = types[TINT]; a->type = types[TINT];
r = list(a, r); args = list(args, a);
a = listfirst(&save, &n->left); // nel // width
if(a == N) { a = nodintconst(t->type->width); // width
yyerror("new slice must have size");
a = nodintconst(1);
}
a = nod(OCONV, a, N); a = nod(OCONV, a, N);
a->type = types[TINT]; a->type = types[TINT];
r = list(a, r); args = list(args, a);
on = syslook("newarray", 1); on = syslook("newarray", 1);
argtype(on, t->type); // any-1 argtype(on, t->type); // any-1
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
walkexpr(r, top, nil); walkexpr(r, top, nil);
r->type = t; // if t had a name, going through newarray lost it r->type = t; // if t had a name, going through newarray lost it
break; break;
...@@ -3172,28 +3246,15 @@ arrayop(Node *n, int top) ...@@ -3172,28 +3246,15 @@ arrayop(Node *n, int top)
if(t == T) if(t == T)
break; break;
a = nodintconst(t->type->width); // width
a = nod(OCONV, a, N);
a->type = types[TINT];
r = a;
a = nod(OCONV, n->right->right, N); // hb
a->type = types[TINT];
r = list(a, r);
a = nod(OCONV, n->right->left, N); // lb
a->type = types[TINT];
r = list(a, r);
if(t->bound >= 0) { if(t->bound >= 0) {
// static slice // static slice
a = nod(OADDR, n->left, N); // old
args = list1(a);
a = nodintconst(t->bound); // nel a = nodintconst(t->bound); // nel
a = nod(OCONV, a, N); a = nod(OCONV, a, N);
a->type = types[TINT]; a->type = types[TINT];
r = list(a, r); args = list(args, a);
a = nod(OADDR, n->left, N); // old
r = list(a, r);
on = syslook("arrayslices", 1); on = syslook("arrayslices", 1);
argtype(on, t); // any-1 argtype(on, t); // any-1
...@@ -3201,13 +3262,28 @@ arrayop(Node *n, int top) ...@@ -3201,13 +3262,28 @@ arrayop(Node *n, int top)
} else { } else {
// dynamic slice // dynamic slice
a = n->left; // old a = n->left; // old
r = list(a, r); args = list1(a);
on = syslook("arraysliced", 1); on = syslook("arraysliced", 1);
argtype(on, t->type); // any-1 argtype(on, t->type); // any-1
argtype(on, t->type); // any-2 argtype(on, t->type); // any-2
} }
r = nod(OCALL, on, r);
a = nod(OCONV, n->right->left, N); // lb
a->type = types[TINT];
args = list(args, a);
a = nod(OCONV, n->right->right, N); // hb
a->type = types[TINT];
args = list(args, a);
a = nodintconst(t->type->width); // width
a = nod(OCONV, a, N);
a->type = types[TINT];
args = list(args, a);
r = nod(OCALL, on, N);
r->list = args;
walkexpr(r, top, nil); walkexpr(r, top, nil);
break; break;
} }
...@@ -3295,7 +3371,8 @@ Node* ...@@ -3295,7 +3371,8 @@ Node*
ifacecvt(Type *tl, Node *n, int et) ifacecvt(Type *tl, Node *n, int et)
{ {
Type *tr; Type *tr;
Node *r, *a, *on; Node *r, *on;
NodeList *args;
tr = n->type; tr = n->type;
...@@ -3305,15 +3382,9 @@ ifacecvt(Type *tl, Node *n, int et) ...@@ -3305,15 +3382,9 @@ ifacecvt(Type *tl, Node *n, int et)
case T2I: case T2I:
// ifaceT2I(sigi *byte, sigt *byte, elem any) (ret any); // ifaceT2I(sigi *byte, sigt *byte, elem any) (ret any);
args = list1(typename(tl)); // sigi
a = n; // elem args = list(args, typename(tr)); // sigt
r = a; args = list(args, n); // elem
a = typename(tr); // sigt
r = list(a, r);
a = typename(tl); // sigi
r = list(a, r);
on = syslook("ifaceT2I", 1); on = syslook("ifaceT2I", 1);
argtype(on, tr); argtype(on, tr);
...@@ -3330,11 +3401,8 @@ ifacecvt(Type *tl, Node *n, int et) ...@@ -3330,11 +3401,8 @@ ifacecvt(Type *tl, Node *n, int et)
case E2I: case E2I:
case E2I2: case E2I2:
// iface[IT]2[IT][2](sigt *byte, iface any) (ret any[, ok bool]); // iface[IT]2[IT][2](sigt *byte, iface any) (ret any[, ok bool]);
a = n; // interface args = list1(typename(tl)); // sigi or sigt
r = a; args = list(args, n); // iface
a = typename(tl); // sigi or sigt
r = list(a, r);
on = syslook(ifacename[et], 1); on = syslook(ifacename[et], 1);
argtype(on, tr); argtype(on, tr);
...@@ -3344,8 +3412,8 @@ ifacecvt(Type *tl, Node *n, int et) ...@@ -3344,8 +3412,8 @@ ifacecvt(Type *tl, Node *n, int et)
case I2E: case I2E:
// TODO(rsc): Should do this in back end, without a call. // TODO(rsc): Should do this in back end, without a call.
// ifaceI2E(elem any) (ret any); // ifaceI2E(elem any) (ret any);
a = n; // interface args = list1(n); // elem
r = a;
on = syslook("ifaceI2E", 1); on = syslook("ifaceI2E", 1);
argtype(on, tr); argtype(on, tr);
argtype(on, tl); argtype(on, tl);
...@@ -3354,11 +3422,8 @@ ifacecvt(Type *tl, Node *n, int et) ...@@ -3354,11 +3422,8 @@ ifacecvt(Type *tl, Node *n, int et)
case T2E: case T2E:
// TODO(rsc): Should do this in back end for pointer case, without a call. // TODO(rsc): Should do this in back end for pointer case, without a call.
// ifaceT2E(sigt *byte, elem any) (ret any); // ifaceT2E(sigt *byte, elem any) (ret any);
a = n; // elem args = list1(typename(tr)); // sigt
r = a; args = list(args, n); // elem
a = typename(tr); // sigt
r = list(a, r);
on = syslook("ifaceT2E", 1); on = syslook("ifaceT2E", 1);
argtype(on, tr); argtype(on, tr);
...@@ -3366,7 +3431,8 @@ ifacecvt(Type *tl, Node *n, int et) ...@@ -3366,7 +3431,8 @@ ifacecvt(Type *tl, Node *n, int et)
break; break;
} }
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
walkexpr(r, Erv, nil); walkexpr(r, Erv, nil);
return r; return r;
} }
...@@ -3374,7 +3440,8 @@ ifacecvt(Type *tl, Node *n, int et) ...@@ -3374,7 +3440,8 @@ ifacecvt(Type *tl, Node *n, int et)
Node* Node*
ifaceop(Node *n) ifaceop(Node *n)
{ {
Node *r, *a, *on; Node *r, *on;
NodeList *args;
switch(n->op) { switch(n->op) {
default: default:
...@@ -3383,11 +3450,8 @@ ifaceop(Node *n) ...@@ -3383,11 +3450,8 @@ ifaceop(Node *n)
case OEQ: case OEQ:
case ONE: case ONE:
// ifaceeq(i1 any-1, i2 any-2) (ret bool); // ifaceeq(i1 any-1, i2 any-2) (ret bool);
a = n->right; // i2 args = list1(n->left); // i1
r = a; args = list(args, n->right); // i2
a = n->left; // i1
r = list(a, r);
if(!eqtype(n->left->type, n->right->type)) if(!eqtype(n->left->type, n->right->type))
fatal("ifaceop %O %T %T", n->op, n->left->type, n->right->type); fatal("ifaceop %O %T %T", n->op, n->left->type, n->right->type);
...@@ -3398,7 +3462,8 @@ ifaceop(Node *n) ...@@ -3398,7 +3462,8 @@ ifaceop(Node *n)
argtype(on, n->right->type); argtype(on, n->right->type);
argtype(on, n->left->type); argtype(on, n->left->type);
r = nod(OCALL, on, r); r = nod(OCALL, on, N);
r->list = args;
if(n->op == ONE) if(n->op == ONE)
r = nod(ONOT, r, N); r = nod(ONOT, r, N);
walkexpr(r, Erv, nil); walkexpr(r, Erv, nil);
...@@ -3407,7 +3472,7 @@ ifaceop(Node *n) ...@@ -3407,7 +3472,7 @@ ifaceop(Node *n)
} }
Node* Node*
convas(Node *n, Node **init) convas(Node *n, NodeList **init)
{ {
Node *l, *r; Node *l, *r;
Type *lt, *rt; Type *lt, *rt;
...@@ -3471,6 +3536,8 @@ out: ...@@ -3471,6 +3536,8 @@ out:
int int
colasname(Node *n) colasname(Node *n)
{ {
// TODO(rsc): can probably simplify
// once late-binding of names goes in
switch(n->op) { switch(n->op) {
case ONAME: case ONAME:
case ONONAME: case ONONAME:
...@@ -3488,7 +3555,7 @@ colasname(Node *n) ...@@ -3488,7 +3555,7 @@ colasname(Node *n)
} }
Node* Node*
old2new(Node *n, Type *t, Node **init) old2new(Node *n, Type *t, NodeList **init)
{ {
Node *l; Node *l;
...@@ -3509,23 +3576,21 @@ mixedoldnew(Node *n, Type *t) ...@@ -3509,23 +3576,21 @@ mixedoldnew(Node *n, Type *t)
return n; return n;
} }
static Node* static NodeList*
checkmixed(Node *nl, Node **init) checkmixed(NodeList *nl, NodeList **init)
{ {
Iter save; Node *a, *l;
Node *l, *n, *a; NodeList *ll, *n;
Type *t; Type *t;
int ntot, nred; int ntot, nred;
nl = rev(nl);
// first pass, check if it is a special // first pass, check if it is a special
// case of new and old declarations // case of new and old declarations
ntot = 0; // number assignments ntot = 0; // number assignments
nred = 0; // number redeclarations nred = 0; // number redeclarations
l = listfirst(&save, &nl); for(ll=nl; ll; ll=ll->next) {
while(l != N) { l = ll->n;
t = l->type; t = l->type;
l = l->left; l = l->left;
...@@ -3537,7 +3602,6 @@ checkmixed(Node *nl, Node **init) ...@@ -3537,7 +3602,6 @@ checkmixed(Node *nl, Node **init)
nred++; nred++;
} }
ntot++; ntot++;
l = listnext(&save);
} }
// test for special case // test for special case
...@@ -3547,9 +3611,9 @@ checkmixed(Node *nl, Node **init) ...@@ -3547,9 +3611,9 @@ checkmixed(Node *nl, Node **init)
if(nred == 0 || ntot <= 1 || nred == ntot) if(nred == 0 || ntot <= 1 || nred == ntot)
goto allnew; goto allnew;
n = N; n = nil;
l = listfirst(&save, &nl); for(ll=nl; ll; ll=ll->next) {
while(l != N) { l = ll->n;
t = l->type; t = l->type;
l = l->left; l = l->left;
...@@ -3558,30 +3622,29 @@ checkmixed(Node *nl, Node **init) ...@@ -3558,30 +3622,29 @@ checkmixed(Node *nl, Node **init)
a = old2new(l, t, init); a = old2new(l, t, init);
n = list(n, a); n = list(n, a);
l = listnext(&save);
} }
return rev(n); return n;
allnew: allnew:
// same as original // same as original
n = N; n = nil;
l = listfirst(&save, &nl); for(ll=nl; ll; ll=ll->next) {
while(l != N) { l = ll->n;
t = l->type; t = l->type;
l = l->left; l = l->left;
a = old2new(l, t, init); a = old2new(l, t, init);
n = list(n, a); n = list(n, a);
l = listnext(&save);
} }
return rev(n); return n;
} }
Node* Node*
colas(Node *nl, Node *nr, Node **init) colas(NodeList *ll, NodeList *lr)
{ {
Iter savel, saver; Node *l, *r, *a, *nl, *nr;
Node *l, *r, *a, *n; Iter savet;
NodeList *init, *savel, *saver, *n;
Type *t; Type *t;
int cl, cr; int cl, cr;
...@@ -3590,23 +3653,25 @@ colas(Node *nl, Node *nr, Node **init) ...@@ -3590,23 +3653,25 @@ colas(Node *nl, Node *nr, Node **init)
* return a newname-list from * return a newname-list from
* types derived from the rhs. * types derived from the rhs.
*/ */
n = N; cr = count(lr);
cr = listcount(nr); cl = count(ll);
cl = listcount(nl); init = nil;
n = nil;
/* check calls early, to give better message for a := f() */ /* check calls early, to give better message for a := f() */
if(cr == 1) { if(cr == 1) {
nr = lr->n;
switch(nr->op) { switch(nr->op) {
case OCALL: case OCALL:
if(nr->left->op == ONAME && nr->left->etype != 0) if(nr->left->op == ONAME && nr->left->etype != 0)
break; break;
walkexpr(nr->left, Erv | Etype, init); walkexpr(nr->left, Erv | Etype, &init);
if(nr->left->op == OTYPE) if(nr->left->op == OTYPE)
break; break;
goto call; goto call;
case OCALLMETH: case OCALLMETH:
case OCALLINTER: case OCALLINTER:
walkexpr(nr->left, Erv, init); walkexpr(nr->left, Erv, &init);
call: call:
convlit(nr->left, types[TFUNC]); convlit(nr->left, types[TFUNC]);
t = nr->left->type; t = nr->left->type;
...@@ -3623,39 +3688,37 @@ colas(Node *nl, Node *nr, Node **init) ...@@ -3623,39 +3688,37 @@ colas(Node *nl, Node *nr, Node **init)
goto badt; goto badt;
} }
// finish call - first half above // finish call - first half above
l = listfirst(&savel, &nl); t = structfirst(&savet, getoutarg(t));
t = structfirst(&saver, getoutarg(t));
if(t == T) if(t == T)
goto outl; goto outl;
while(l != N) { for(savel=ll; savel; savel=savel->next) {
l = savel->n;
a = mixedoldnew(l, t->type); a = mixedoldnew(l, t->type);
n = list(n, a); n = list(n, a);
l = listnext(&savel); t = structnext(&savet);
t = structnext(&saver);
} }
n = checkmixed(n, init); n = checkmixed(n, &init);
goto out; goto out;
} }
} }
if(cl != cr) { if(cl != cr) {
if(cr == 1) if(cr == 1) {
nr = lr->n;
goto multi; goto multi;
}
goto badt; goto badt;
} }
l = listfirst(&savel, &nl); for(savel=ll, saver=lr; savel != nil; savel=savel->next, saver=saver->next) {
r = listfirst(&saver, &nr); l = savel->n;
r = saver->n;
while(l != N) { walkexpr(r, Erv, &init);
walkexpr(r, Erv, init);
defaultlit(r, T); defaultlit(r, T);
a = mixedoldnew(l, r->type); a = mixedoldnew(l, r->type);
n = list(n, a); n = list(n, a);
l = listnext(&savel);
r = listnext(&saver);
} }
n = checkmixed(n, init); n = checkmixed(n, &init);
goto out; goto out;
multi: multi:
...@@ -3674,56 +3737,65 @@ multi: ...@@ -3674,56 +3737,65 @@ multi:
// if so, types are valuetype,bool // if so, types are valuetype,bool
if(cl != 2) if(cl != 2)
goto badt; goto badt;
walkexpr(nr->left, Erv, init); walkexpr(nr->left, Erv, &init);
implicitstar(&nr->left); implicitstar(&nr->left);
t = nr->left->type; t = nr->left->type;
if(!istype(t, TMAP)) if(!istype(t, TMAP))
goto badt; goto badt;
a = mixedoldnew(nl->left, t->type); a = mixedoldnew(ll->n, t->type);
n = a; n = list1(a);
a = mixedoldnew(nl->right, types[TBOOL]); a = mixedoldnew(ll->next->n, types[TBOOL]);
n = list(n, a); n = list(n, a);
n = checkmixed(n, init); n = checkmixed(n, &init);
break; break;
case ODOTTYPE: case ODOTTYPE:
// a,b := i.(T) // a,b := i.(T)
walkdottype(nr, init); walkdottype(nr, &init);
if(cl != 2) if(cl != 2)
goto badt; goto badt;
// a,b = iface // a,b = iface
a = mixedoldnew(nl->left, nr->type); a = mixedoldnew(ll->n, nr->type);
n = a; n = list1(a);
a = mixedoldnew(nl->right, types[TBOOL]); a = mixedoldnew(ll->next->n, types[TBOOL]);
n = list(n, a); n = list(n, a);
n = checkmixed(n, init); n = checkmixed(n, &init);
break; break;
case ORECV: case ORECV:
if(cl != 2) if(cl != 2)
goto badt; goto badt;
walkexpr(nr->left, Erv, init); walkexpr(nr->left, Erv, &init);
t = nr->left->type; t = nr->left->type;
if(!istype(t, TCHAN)) if(!istype(t, TCHAN))
goto badt; goto badt;
a = mixedoldnew(nl->left, t->type); a = mixedoldnew(ll->n, t->type);
n = a; n = list1(a);
a = mixedoldnew(nl->right, types[TBOOL]); a = mixedoldnew(ll->next->n, types[TBOOL]);
n = list(n, a); n = list(n, a);
n = checkmixed(n, init); n = checkmixed(n, &init);
break; break;
} }
n = rev(n); goto out;
out:
return n;
badt: badt:
nl = ll->n;
if(nl->diag == 0) { if(nl->diag == 0) {
nl->diag = 1; nl->diag = 1;
yyerror("assignment count mismatch: %d = %d", cl, cr); yyerror("assignment count mismatch: %d = %d", cl, cr);
} }
outl: outl:
return nl; n = ll;
out:
// n is the lhs of the assignment.
// init holds the list of declarations.
a = nod(OAS2, N, N);
a->list = n;
a->rlist = lr;
a->ninit = init;
a->colas = 1;
return a;
} }
/* /*
...@@ -3735,23 +3807,28 @@ outl: ...@@ -3735,23 +3807,28 @@ outl:
Node* Node*
dorange(Node *nn) dorange(Node *nn)
{ {
Node *k, *v, *m, *init; Node *k, *v, *m;
Node *n, *hv, *hc, *ha, *hk, *ohk, *on, *r, *a; Node *n, *hv, *hc, *ha, *hk, *ohk, *on, *r, *a, *as;
NodeList *init, *args;
Type *t, *th; Type *t, *th;
int local; int local;
NodeList *nl;
if(nn->op != ORANGE) if(nn->op != ORANGE)
fatal("dorange not ORANGE"); fatal("dorange not ORANGE");
k = nn->left; nl = nn->list;
v = N; k = nl->n;
if(k->op == OLIST) { if((nl = nl->next) != nil) {
v = k->right; v = nl->n;
k = k->left; nl = nl->next;
} } else
v = N;
if(nl != nil)
yyerror("too many variables in range");
n = nod(OFOR, N, N); n = nod(OFOR, N, N);
init = N; init = nil;
walkexpr(nn->right, Erv, &init); walkexpr(nn->right, Erv, &init);
implicitstar(&nn->right); implicitstar(&nn->right);
...@@ -3792,7 +3869,7 @@ ary: ...@@ -3792,7 +3869,7 @@ ary:
if(local) if(local)
k = old2new(k, hk->type, &init); k = old2new(k, hk->type, &init);
n->nbody = nod(OAS, k, hk); n->nbody = list1(nod(OAS, k, hk));
if(v != N) { if(v != N) {
if(local) if(local)
...@@ -3814,9 +3891,9 @@ map: ...@@ -3814,9 +3891,9 @@ map:
argtype(on, t->down); argtype(on, t->down);
argtype(on, t->type); argtype(on, t->type);
argtype(on, th); argtype(on, th);
r = nod(OADDR, hk, N); a = nod(OADDR, hk, N);
r = list(m, r); r = nod(OCALL, on, N);
r = nod(OCALL, on, r); r->list = list(list1(m), a);
init = list(init, r); init = list(init, r);
...@@ -3830,7 +3907,9 @@ map: ...@@ -3830,7 +3907,9 @@ map:
on = syslook("mapiternext", 1); on = syslook("mapiternext", 1);
argtype(on, th); argtype(on, th);
r = nod(OADDR, hk, N); r = nod(OADDR, hk, N);
r = nod(OCALL, on, r); args = list1(r);
r = nod(OCALL, on, N);
r->list = args;
n->nincr = r; n->nincr = r;
if(local) if(local)
...@@ -3840,8 +3919,10 @@ map: ...@@ -3840,8 +3919,10 @@ map:
argtype(on, th); argtype(on, th);
argtype(on, t->down); argtype(on, t->down);
r = nod(OADDR, hk, N); r = nod(OADDR, hk, N);
r = nod(OCALL, on, r); args = list1(r);
n->nbody = nod(OAS, k, r); r = nod(OCALL, on, N);
r->list = args;
n->nbody = list1(nod(OAS, k, r));
goto out; goto out;
} }
if(local) if(local)
...@@ -3851,8 +3932,13 @@ map: ...@@ -3851,8 +3932,13 @@ map:
argtype(on, t->down); argtype(on, t->down);
argtype(on, t->type); argtype(on, t->type);
r = nod(OADDR, hk, N); r = nod(OADDR, hk, N);
r = nod(OCALL, on, r); args = list1(r);
n->nbody = nod(OAS, nod(OLIST, k, v), r); r = nod(OCALL, on, N);
r->list = args;
as = nod(OAS2, N, N);
as->list = list(list1(k), v);
as->rlist = list1(r);
n->nbody = list1(as);
goto out; goto out;
chan: chan:
...@@ -3872,12 +3958,14 @@ chan: ...@@ -3872,12 +3958,14 @@ chan:
a = nod(OAS, hv, a); a = nod(OAS, hv, a);
init = list(init, a); init = list(init, a);
n->ntest = nod(ONOT, nod(OCLOSED, hc, N), N); a = nod(OCLOSED, N, N);
a->list = list1(hc);
n->ntest = nod(ONOT, a, N);
n->nincr = nod(OAS, hv, nod(ORECV, hc, N)); n->nincr = nod(OAS, hv, nod(ORECV, hc, N));
if(local) if(local)
k = old2new(k, hv->type, &init); k = old2new(k, hv->type, &init);
n->nbody = nod(OAS, k, hv); n->nbody = list1(nod(OAS, k, hv));
goto out; goto out;
...@@ -3915,15 +4003,17 @@ strng: ...@@ -3915,15 +4003,17 @@ strng:
if(v != N) { if(v != N) {
// hk,v = stringiter2(ha, hk) // hk,v = stringiter2(ha, hk)
on = syslook("stringiter2", 0); on = syslook("stringiter2", 0);
// argtype(on, v->type); a = nod(OCALL, on, N);
a = list(ha, nodintconst(0)); a->list = list(list1(ha), nodintconst(0));
a = nod(OCALL, on, a); as = nod(OAS2, N, N);
a = nod(OAS, list(hk, hv), a); as->list = list(list1(hk), hv);
as->rlist = list1(a);
a = as;
} else { } else {
// hk = stringiter(ha, hk) // hk = stringiter(ha, hk)
on = syslook("stringiter", 0); on = syslook("stringiter", 0);
a = list(ha, nodintconst(0)); a = nod(OCALL, on, N);
a = nod(OCALL, on, a); a->list = list(list1(ha), nodintconst(0));
a = nod(OAS, hk, a); a = nod(OAS, hk, a);
} }
init = list(init, a); init = list(init, a);
...@@ -3935,21 +4025,24 @@ strng: ...@@ -3935,21 +4025,24 @@ strng:
if(v != N) { if(v != N) {
// hk,hv = stringiter2(ha, hk) // hk,hv = stringiter2(ha, hk)
on = syslook("stringiter2", 0); on = syslook("stringiter2", 0);
a = list(ha, hk); a = nod(OCALL, on, N);
a = nod(OCALL, on, a); a->list = list(list1(ha), hk);
a = nod(OAS, list(hk, hv), a); as = nod(OAS2, N, N);
as->list = list(list1(hk), hv);
as->rlist = list1(a);
a = as;
} else { } else {
// hk = stringiter(ha, hk) // hk = stringiter(ha, hk)
on = syslook("stringiter", 0); on = syslook("stringiter", 0);
a = list(ha, hk); a = nod(OCALL, on, N);
a = nod(OCALL, on, a); a->list = list(list1(ha), hk);
a = nod(OAS, hk, a); a = nod(OAS, hk, a);
} }
n->nincr = list(n->nincr, a); n->nincr = a;
// k,ohk[,v] = ohk,hk,[,hv] // k,ohk[,v] = ohk,hk,[,hv]
a = nod(OAS, k, ohk); a = nod(OAS, k, ohk);
n->nbody = a; n->nbody = list1(a);
a = nod(OAS, ohk, hk); a = nod(OAS, ohk, hk);
n->nbody = list(n->nbody, a); n->nbody = list(n->nbody, a);
if(v != N) { if(v != N) {
...@@ -3958,7 +4051,7 @@ strng: ...@@ -3958,7 +4051,7 @@ strng:
} }
out: out:
n->ninit = list(n->ninit, init); n->ninit = concat(n->ninit, init);
return n; return n;
} }
...@@ -3970,71 +4063,57 @@ out: ...@@ -3970,71 +4063,57 @@ out:
* then it is done first. otherwise must * then it is done first. otherwise must
* make temp variables * make temp variables
*/ */
Node* NodeList*
reorder1(Node *n) reorder1(NodeList *all)
{ {
Iter save; Node *f, *a, *n;
Node *l, *r, *f, *a, *g; NodeList *l, *r, *g;
int c, t; int c, t;
l = listfirst(&save, &n);
c = 0; // function calls c = 0; // function calls
t = 0; // total parameters t = 0; // total parameters
loop1: for(l=all; l; l=l->next) {
if(l == N) { n = l->n;
if(c == 0 || t == 1) t++;
return n; ullmancalc(n);
goto pass2; if(n->ullman >= UINF)
c++;
} }
if(l->op == OLIST) if(c == 0 || t == 1)
fatal("reorder1 OLIST"); return all;
t++; g = nil; // fncalls assigned to tempnames
ullmancalc(l);
if(l->ullman >= UINF)
c++;
l = listnext(&save);
goto loop1;
pass2:
l = listfirst(&save, &n);
g = N; // fncalls assigned to tempnames
f = N; // one fncall assigned to stack f = N; // one fncall assigned to stack
r = N; // non fncalls and tempnames assigned to stack r = nil; // non fncalls and tempnames assigned to stack
loop2:
if(l == N) {
r = rev(r);
g = rev(g);
f = list(g, f);
r = list(f, r);
return r;
}
ullmancalc(l);
if(l->ullman < UINF) {
r = list(l, r);
goto more;
}
if(f == N) {
f = l;
goto more;
}
// make assignment of fncall to tempname for(l=all; l; l=l->next) {
a = nod(OXXX, N, N); n = l->n;
tempname(a, l->right->type); ullmancalc(n);
a = nod(OAS, a, l->right); if(n->ullman < UINF) {
g = list(a, g); r = list(r, n);
continue;
}
if(f == N) {
f = n;
continue;
}
// put normal arg assignment on list // make assignment of fncall to tempname
// with fncall replaced by tempname a = nod(OXXX, N, N);
l->right = a->left; tempname(a, n->right->type);
r = list(l, r); a = nod(OAS, a, n->right);
g = list(g, a);
// put normal arg assignment on list
// with fncall replaced by tempname
n->right = a->left;
r = list(r, n);
}
more: if(f != N)
l = listnext(&save); g = list(g, f);
goto loop2; return concat(g, r);
} }
/* /*
...@@ -4046,8 +4125,8 @@ more: ...@@ -4046,8 +4125,8 @@ more:
int int
vmatch2(Node *l, Node *r) vmatch2(Node *l, Node *r)
{ {
NodeList *ll;
loop:
/* /*
* isolate all right sides * isolate all right sides
*/ */
...@@ -4061,17 +4140,21 @@ loop: ...@@ -4061,17 +4140,21 @@ loop:
case OLITERAL: case OLITERAL:
return 0; return 0;
} }
if(vmatch2(l, r->left))
return 1;
if(vmatch2(l, r->right)) if(vmatch2(l, r->right))
return 1; return 1;
r = r->left; for(ll=r->list; ll; ll=ll->next)
goto loop; if(vmatch2(l, ll->n))
return 1;
return 0;
} }
int int
vmatch1(Node *l, Node *r) vmatch1(Node *l, Node *r)
{ {
NodeList *ll;
loop:
/* /*
* isolate all left sides * isolate all left sides
*/ */
...@@ -4084,76 +4167,59 @@ loop: ...@@ -4084,76 +4167,59 @@ loop:
case OLITERAL: case OLITERAL:
return 0; return 0;
} }
if(vmatch1(l->left, r))
return 1;
if(vmatch1(l->right, r)) if(vmatch1(l->right, r))
return 1; return 1;
l = l->left; for(ll=l->list; ll; ll=ll->next)
goto loop; if(vmatch1(ll->n, r))
return 1;
return 0;
} }
Node* NodeList*
reorder3(Node *n) reorder3(NodeList *all)
{ {
Iter save1, save2; Node *n1, *n2, *q;
Node *l1, *l2, *q, *r;
int c1, c2; int c1, c2;
NodeList *l1, *l2, *r;
r = N; r = nil;
for(l1=all, c1=0; l1; l1=l1->next, c1++) {
l1 = listfirst(&save1, &n); n1 = l1->n;
c1 = 0; for(l2=all, c2=0; l2; l2=l2->next, c2++) {
n2 = l2->n;
while(l1 != N) {
l2 = listfirst(&save2, &n);
c2 = 0;
while(l2 != N) {
if(c2 > c1) { if(c2 > c1) {
if(vmatch1(l1->left, l2->right)) { if(vmatch1(n1->left, n2->right)) {
q = nod(OXXX, N, N); q = nod(OXXX, N, N);
tempname(q, l1->right->type); tempname(q, n1->right->type);
q = nod(OAS, l1->left, q); q = nod(OAS, n1->left, q);
l1->left = q->right; n1->left = q->right;
r = list(r, q); r = list(r, q);
break; break;
} }
} }
l2 = listnext(&save2);
c2++;
} }
l1 = listnext(&save1);
c1++;
}
if(r == N)
return n;
q = N;
l1 = listfirst(&save1, &n);
while(l1 != N) {
q = list(q, l1);
l1 = listnext(&save1);
}
r = rev(r);
l1 = listfirst(&save1, &r);
while(l1 != N) {
q = list(q, l1);
l1 = listnext(&save1);
} }
return concat(all, r);
q = rev(q);
//dump("res", q);
return q;
} }
Node* NodeList*
reorder4(Node *n) reorder4(NodeList *ll)
{ {
/* /*
* from ascompat[te] * from ascompat[te]
* return c,d * return c,d
* return expression assigned to output * return expression assigned to output
* parameters. there may be no problems. * parameters. there may be no problems.
*
* TODO(rsc): i don't believe that.
* func f() (a, b int) {
* a, b = 1, 2;
* return b, a;
* }
*/ */
return n; return ll;
} }
static void static void
...@@ -4178,12 +4244,13 @@ fielddup(Node *n, Node *hash[], ulong nhash) ...@@ -4178,12 +4244,13 @@ fielddup(Node *n, Node *hash[], ulong nhash)
} }
Node* Node*
structlit(Node *n, Node *var, Node **init) structlit(Node *n, Node *var, NodeList **init)
{ {
Iter savel, saver; Iter savel;
Type *l, *t; Type *l, *t;
Node *r, *a; Node *r, *a;
Node* hash[101]; Node* hash[101];
NodeList *nl;
int nerr; int nerr;
nerr = nerrors; nerr = nerrors;
...@@ -4196,17 +4263,13 @@ structlit(Node *n, Node *var, Node **init) ...@@ -4196,17 +4263,13 @@ structlit(Node *n, Node *var, Node **init)
tempname(var, t); tempname(var, t);
} }
r = listfirst(&saver, &n->left); nl = n->list;
if(r != N && r->op == OEMPTY) if(nl == nil || nl->n->op == OKEY)
r = N;
if(r == N)
goto keyval; // must clear structure
if(r->op == OKEY)
goto keyval; goto keyval;
l = structfirst(&savel, &n->type);
while(r != N) { l = structfirst(&savel, &n->type);
for(; nl; nl=nl->next) {
r = nl->n;
// assignment to every field // assignment to every field
if(l == T) if(l == T)
break; break;
...@@ -4224,11 +4287,10 @@ structlit(Node *n, Node *var, Node **init) ...@@ -4224,11 +4287,10 @@ structlit(Node *n, Node *var, Node **init)
*init = list(*init, a); *init = list(*init, a);
l = structnext(&savel); l = structnext(&savel);
r = listnext(&saver);
} }
if(l != T) if(l != T)
yyerror("struct literal expect expr of type %T", l); yyerror("struct literal expect expr of type %T", l);
if(r != N) if(nl != nil)
yyerror("struct literal too many expressions"); yyerror("struct literal too many expressions");
return var; return var;
...@@ -4238,7 +4300,9 @@ keyval: ...@@ -4238,7 +4300,9 @@ keyval:
walkexpr(a, Etop, init); walkexpr(a, Etop, init);
*init = list(*init, a); *init = list(*init, a);
while(r != N) { for(; nl; nl=nl->next) {
r = nl->n;
// assignment to field:value elements // assignment to field:value elements
if(r->op != OKEY) { if(r->op != OKEY) {
yyerror("mixture of field:value and value initializers"); yyerror("mixture of field:value and value initializers");
...@@ -4257,8 +4321,6 @@ keyval: ...@@ -4257,8 +4321,6 @@ keyval:
break; break;
*init = list(*init, a); *init = list(*init, a);
r = listnext(&saver);
} }
return var; return var;
} }
...@@ -4287,11 +4349,11 @@ indexdup(Node *n, Node *hash[], ulong nhash) ...@@ -4287,11 +4349,11 @@ indexdup(Node *n, Node *hash[], ulong nhash)
} }
Node* Node*
arraylit(Node *n, Node *var, Node **init) arraylit(Node *n, Node *var, NodeList **init)
{ {
Iter saver;
Type *t; Type *t;
Node *r, *a; Node *r, *a;
NodeList *l;
long ninit, b; long ninit, b;
Node* hash[101]; Node* hash[101];
int nerr; int nerr;
...@@ -4305,11 +4367,8 @@ arraylit(Node *n, Node *var, Node **init) ...@@ -4305,11 +4367,8 @@ arraylit(Node *n, Node *var, Node **init)
ninit = 0; ninit = 0;
b = 0; b = 0;
r = listfirst(&saver, &n->left); for(l=n->list; l; l=l->next) {
if(r != N && r->op == OEMPTY) r = l->n;
r = N;
while(r != N) {
if(r->op == OKEY) { if(r->op == OKEY) {
evconst(r->left); evconst(r->left);
b = nonnegconst(r->left); b = nonnegconst(r->left);
...@@ -4317,7 +4376,6 @@ arraylit(Node *n, Node *var, Node **init) ...@@ -4317,7 +4376,6 @@ arraylit(Node *n, Node *var, Node **init)
b++; b++;
if(b > ninit) if(b > ninit)
ninit = b; ninit = b;
r = listnext(&saver);
} }
b = t->bound; b = t->bound;
...@@ -4336,7 +4394,8 @@ arraylit(Node *n, Node *var, Node **init) ...@@ -4336,7 +4394,8 @@ arraylit(Node *n, Node *var, Node **init)
if(b < 0) { if(b < 0) {
// slice // slice
a = nod(OMAKE, nod(OLIST, typenod(t), nodintconst(ninit)), N); a = nod(OMAKE, N, N);
a->list = list(list1(typenod(t)), nodintconst(ninit));
a = nod(OAS, var, a); a = nod(OAS, var, a);
walkexpr(a, Etop, init); walkexpr(a, Etop, init);
*init = list(*init, a); *init = list(*init, a);
...@@ -4351,12 +4410,9 @@ arraylit(Node *n, Node *var, Node **init) ...@@ -4351,12 +4410,9 @@ arraylit(Node *n, Node *var, Node **init)
} }
b = 0; b = 0;
r = listfirst(&saver, &n->left);
if(r != N && r->op == OEMPTY)
r = N;
memset(hash, 0, sizeof(hash)); memset(hash, 0, sizeof(hash));
while(r != N) { for(l=n->list; l; l=l->next) {
r = l->n;
// build list of var[c] = expr // build list of var[c] = expr
if(r->op == OKEY) { if(r->op == OKEY) {
b = nonnegconst(r->left); b = nonnegconst(r->left);
...@@ -4385,8 +4441,6 @@ arraylit(Node *n, Node *var, Node **init) ...@@ -4385,8 +4441,6 @@ arraylit(Node *n, Node *var, Node **init)
*init = list(*init, a); *init = list(*init, a);
b++; b++;
r = listnext(&saver);
} }
return var; return var;
} }
...@@ -4447,12 +4501,12 @@ keydup(Node *n, Node *hash[], ulong nhash) ...@@ -4447,12 +4501,12 @@ keydup(Node *n, Node *hash[], ulong nhash)
} }
Node* Node*
maplit(Node *n, Node *var, Node **init) maplit(Node *n, Node *var, NodeList **init)
{ {
Iter saver;
Type *t; Type *t;
Node *r, *a; Node *r, *a;
Node* hash[101]; Node* hash[101];
NodeList *l;
int nerr; int nerr;
nerr = nerrors; nerr = nerrors;
...@@ -4465,20 +4519,15 @@ maplit(Node *n, Node *var, Node **init) ...@@ -4465,20 +4519,15 @@ maplit(Node *n, Node *var, Node **init)
tempname(var, t); tempname(var, t);
} }
a = nod(OMAKE, typenod(t), N); a = nod(OMAKE, N, N);
a->list = list1(typenod(t));
a = nod(OAS, var, a); a = nod(OAS, var, a);
walkexpr(a, Etop, init); walkexpr(a, Etop, init);
*init = list(*init, a); *init = list(*init, a);
r = listfirst(&saver, &n->left);
if(r != N && r->op == OEMPTY)
r = N;
memset(hash, 0, sizeof(hash)); memset(hash, 0, sizeof(hash));
while(r != N) { for(l=n->list; l; l=l->next) {
if(r == N) r = l->n;
break;
if(r->op != OKEY) { if(r->op != OKEY) {
yyerror("map literal must have key:value pairs"); yyerror("map literal must have key:value pairs");
break; break;
...@@ -4496,8 +4545,6 @@ maplit(Node *n, Node *var, Node **init) ...@@ -4496,8 +4545,6 @@ maplit(Node *n, Node *var, Node **init)
break; break;
*init = list(*init, a); *init = list(*init, a);
r = listnext(&saver);
} }
return var; return var;
} }
...@@ -4573,14 +4620,15 @@ addrescapes(Node *n) ...@@ -4573,14 +4620,15 @@ addrescapes(Node *n)
* generate and return code to allocate * generate and return code to allocate
* copies of escaped parameters to the heap. * copies of escaped parameters to the heap.
*/ */
Node* NodeList*
paramstoheap(Type **argin) paramstoheap(Type **argin)
{ {
Type *t; Type *t;
Iter savet; Iter savet;
Node *v, *nn; Node *v;
NodeList *nn;
nn = N; nn = nil;
for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) { for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
v = t->nname; v = t->nname;
if(v == N || !(v->class & PHEAP)) if(v == N || !(v->class & PHEAP))
...@@ -4601,9 +4649,9 @@ paramstoheap(Type **argin) ...@@ -4601,9 +4649,9 @@ paramstoheap(Type **argin)
void void
heapmoves(void) heapmoves(void)
{ {
Node *nn; NodeList *nn;
nn = paramstoheap(getthis(curfn->type)); nn = paramstoheap(getthis(curfn->type));
nn = list(nn, paramstoheap(getinarg(curfn->type))); nn = concat(nn, paramstoheap(getinarg(curfn->type)));
curfn->enter = list(curfn->enter, nn); curfn->enter = concat(curfn->enter, nn);
} }
...@@ -431,13 +431,6 @@ sys·chanrecv2(Hchan* c, ...) ...@@ -431,13 +431,6 @@ sys·chanrecv2(Hchan* c, ...)
chanrecv(c, ae, ap); chanrecv(c, ae, ap);
} }
// chanrecv3(hchan *chan any, elem *any) (pres bool);
void
sys·chanrecv3(Hchan* c, byte* ep, byte pres)
{
chanrecv(c, ep, &pres);
}
// newselect(size uint32) (sel *byte); // newselect(size uint32) (sel *byte);
void void
sys·newselect(int32 size, ...) sys·newselect(int32 size, ...)
......
...@@ -99,8 +99,7 @@ throw: interface conversion ...@@ -99,8 +99,7 @@ throw: interface conversion
panic PC=xxx panic PC=xxx
=========== bugs/bug159.go =========== bugs/bug159.go
xyz: expected 1 2 3 got 3 2 1 abc: expected 4 5 6 got 4 4 -4
abc: expected 4 5 6 got -4 4 4
BUG: bug159 BUG: bug159
=========== bugs/bug162.go =========== bugs/bug162.go
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment