1
0
mirror of https://github.com/golang/go synced 2024-11-22 16:25:07 -07:00

allowed syntax for range

a range m (implies :=)
a,b range m (implies :=)
a:b range m (implies :=)

a := range m
a,b := range m
a:b := range m

a = range m
a,b = range m
a:b = range m

R=r
OCL=20676
CL=20676
This commit is contained in:
Ken Thompson 2008-12-06 13:40:30 -08:00
parent 26b357ca5b
commit b79272d9a2
4 changed files with 76 additions and 23 deletions

View File

@ -300,7 +300,7 @@ enum
ONAME, ONONAME,
ODOT, ODOTPTR, ODOTMETH, ODOTINTER,
ODCLFUNC, ODCLFIELD, ODCLARG,
OLIST, OCMP, OPTR, OARRAY,
OLIST, OCMP, OPTR, OARRAY, ORANGE,
ORETURN, OFOR, OIF, OSWITCH,
OAS, OASOP, OCASE, OXCASE, OFALL, OXFALL,
OGOTO, OPROC, ONEW, OEMPTY, OSELECT,
@ -806,7 +806,7 @@ int isandss(Type*, Node*);
Node* convas(Node*);
void arrayconv(Type*, Node*);
Node* colas(Node*, Node*);
Node* dorange(Node*, Node*, Node*, int);
Node* dorange(Node*);
Node* reorder1(Node*);
Node* reorder2(Node*);
Node* reorder3(Node*);

View File

@ -52,7 +52,7 @@
%type <node> Astmt Bstmt
%type <node> for_stmt for_body for_header
%type <node> if_stmt if_body if_header select_stmt
%type <node> simple_stmt osimple_stmt semi_stmt
%type <node> simple_stmt osimple_stmt orange_stmt semi_stmt
%type <node> expr uexpr pexpr expr_list oexpr oexpr_list expr_list_r
%type <node> exprsym3_list_r exprsym3
%type <node> name onew_name new_name new_name_list_r new_field
@ -416,7 +416,6 @@ simple_stmt:
{
if(addtop != N)
fatal("exprsym3_list_r LCOLAS expr_list");
$$ = rev($1);
$$ = colas($$, $3);
$$ = nod(OAS, $$, $3);
@ -555,31 +554,62 @@ compound_stmt:
popdcl();
}
for_header:
osimple_stmt ';' osimple_stmt ';' osimple_stmt
ocolas:
| LCOLAS
orange_stmt:
osimple_stmt
| exprsym3_list_r '=' LRANGE expr
{
$$ = nod(ORANGE, $1, $4);
$$->etype = 0; // := flag
}
| exprsym3 ':' exprsym3 '=' LRANGE expr
{
$$ = nod(OLIST, $1, $3);
$$ = nod(ORANGE, $$, $6);
$$->etype = 0;
}
| exprsym3_list_r ocolas LRANGE expr
{
$$ = nod(ORANGE, $1, $4);
$$->etype = 1;
}
| exprsym3 ':' exprsym3 ocolas LRANGE expr
{
$$ = nod(OLIST, $1, $3);
$$ = nod(ORANGE, $$, $6);
$$->etype = 1;
}
for_header:
osimple_stmt ';' orange_stmt ';' osimple_stmt
{
if($3 != N && $3->op == ORANGE) {
$$ = dorange($3);
$$->ninit = list($$->ninit, $1);
$$->nincr = list($$->nincr, $5);
break;
}
// init ; test ; incr
$$ = nod(OFOR, N, N);
$$->ninit = $1;
$$->ntest = $3;
$$->nincr = $5;
}
| osimple_stmt
| orange_stmt
{
// test
// range
if($1 != N && $1->op == ORANGE) {
$$ = dorange($1);
break;
}
// normal test
$$ = nod(OFOR, N, N);
$$->ninit = N;
$$->ntest = $1;
$$->nincr = N;
}
| new_name ':' new_name LRANGE expr
{
$$ = dorange($1, $3, $5, 1);
}
| new_name LRANGE expr
{
$$ = dorange($1, N, $3, 1);
}
for_body:
for_header compound_stmt

View File

@ -687,6 +687,7 @@ opnames[] =
[OREGISTER] = "REGISTER",
[OINDREG] = "INDREG",
[OSEND] = "SEND",
[ORANGE] = "RANGE",
[ORECV] = "RECV",
[OPTR] = "PTR",
[ORETURN] = "RETURN",

View File

@ -3033,14 +3033,32 @@ badt:
return nl;
}
/*
* rewrite a range statement
* k and v are names/new_names
* m is an array or map
* local is =/0 or :=/1
*/
Node*
dorange(Node *k, Node *v, Node *m, int local)
dorange(Node *nn)
{
Node *k, *v, *m;
Node *n, *hk, *on, *r, *a;
Type *t, *th;
int local;
if(!local)
fatal("only local varables now");
if(nn->op != ORANGE)
fatal("dorange not ORANGE");
k = nn->left;
m = nn->right;
local = nn->etype;
v = N;
if(k->op == OLIST) {
v = k->right;
k = k->left;
}
n = nod(OFOR, N, N);
@ -3073,11 +3091,13 @@ ary:
n->nincr = nod(OASOP, hk, literal(1));
n->nincr->etype = OADD;
k = old2new(k, hk->type);
if(local)
k = old2new(k, hk->type);
n->nbody = nod(OAS, k, hk);
if(v != N) {
v = old2new(v, t->type);
if(local)
v = old2new(v, t->type);
n->nbody = list(n->nbody,
nod(OAS, v, nod(OINDEX, m, hk)) );
}
@ -3112,7 +3132,8 @@ map:
r = nod(OCALL, on, r);
n->nincr = r;
k = old2new(k, t->down);
if(local)
k = old2new(k, t->down);
if(v == N) {
on = syslook("mapiter1", 1);
argtype(on, th);
@ -3122,7 +3143,8 @@ map:
n->nbody = nod(OAS, k, r);
goto out;
}
v = old2new(v, t->type);
if(local)
v = old2new(v, t->type);
on = syslook("mapiter2", 1);
argtype(on, th);
argtype(on, t->down);