Commit 26097317 authored by Russ Cox's avatar Russ Cox

delay range processing. old2new is gone

R=ken
OCL=32780
CL=32780
parent 54b40372
...@@ -30,6 +30,7 @@ OFILES=\ ...@@ -30,6 +30,7 @@ OFILES=\
mparith3.$O\ mparith3.$O\
obj.$O\ obj.$O\
print.$O\ print.$O\
range.$O\
reflect.$O\ reflect.$O\
select.$O\ select.$O\
sinit.$O\ sinit.$O\
......
...@@ -594,39 +594,12 @@ colasname(Node *n) ...@@ -594,39 +594,12 @@ colasname(Node *n)
return 0; return 0;
} }
Node* void
old2new(Node *n, Type *t, NodeList **init) colasdefn(NodeList *left, Node *defn)
{
Node *l;
if(!colasname(n)) {
yyerror("left side of := must be a name");
return n;
}
if(t != T && t->funarg) {
yyerror("use of multi func value as single value in :=");
return n;
}
l = newname(n->sym);
dodclvar(l, t, init);
return l;
}
Node*
colas(NodeList *left, NodeList *right)
{ {
int nnew; int nnew;
Node *n, *as;
NodeList *l; NodeList *l;
Node *n;
if(count(left) == 1 && count(right) == 1)
as = nod(OAS, left->n, right->n);
else {
as = nod(OAS2, N, N);
as->list = left;
as->rlist = right;
}
as->colas = 1;
nnew = 0; nnew = 0;
for(l=left; l; l=l->next) { for(l=left; l; l=l->next) {
...@@ -640,14 +613,34 @@ colas(NodeList *left, NodeList *right) ...@@ -640,14 +613,34 @@ colas(NodeList *left, NodeList *right)
nnew++; nnew++;
n = newname(n->sym); n = newname(n->sym);
declare(n, dclcontext); declare(n, dclcontext);
if(as->op == OAS) n->defn = defn;
as->left = n; defn->ninit = list(defn->ninit, nod(ODCL, n, N));
n->defn = as;
as->ninit = list(as->ninit, nod(ODCL, n, N));
l->n = n; l->n = n;
} }
if(nnew == 0) if(nnew == 0)
yyerror("no new variables on left side of :="); yyerror("no new variables on left side of :=");
}
Node*
colas(NodeList *left, NodeList *right)
{
Node *as;
as = nod(OAS2, N, N);
as->list = left;
as->rlist = right;
as->colas = 1;
colasdefn(left, as);
// make the tree prettier; not necessary
if(count(left) == 1 && count(right) == 1) {
as->left = as->list->n;
as->right = as->rlist->n;
as->list = nil;
as->rlist = nil;
as->op = OAS;
}
return as; return as;
} }
......
...@@ -332,7 +332,7 @@ enum ...@@ -332,7 +332,7 @@ enum
OCOMPSLICE, OCOMPMAP, OCOMPSLICE, OCOMPMAP,
OCONV, OCONVNOP, OCONVA2S, OCONVIFACE, OCONVSLICE, OCONV, OCONVNOP, OCONVA2S, OCONVIFACE, OCONVSLICE,
ODCL, ODCLFUNC, ODCLFIELD, ODCLARG, ODCL, ODCLFUNC, ODCLFIELD, ODCLARG,
ODOT, ODOTPTR, ODOTMETH, ODOTINTER, ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT,
ODOTTYPE, ODOTTYPE,
OEQ, ONE, OLT, OLE, OGE, OGT, OEQ, ONE, OLT, OLE, OGE, OGT,
OFUNC, OFUNC,
...@@ -948,6 +948,7 @@ void walkconv(Node**, NodeList**); ...@@ -948,6 +948,7 @@ void walkconv(Node**, NodeList**);
void walkdottype(Node*, NodeList**); void walkdottype(Node*, NodeList**);
void walkas(Node*); void walkas(Node*);
void walkswitch(Node*); void walkswitch(Node*);
void walkrange(Node*);
void walkselect(Node*); void walkselect(Node*);
void walkdot(Node*, NodeList**); void walkdot(Node*, NodeList**);
void walkexpr(Node**, NodeList**); void walkexpr(Node**, NodeList**);
...@@ -967,22 +968,22 @@ void ifacecheck(Type*, Type*, int, int); ...@@ -967,22 +968,22 @@ void ifacecheck(Type*, Type*, int, int);
void runifacechecks(void); void runifacechecks(void);
Node* convas(Node*, NodeList**); Node* convas(Node*, NodeList**);
Node* colas(NodeList*, NodeList*); Node* colas(NodeList*, NodeList*);
Node* dorange(Node*); void colasdefn(NodeList*, Node*);
NodeList* reorder1(NodeList*); NodeList* reorder1(NodeList*);
NodeList* reorder3(NodeList*); NodeList* reorder3(NodeList*);
NodeList* reorder4(NodeList*); NodeList* reorder4(NodeList*);
Node* structlit(Node*, Node*, NodeList**); Node* structlit(Node*, Node*, NodeList**);
Node* arraylit(Node*, Node*, NodeList**); Node* arraylit(Node*, Node*, NodeList**);
Node* maplit(Node*, Node*, NodeList**); Node* maplit(Node*, Node*, NodeList**);
Node* selectas(Node*, Node*, NodeList**);
Node* old2new(Node*, Type*, NodeList**);
void heapmoves(void); void heapmoves(void);
void walkdeflist(NodeList*); void walkdeflist(NodeList*);
void walkdef(Node*); void walkdef(Node*);
void typechecklist(NodeList*, int); void typechecklist(NodeList*, int);
void typecheckswitch(Node*); void typecheckswitch(Node*);
void typecheckselect(Node*); void typecheckselect(Node*);
void typecheckrange(Node*);
Node* typecheckconv(Node*, Node*, Type*, int); Node* typecheckconv(Node*, Node*, Type*, int);
int checkconv(Type*, Type*, int, int*, int*);
Node* typecheck(Node**, int); Node* typecheck(Node**, int);
/* /*
......
...@@ -464,8 +464,7 @@ simple_stmt: ...@@ -464,8 +464,7 @@ simple_stmt:
case: case:
LCASE expr_or_type_list ':' LCASE expr_or_type_list ':'
{ {
int e; Node *n, *ntype;
Node *n;
// will be converted to OCASE // will be converted to OCASE
// right will point to next case // right will point to next case
...@@ -474,29 +473,18 @@ case: ...@@ -474,29 +473,18 @@ case:
$$ = nod(OXCASE, N, N); $$ = nod(OXCASE, N, N);
if(typeswvar != N && typeswvar->right != N) { if(typeswvar != N && typeswvar->right != N) {
// type switch // type switch
n = $2->n; ntype = $2->n;
if($2->next != nil) if($2->next != nil)
yyerror("type switch case cannot be list"); yyerror("type switch case cannot be list");
if(n->op == OLITERAL && n->val.ctype == CTNIL) { if(ntype->op == OLITERAL && ntype->val.ctype == CTNIL) {
// case nil // case nil
$$->list = list1(nod(OTYPECASE, N, N)); $$->list = list1(nod(OTYPECASE, N, N));
break; break;
} }
n = newname(typeswvar->right->sym);
// TODO: move declare(n, dclcontext);
e = nerrors; n->ntype = ntype;
typecheck(&n, Etype | Erv); $$->list = list1(nod(OTYPECASE, n, N));
if(n->op == OTYPE) {
n = old2new(typeswvar->right, n->type, &$$->ninit);
$$->list = list1(nod(OTYPECASE, n, N));
break;
}
// maybe typecheck found problems that keep
// e from being valid even outside a type switch.
// only complain if typecheck didn't print new errors.
if(nerrors == e)
yyerror("non-type case in type switch");
$$->diag = 1;
} else { } else {
// expr switch // expr switch
$$->list = $2; $$->list = $2;
...@@ -519,7 +507,6 @@ case: ...@@ -519,7 +507,6 @@ case:
// done in casebody() // done in casebody()
poptodcl(); poptodcl();
$$ = nod(OXCASE, N, N); $$ = nod(OXCASE, N, N);
// $$->list = list1(nod(OAS, selectas($2, $4, &$$->ninit), $4));
$$->list = list1(colas(list1($2), list1($4))); $$->list = list1(colas(list1($2), list1($4)));
} }
| LDEFAULT ':' | LDEFAULT ':'
...@@ -590,7 +577,8 @@ range_stmt: ...@@ -590,7 +577,8 @@ range_stmt:
{ {
$$ = nod(ORANGE, N, $4); $$ = nod(ORANGE, N, $4);
$$->list = $1; $$->list = $1;
$$->etype = 1; $$->colas = 1;
colasdefn($1, $$);
} }
for_header: for_header:
...@@ -612,9 +600,6 @@ for_header: ...@@ -612,9 +600,6 @@ for_header:
$$->ntest = $1; $$->ntest = $1;
} }
| range_stmt | range_stmt
{
$$ = dorange($1);
}
for_body: for_body:
for_header loop_body for_header loop_body
...@@ -850,8 +835,7 @@ pexpr: ...@@ -850,8 +835,7 @@ pexpr:
$$ = oldname(s); $$ = oldname(s);
break; break;
} }
$$ = nod(ODOT, $1, newname($3)); $$ = nod(OXDOT, $1, newname($3));
$$ = adddot($$);
} }
| '(' expr_or_type ')' | '(' expr_or_type ')'
{ {
...@@ -1041,8 +1025,7 @@ dotname: ...@@ -1041,8 +1025,7 @@ dotname:
$$ = oldname(s); $$ = oldname(s);
break; break;
} }
$$ = nod(ODOT, $1, newname($3)); $$ = nod(OXDOT, $1, newname($3));
$$ = adddot($$);
} }
othertype: othertype:
......
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
* range
*/
#include "go.h"
void
typecheckrange(Node *n)
{
int op, et;
Type *t, *t1, *t2;
Node *v1, *v2;
NodeList *ll;
// delicate little dance. see typecheckas2
for(ll=n->list; ll; ll=ll->next)
if(ll->n->defn != n)
typecheck(&ll->n, Erv);
typecheck(&n->right, Erv);
if((t = n->right->type) == T)
goto out;
n->type = t;
switch(t->etype) {
default:
yyerror("cannot range over %+N", n->right);
goto out;
case TARRAY:
t1 = types[TINT];
t2 = t->type;
break;
case TMAP:
t1 = t->down;
t2 = t->type;
break;
case TCHAN:
t1 = t->type;
t2 = nil;
if(count(n->list) == 2)
goto toomany;
break;
case TSTRING:
t1 = types[TINT];
t2 = types[TINT];
break;
}
if(count(n->list) > 2) {
toomany:
yyerror("too many variables in range");
}
v1 = n->list->n;
v2 = N;
if(n->list->next)
v2 = n->list->next->n;
if(v1->defn == n)
v1->type = t1;
else if(v1->type != T && checkconv(t1, v1->type, 0, &op, &et) < 0)
yyerror("cannot assign type %T to %+N", t1, v1);
if(v2) {
if(v2->defn == n)
v2->type = t2;
else if(v2->type != T && checkconv(t2, v2->type, 0, &op, &et) < 0)
yyerror("cannot assign type %T to %+N", t1, v1);
}
out:
typechecklist(n->nbody, Etop);
// second half of dance
n->typecheck = 1;
for(ll=n->list; ll; ll=ll->next)
if(ll->n->typecheck == 0)
typecheck(&ll->n, Erv);
}
void
walkrange(Node *n)
{
Node *ohv1, *hv1, *hv2; // hidden (old) val 1, 2
Node *ha, *hit; // hidden aggregate, iterator
Node *a, *v1, *v2; // not hidden aggregate, val 1, 2
Node *fn;
NodeList *body, *init;
Type *th, *t;
t = n->type;
init = nil;
a = n->right;
if(t->etype == TSTRING && !eqtype(t, types[TSTRING])) {
a = nod(OCONV, n->right, N);
a->type = types[TSTRING];
}
ha = nod(OXXX, N, N);
tempname(ha, a->type);
init = list(init, nod(OAS, ha, a));
v1 = n->list->n;
hv1 = N;
v2 = N;
if(n->list->next)
v2 = n->list->next->n;
hv2 = N;
switch(t->etype) {
default:
fatal("walkrange");
case TARRAY:
hv1 = nod(OXXX, N, n);
tempname(hv1, v1->type);
init = list(init, nod(OAS, hv1, N));
n->ntest = nod(OLT, hv1, nod(OLEN, ha, N));
n->nincr = nod(OASOP, hv1, nodintconst(1));
n->nincr->etype = OADD;
body = list1(nod(OAS, v1, hv1));
if(v2)
body = list(body, nod(OAS, v2, nod(OINDEX, ha, hv1)));
break;
case TMAP:
th = typ(TARRAY);
th->type = ptrto(types[TUINT8]);
th->bound = (sizeof(struct Hiter) + widthptr - 1) / widthptr;
hit = nod(OXXX, N, N);
tempname(hit, th);
fn = syslook("mapiterinit", 1);
argtype(fn, t->down);
argtype(fn, t->type);
argtype(fn, th);
init = list(init, mkcall1(fn, T, nil, ha, nod(OADDR, hit, N)));
n->ntest = nod(ONE, nod(OINDEX, hit, nodintconst(0)), nodnil());
fn = syslook("mapiternext", 1);
argtype(fn, th);
n->nincr = mkcall1(fn, T, nil, nod(OADDR, hit, N));
if(v2 == N) {
fn = syslook("mapiter1", 1);
argtype(fn, th);
argtype(fn, t->down);
a = nod(OAS, v1, mkcall1(fn, t->down, nil, nod(OADDR, hit, N)));
} else {
fn = syslook("mapiter2", 1);
argtype(fn, th);
argtype(fn, t->down);
argtype(fn, t->type);
a = nod(OAS2, N, N);
a->list = list(list1(v1), v2);
a->rlist = list1(mkcall1(fn, getoutargx(fn->type), nil, nod(OADDR, hit, N)));
}
body = list1(a);
break;
case TCHAN:
hv1 = nod(OXXX, N, n);
tempname(hv1, v1->type);
n->ntest = nod(ONOT, nod(OCLOSED, ha, N), N);
n->ntest->ninit = list1(nod(OAS, hv1, nod(ORECV, ha, N)));
body = list1(nod(OAS, v1, hv1));
break;
case TSTRING:
ohv1 = nod(OXXX, N, N);
tempname(ohv1, types[TINT]);
hv1 = nod(OXXX, N, N);
tempname(hv1, types[TINT]);
init = list(init, nod(OAS, hv1, N));
if(v2 == N)
a = nod(OAS, hv1, mkcall("stringiter", types[TINT], nil, ha, hv1));
else {
hv2 = nod(OXXX, N, N);
tempname(hv2, types[TINT]);
a = nod(OAS2, N, N);
a->list = list(list1(hv1), hv2);
fn = syslook("stringiter2", 0);
a->rlist = list1(mkcall1(fn, getoutargx(fn->type), nil, ha, hv1));
}
n->ntest = nod(ONE, hv1, nodintconst(0));
n->ntest->ninit = list(list1(nod(OAS, ohv1, hv1)), a);
body = list1(nod(OAS, v1, ohv1));
if(v2 != N)
body = list(body, nod(OAS, v2, hv2));
break;
}
n->op = OFOR;
typechecklist(init, Etop);
n->ninit = concat(n->ninit, init);
typechecklist(n->ntest->ninit, Etop);
typecheck(&n->ntest, Erv);
typecheck(&n->nincr, Etop);
typechecklist(body, Etop);
n->nbody = concat(body, n->nbody);
walkstmt(&n);
}
...@@ -8,32 +8,6 @@ ...@@ -8,32 +8,6 @@
#include "go.h" #include "go.h"
/*
* declare v in
* case v := <-chan // select and switch
* called during parse
*/
Node*
selectas(Node *name, Node *expr, NodeList **init)
{
Type *t;
if(expr == N || expr->op != ORECV)
goto bad;
walkexpr(&expr->left, init);
t = expr->left->type;
if(t == T)
goto bad;
if(t->etype != TCHAN)
goto bad;
t = t->type;
return old2new(name, t, init);
bad:
return name;
}
void void
typecheckselect(Node *sel) typecheckselect(Node *sel)
{ {
......
...@@ -582,11 +582,6 @@ dodump(Node *n, int dep) ...@@ -582,11 +582,6 @@ dodump(Node *n, int dep)
print("%O-ntype\n", n->op); print("%O-ntype\n", n->op);
dodump(n->ntype, dep+1); dodump(n->ntype, dep+1);
} }
if(n->defn != nil && n->defn->op != OAS && n->defn->op != OAS2) {
indent(dep);
print("%O-defn\n", n->op);
dodump(n->defn, dep+1);
}
if(n->list != nil) { if(n->list != nil) {
indent(dep); indent(dep);
print("%O-list\n", n->op); print("%O-list\n", n->op);
...@@ -597,6 +592,11 @@ dodump(Node *n, int dep) ...@@ -597,6 +592,11 @@ dodump(Node *n, int dep)
print("%O-rlist\n", n->op); print("%O-rlist\n", n->op);
dodumplist(n->rlist, dep+1); dodumplist(n->rlist, dep+1);
} }
if(n->nbody != nil) {
indent(dep);
print("%O-nbody\n", n->op);
dodumplist(n->nbody, dep+1);
}
} }
void void
...@@ -2466,10 +2466,8 @@ out: ...@@ -2466,10 +2466,8 @@ out:
yyerror("ambiguous DOT reference %T.%S", t, s); yyerror("ambiguous DOT reference %T.%S", t, s);
// rebuild elided dots // rebuild elided dots
for(c=d-1; c>=0; c--) { for(c=d-1; c>=0; c--)
n = nod(ODOT, n, n->right); n->left = nod(ODOT, n->left, newname(dotlist[c].field->sym));
n->left->right = newname(dotlist[c].field->sym);
}
ret: ret:
return n; return n;
} }
...@@ -2705,7 +2703,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam) ...@@ -2705,7 +2703,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam)
args = list(args, l->n->left); args = list(args, l->n->left);
// generate call // generate call
call = nod(OCALL, adddot(nod(ODOT, this->left, newname(method->sym))), N); call = nod(OCALL, adddot(nod(OXDOT, this->left, newname(method->sym))), N);
call->list = args; call->list = args;
fn->nbody = list1(call); fn->nbody = list1(call);
if(method->type->outtuple > 0) { if(method->type->outtuple > 0) {
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
* *
* TODO: * TODO:
* trailing ... section of function calls * trailing ... section of function calls
* range
*/ */
#include "go.h" #include "go.h"
...@@ -376,6 +375,10 @@ reswitch: ...@@ -376,6 +375,10 @@ reswitch:
goto error; goto error;
goto ret; goto ret;
case OXDOT:
n = adddot(n);
n->op = ODOT;
// fall through
case ODOT: case ODOT:
l = typecheck(&n->left, Erv); l = typecheck(&n->left, Erv);
if((t = l->type) == T) if((t = l->type) == T)
...@@ -882,6 +885,11 @@ reswitch: ...@@ -882,6 +885,11 @@ reswitch:
typecheckswitch(n); typecheckswitch(n);
goto ret; goto ret;
case ORANGE:
ok |= Etop;
typecheckrange(n);
goto ret;
case OTYPECASE: case OTYPECASE:
ok |= Etop | Erv; ok |= Etop | Erv;
typecheck(&n->left, Erv); typecheck(&n->left, Erv);
...@@ -1069,7 +1077,7 @@ nokeys(NodeList *l) ...@@ -1069,7 +1077,7 @@ nokeys(NodeList *l)
return 1; return 1;
} }
static int int
checkconv(Type *nt, Type *t, int explicit, int *op, int *et) checkconv(Type *nt, Type *t, int explicit, int *op, int *et)
{ {
*op = OCONV; *op = OCONV;
......
...@@ -285,7 +285,10 @@ walkstmt(Node **np) ...@@ -285,7 +285,10 @@ walkstmt(Node **np)
case OFOR: case OFOR:
walkstmtlist(n->ninit); walkstmtlist(n->ninit);
walkexpr(&n->ntest, &n->ntest->ninit); if(n->ntest != N) {
walkstmtlist(n->ntest->ninit);
walkexpr(&n->ntest, &n->ntest->ninit);
}
walkstmt(&n->nincr); walkstmt(&n->nincr);
walkstmtlist(n->nbody); walkstmtlist(n->nbody);
break; break;
...@@ -319,6 +322,10 @@ walkstmt(Node **np) ...@@ -319,6 +322,10 @@ walkstmt(Node **np)
walkswitch(n); walkswitch(n);
break; break;
case ORANGE:
walkrange(n);
break;
case OXFALL: case OXFALL:
yyerror("fallthrough statement out of place"); yyerror("fallthrough statement out of place");
n->op = OFALL; n->op = OFALL;
...@@ -1702,264 +1709,6 @@ out: ...@@ -1702,264 +1709,6 @@ out:
return n; return n;
} }
/*
* rewrite a range statement
* k and v are names/new_names
* m is an array or map
* local is 0 (meaning =) or 1 (meaning :=)
*/
Node*
dorange(Node *nn)
{
Node *k, *v, *m;
Node *n, *hv, *hc, *ha, *hk, *ohk, *on, *r, *a, *as;
NodeList *init, *args;
Type *t, *th;
int local;
NodeList *nl;
if(nn->op != ORANGE)
fatal("dorange not ORANGE");
nl = nn->list;
k = nl->n;
if((nl = nl->next) != nil) {
v = nl->n;
nl = nl->next;
} else
v = N;
if(nl != nil)
yyerror("too many variables in range");
n = nod(OFOR, N, N);
init = nil;
typecheck(&nn->right, Erv);
m = nn->right;
local = nn->etype;
t = m->type;
if(t == T)
goto out;
if(t->etype == TARRAY)
goto ary;
if(t->etype == TMAP)
goto map;
if(t->etype == TCHAN)
goto chan;
if(t->etype == TSTRING)
goto strng;
yyerror("range must be over map/array/chan/string");
goto out;
ary:
hk = nod(OXXX, N, N); // hidden key
tempname(hk, types[TINT]);
ha = nod(OXXX, N, N); // hidden array
tempname(ha, t);
a = nod(OAS, hk, nodintconst(0));
init = list(init, a);
a = nod(OAS, ha, m);
init = list(init, a);
n->ntest = nod(OLT, hk, nod(OLEN, ha, N));
n->nincr = nod(OASOP, hk, nodintconst(1));
n->nincr->etype = OADD;
if(local)
k = old2new(k, hk->type, &init);
n->nbody = list1(nod(OAS, k, hk));
if(v != N) {
if(local)
v = old2new(v, t->type, &init);
n->nbody = list(n->nbody,
nod(OAS, v, nod(OINDEX, ha, hk)) );
}
goto out;
map:
th = typ(TARRAY);
th->type = ptrto(types[TUINT8]);
th->bound = (sizeof(struct Hiter) + types[tptr]->width - 1) /
types[tptr]->width;
hk = nod(OXXX, N, N); // hidden iterator
tempname(hk, th); // hashmap hash_iter
on = syslook("mapiterinit", 1);
argtype(on, t->down);
argtype(on, t->type);
argtype(on, th);
a = nod(OADDR, hk, N);
r = nod(OCALL, on, N);
r->list = list(list1(m), a);
init = list(init, r);
r = nod(OINDEX, hk, nodintconst(0));
a = nod(OLITERAL, N, N);
a->val.ctype = CTNIL;
a->type = types[TNIL];
r = nod(ONE, r, a);
n->ntest = r;
on = syslook("mapiternext", 1);
argtype(on, th);
r = nod(OADDR, hk, N);
args = list1(r);
r = nod(OCALL, on, N);
r->list = args;
n->nincr = r;
if(local)
k = old2new(k, t->down, &init);
if(v == N) {
on = syslook("mapiter1", 1);
argtype(on, th);
argtype(on, t->down);
r = nod(OADDR, hk, N);
args = list1(r);
r = nod(OCALL, on, N);
r->list = args;
n->nbody = list1(nod(OAS, k, r));
goto out;
}
if(local)
v = old2new(v, t->type, &init);
on = syslook("mapiter2", 1);
argtype(on, th);
argtype(on, t->down);
argtype(on, t->type);
r = nod(OADDR, hk, N);
args = list1(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;
chan:
if(v != N)
yyerror("chan range can only have one variable");
hc = nod(OXXX, N, N); // hidden chan
tempname(hc, t);
hv = nod(OXXX, N, N); // hidden value
tempname(hv, t->type);
a = nod(OAS, hc, m);
init = list(init, a);
a = nod(ORECV, hc, N);
a = nod(OAS, hv, a);
init = list(init, a);
a = nod(OCLOSED, N, N);
a->list = list1(hc);
n->ntest = nod(ONOT, a, N);
n->nincr = nod(OAS, hv, nod(ORECV, hc, N));
if(local)
k = old2new(k, hv->type, &init);
n->nbody = list1(nod(OAS, k, hv));
goto out;
strng:
hk = nod(OXXX, N, N); // hidden key
tempname(hk, types[TINT]);
ohk = nod(OXXX, N, N); // old hidden key
tempname(ohk, types[TINT]);
ha = nod(OXXX, N, N); // hidden string
tempname(ha, types[TSTRING]);
hv = N;
if(v != N) {
hv = nod(OXXX, N, N); // hidden value
tempname(hv, types[TINT]);
}
if(local) {
k = old2new(k, types[TINT], &init);
if(v != N)
v = old2new(v, types[TINT], &init);
}
// ha = s
a = nod(OCONV, m, N);
a->type = ha->type;
a = nod(OAS, ha, a);
init = list(init, a);
// ohk = 0
a = nod(OAS, ohk, nodintconst(0));
init = list(init, a);
// hk[,hv] = stringiter(ha,hk)
if(v != N) {
// hk,v = stringiter2(ha, hk)
on = syslook("stringiter2", 0);
a = nod(OCALL, on, N);
a->list = list(list1(ha), nodintconst(0));
as = nod(OAS2, N, N);
as->list = list(list1(hk), hv);
as->rlist = list1(a);
a = as;
} else {
// hk = stringiter(ha, hk)
on = syslook("stringiter", 0);
a = nod(OCALL, on, N);
a->list = list(list1(ha), nodintconst(0));
a = nod(OAS, hk, a);
}
init = list(init, a);
// while(hk != 0)
n->ntest = nod(ONE, hk, nodintconst(0));
// hk[,hv] = stringiter(ha,hk)
if(v != N) {
// hk,hv = stringiter2(ha, hk)
on = syslook("stringiter2", 0);
a = nod(OCALL, on, N);
a->list = list(list1(ha), hk);
as = nod(OAS2, N, N);
as->list = list(list1(hk), hv);
as->rlist = list1(a);
a = as;
} else {
// hk = stringiter(ha, hk)
on = syslook("stringiter", 0);
a = nod(OCALL, on, N);
a->list = list(list1(ha), hk);
a = nod(OAS, hk, a);
}
n->nincr = a;
// k,ohk[,v] = ohk,hk,[,hv]
a = nod(OAS, k, ohk);
n->nbody = list1(a);
a = nod(OAS, ohk, hk);
n->nbody = list(n->nbody, a);
if(v != N) {
a = nod(OAS, v, hv);
n->nbody = list(n->nbody, a);
}
out:
n->ninit = concat(n->ninit, init);
return n;
}
/* /*
* from ascompat[te] * from ascompat[te]
* evaluating actual function arguments. * evaluating actual function arguments.
......
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