mirror of
https://github.com/golang/go
synced 2024-11-22 01:14:40 -07:00
range statement
R=r OCL=20667 CL=20667
This commit is contained in:
parent
2fe97c336d
commit
26b357ca5b
@ -1263,7 +1263,7 @@ void
|
||||
constiter(Node *vv, Type *t, Node *cc)
|
||||
{
|
||||
Iter viter, citer;
|
||||
Node *v, *c, *a;
|
||||
Node *v, *c;
|
||||
|
||||
if(cc == N)
|
||||
cc = lastconst;
|
||||
|
@ -74,6 +74,33 @@ struct Array
|
||||
uchar b; // actual array - may not be contig
|
||||
};
|
||||
|
||||
/*
|
||||
* note this is the runtime representation
|
||||
* of hashmap iterator. it is probably
|
||||
* insafe to use it this way, but it puts
|
||||
* all the changes in one place.
|
||||
* only flag is referenced from go.
|
||||
* actual placement does not matter as long
|
||||
* as the size is >= actual size.
|
||||
*/
|
||||
typedef struct Hiter Hiter;
|
||||
struct Hiter
|
||||
{
|
||||
uchar data[8]; // return val from next
|
||||
int32 elemsize; // size of elements in table */
|
||||
int32 changes; // number of changes observed last time */
|
||||
int32 i; // stack pointer in subtable_state */
|
||||
uchar last[8]; // last hash value returned */
|
||||
uchar h[8]; // the hash table */
|
||||
struct
|
||||
{
|
||||
uchar sub[8]; // pointer into subtable */
|
||||
uchar start[8]; // pointer into start of subtable */
|
||||
uchar end[8]; // pointer into end of subtable */
|
||||
uchar pad[8];
|
||||
} sub[4];
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
Mpscale = 29, // safely smaller than bits in a long
|
||||
@ -779,6 +806,7 @@ int isandss(Type*, Node*);
|
||||
Node* convas(Node*);
|
||||
void arrayconv(Type*, Node*);
|
||||
Node* colas(Node*, Node*);
|
||||
Node* dorange(Node*, Node*, Node*, int);
|
||||
Node* reorder1(Node*);
|
||||
Node* reorder2(Node*);
|
||||
Node* reorder3(Node*);
|
||||
|
@ -51,8 +51,7 @@
|
||||
%type <node> stmt_list_r Astmt_list_r Bstmt_list_r
|
||||
%type <node> Astmt Bstmt
|
||||
%type <node> for_stmt for_body for_header
|
||||
%type <node> if_stmt if_body if_header
|
||||
%type <node> range_header range_body range_stmt select_stmt
|
||||
%type <node> if_stmt if_body if_header select_stmt
|
||||
%type <node> simple_stmt osimple_stmt semi_stmt
|
||||
%type <node> expr uexpr pexpr expr_list oexpr oexpr_list expr_list_r
|
||||
%type <node> exprsym3_list_r exprsym3
|
||||
@ -478,11 +477,6 @@ complex_stmt:
|
||||
popdcl();
|
||||
$$ = $2;
|
||||
}
|
||||
| LRANGE range_stmt
|
||||
{
|
||||
popdcl();
|
||||
$$ = $2;
|
||||
}
|
||||
| LCASE expr_list ':'
|
||||
{
|
||||
// will be converted to OCASE
|
||||
@ -578,12 +572,20 @@ for_header:
|
||||
$$->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
|
||||
{
|
||||
$$ = $1;
|
||||
$$->nbody = $2;
|
||||
$$->nbody = list($$->nbody, $2);
|
||||
}
|
||||
|
||||
for_stmt:
|
||||
@ -625,36 +627,6 @@ if_stmt:
|
||||
$$ = $2;
|
||||
}
|
||||
|
||||
range_header:
|
||||
new_name LCOLAS expr
|
||||
{
|
||||
$$ = N;
|
||||
}
|
||||
| new_name ',' new_name LCOLAS expr
|
||||
{
|
||||
$$ = N;
|
||||
}
|
||||
| new_name ',' new_name '=' expr
|
||||
{
|
||||
yyerror("range statement only allows := assignment");
|
||||
$$ = N;
|
||||
}
|
||||
|
||||
range_body:
|
||||
range_header compound_stmt
|
||||
{
|
||||
$$ = $1;
|
||||
$$->nbody = $2;
|
||||
}
|
||||
|
||||
range_stmt:
|
||||
{
|
||||
markdcl();
|
||||
} range_body
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
|
||||
select_stmt:
|
||||
{
|
||||
markdcl();
|
||||
|
@ -51,8 +51,8 @@ export func Inf(int) float64; // return signed Inf
|
||||
export func NaN() float64; // return a NaN
|
||||
export func float32bits(float32) uint32; // raw bits
|
||||
export func float64bits(float64) uint64; // raw bits
|
||||
export func float32frombits(uint32) float32; // raw bits
|
||||
export func float64frombits(uint64) float64; // raw bits
|
||||
export func float32frombits(uint32) float32; // raw bits
|
||||
export func float64frombits(uint64) float64; // raw bits
|
||||
|
||||
export func newmap(keysize int, valsize int,
|
||||
keyalg int, valalg int,
|
||||
@ -61,6 +61,10 @@ export func mapaccess1(hmap *map[any]any, key any) (val any);
|
||||
export func mapaccess2(hmap *map[any]any, key any) (val any, pres bool);
|
||||
export func mapassign1(hmap *map[any]any, key any, val any);
|
||||
export func mapassign2(hmap *map[any]any, key any, val any, pres bool);
|
||||
export func mapiterinit(hmap *map[any]any, hiter *any);
|
||||
export func mapiternext(hiter *any);
|
||||
export func mapiter1(hiter *any) (key any);
|
||||
export func mapiter2(hiter *any) (key any, val any);
|
||||
|
||||
export func newchan(elemsize int, elemalg int, hint int) (hchan *chan any);
|
||||
export func chanrecv1(hchan *chan any) (elem any);
|
||||
|
@ -1,4 +1,4 @@
|
||||
char *sysimport =
|
||||
char *sysimport =
|
||||
"package sys\n"
|
||||
"export func sys.mal (? int32) (? *any)\n"
|
||||
"export func sys.breakpoint ()\n"
|
||||
@ -48,6 +48,10 @@ char *sysimport =
|
||||
"export func sys.mapaccess2 (hmap *map[any] any, key any) (val any, pres bool)\n"
|
||||
"export func sys.mapassign1 (hmap *map[any] any, key any, val any)\n"
|
||||
"export func sys.mapassign2 (hmap *map[any] any, key any, val any, pres bool)\n"
|
||||
"export func sys.mapiterinit (hmap *map[any] any, hiter *any)\n"
|
||||
"export func sys.mapiternext (hiter *any)\n"
|
||||
"export func sys.mapiter1 (hiter *any) (key any)\n"
|
||||
"export func sys.mapiter2 (hiter *any) (key any, val any)\n"
|
||||
"export func sys.newchan (elemsize int, elemalg int, hint int) (hchan *chan any)\n"
|
||||
"export func sys.chanrecv1 (hchan *chan any) (elem any)\n"
|
||||
"export func sys.chanrecv2 (hchan *chan any) (elem any, pres bool)\n"
|
||||
|
@ -3033,6 +3033,110 @@ badt:
|
||||
return nl;
|
||||
}
|
||||
|
||||
Node*
|
||||
dorange(Node *k, Node *v, Node *m, int local)
|
||||
{
|
||||
Node *n, *hk, *on, *r, *a;
|
||||
Type *t, *th;
|
||||
|
||||
if(!local)
|
||||
fatal("only local varables now");
|
||||
|
||||
n = nod(OFOR, N, N);
|
||||
|
||||
walktype(m, Erv);
|
||||
t = m->type;
|
||||
if(t == T)
|
||||
goto out;
|
||||
if(t->etype == TARRAY)
|
||||
goto ary;
|
||||
if(isptrto(t, TARRAY)) {
|
||||
t = t->type;
|
||||
goto ary;
|
||||
}
|
||||
if(t->etype == TMAP)
|
||||
goto map;
|
||||
if(isptrto(t, TMAP)) {
|
||||
t = t->type;
|
||||
goto map;
|
||||
}
|
||||
|
||||
yyerror("range must be over map/array");
|
||||
goto out;
|
||||
|
||||
ary:
|
||||
hk = nod(OXXX, N, N); // hidden key
|
||||
tempname(hk, types[TINT]); // maybe TINT32
|
||||
|
||||
n->ninit = nod(OAS, hk, literal(0));
|
||||
n->ntest = nod(OLT, hk, nod(OLEN, m, N));
|
||||
n->nincr = nod(OASOP, hk, literal(1));
|
||||
n->nincr->etype = OADD;
|
||||
|
||||
k = old2new(k, hk->type);
|
||||
n->nbody = nod(OAS, k, hk);
|
||||
|
||||
if(v != N) {
|
||||
v = old2new(v, t->type);
|
||||
n->nbody = list(n->nbody,
|
||||
nod(OAS, v, nod(OINDEX, m, 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);
|
||||
r = nod(OADDR, hk, N);
|
||||
r = list(m, r);
|
||||
r = nod(OCALL, on, r);
|
||||
n->ninit = r;
|
||||
|
||||
r = nod(OINDEX, hk, literal(0));
|
||||
a = nod(OLITERAL, N, N);
|
||||
a->val.ctype = CTNIL;
|
||||
r = nod(ONE, r, a);
|
||||
n->ntest = r;
|
||||
|
||||
on = syslook("mapiternext", 1);
|
||||
argtype(on, th);
|
||||
r = nod(OADDR, hk, N);
|
||||
r = nod(OCALL, on, r);
|
||||
n->nincr = r;
|
||||
|
||||
k = old2new(k, t->down);
|
||||
if(v == N) {
|
||||
on = syslook("mapiter1", 1);
|
||||
argtype(on, th);
|
||||
argtype(on, t->down);
|
||||
r = nod(OADDR, hk, N);
|
||||
r = nod(OCALL, on, r);
|
||||
n->nbody = nod(OAS, k, r);
|
||||
goto out;
|
||||
}
|
||||
v = old2new(v, t->type);
|
||||
on = syslook("mapiter2", 1);
|
||||
argtype(on, th);
|
||||
argtype(on, t->down);
|
||||
argtype(on, t->type);
|
||||
r = nod(OADDR, hk, N);
|
||||
r = nod(OCALL, on, r);
|
||||
n->nbody = nod(OAS, nod(OLIST, k, v), r);
|
||||
|
||||
goto out;
|
||||
|
||||
out:
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* from ascompat[te]
|
||||
* evaluating actual function arguments.
|
||||
|
@ -649,7 +649,7 @@ donothing(uint32 s, void *a, void *b)
|
||||
USED(b);
|
||||
}
|
||||
|
||||
typedef struct hash Hmap;
|
||||
typedef struct hash Hmap;
|
||||
static int32 debug = 0;
|
||||
|
||||
// newmap(keysize uint32, valsize uint32,
|
||||
@ -860,3 +860,86 @@ sys·mapassign2(Hmap *h, ...)
|
||||
prints("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// mapiterinit(hmap *map[any]any, hiter *any);
|
||||
void
|
||||
sys·mapiterinit(Hmap *h, struct hash_iter *it)
|
||||
{
|
||||
hash_iter_init(h, it);
|
||||
it->data = hash_next(it);
|
||||
if(debug) {
|
||||
prints("sys·mapiterinit: map=");
|
||||
sys·printpointer(h);
|
||||
prints("; iter=");
|
||||
sys·printpointer(it);
|
||||
prints("; data=");
|
||||
sys·printpointer(it->data);
|
||||
prints("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// mapiternext(hiter *any);
|
||||
void
|
||||
sys·mapiternext(struct hash_iter *it)
|
||||
{
|
||||
it->data = hash_next(it);
|
||||
if(debug) {
|
||||
prints("sys·mapiternext: iter=");
|
||||
sys·printpointer(it);
|
||||
prints("; data=");
|
||||
sys·printpointer(it->data);
|
||||
prints("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// mapiter1(hiter *any) (key any);
|
||||
void
|
||||
sys·mapiter1(struct hash_iter *it, ...)
|
||||
{
|
||||
Hmap *h;
|
||||
byte *ak, *res;
|
||||
|
||||
h = it->h;
|
||||
ak = (byte*)&it + h->ko;
|
||||
|
||||
res = it->data;
|
||||
if(res == nil)
|
||||
throw("sys·mapiter2: key:val nil pointer");
|
||||
|
||||
h->keyalg->copy(h->keysize, ak, res);
|
||||
|
||||
if(debug) {
|
||||
prints("mapiter2: iter=");
|
||||
sys·printpointer(it);
|
||||
prints("; map=");
|
||||
sys·printpointer(h);
|
||||
prints("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// mapiter2(hiter *any) (key any, val any);
|
||||
void
|
||||
sys·mapiter2(struct hash_iter *it, ...)
|
||||
{
|
||||
Hmap *h;
|
||||
byte *ak, *av, *res;
|
||||
|
||||
h = it->h;
|
||||
ak = (byte*)&it + h->ko;
|
||||
av = (byte*)&it + h->vo;
|
||||
|
||||
res = it->data;
|
||||
if(res == nil)
|
||||
throw("sys·mapiter2: key:val nil pointer");
|
||||
|
||||
h->keyalg->copy(h->keysize, ak, res);
|
||||
h->valalg->copy(h->valsize, av, res+h->keysize);
|
||||
|
||||
if(debug) {
|
||||
prints("mapiter2: iter=");
|
||||
sys·printpointer(it);
|
||||
prints("; map=");
|
||||
sys·printpointer(h);
|
||||
prints("\n");
|
||||
}
|
||||
}
|
||||
|
@ -72,24 +72,25 @@
|
||||
#define memcpy(a,b,c) mcpy((byte*)(a),(byte*)(b),(uint32)(c))
|
||||
#define assert(a) if(!(a)) throw("assert")
|
||||
|
||||
struct hash; /* opaque */
|
||||
struct hash_subtable; /* opaque */
|
||||
struct hash_entry; /* opaque */
|
||||
struct hash; /* opaque */
|
||||
struct hash_subtable; /* opaque */
|
||||
struct hash_entry; /* opaque */
|
||||
|
||||
typedef uint64 uintptr_t;
|
||||
typedef uintptr_t hash_hash_t;
|
||||
|
||||
struct hash_iter {
|
||||
int32 elemsize; /* size of elements in table */
|
||||
int32 changes; /* number of changes observed last time */
|
||||
int32 i; /* stack pointer in subtable_state */
|
||||
hash_hash_t last_hash; /* last hash value returned */
|
||||
struct hash *h; /* the hash table */
|
||||
uint8* data; /* returned from next */
|
||||
int32 elemsize; /* size of elements in table */
|
||||
int32 changes; /* number of changes observed last time */
|
||||
int32 i; /* stack pointer in subtable_state */
|
||||
hash_hash_t last_hash; /* last hash value returned */
|
||||
struct hash *h; /* the hash table */
|
||||
struct hash_iter_sub {
|
||||
struct hash_entry *e; /* pointer into subtable */
|
||||
struct hash_entry *start; /* start of subtable */
|
||||
struct hash_entry *end; /* end of subtable */
|
||||
} subtable_state[16]; /* Should be large enough unless the hashing is
|
||||
struct hash_entry *e; /* pointer into subtable */
|
||||
struct hash_entry *start; /* start of subtable */
|
||||
struct hash_entry *end; /* end of subtable */
|
||||
} subtable_state[4]; /* Should be large enough unless the hashing is
|
||||
so bad that many distinct data values hash
|
||||
to the same hash value. */
|
||||
};
|
||||
|
113
test/ken/range.go
Normal file
113
test/ken/range.go
Normal file
@ -0,0 +1,113 @@
|
||||
// $G $D/$F.go && $L $F.$A && ./$A.out
|
||||
|
||||
// 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.
|
||||
|
||||
package main
|
||||
|
||||
const size = 16;
|
||||
|
||||
var a [size]byte;
|
||||
var p *[]byte;
|
||||
var m *map[int]byte;
|
||||
|
||||
func
|
||||
f(k int) byte
|
||||
{
|
||||
return byte(k*10007 % size);
|
||||
}
|
||||
|
||||
func
|
||||
init()
|
||||
{
|
||||
p = new([]byte, size);
|
||||
m = new(map[int]byte);
|
||||
for k:=0; k<size; k++ {
|
||||
v := f(k);
|
||||
a[k] = v;
|
||||
p[k] = v;
|
||||
m[k] = v;
|
||||
}
|
||||
}
|
||||
|
||||
func
|
||||
main()
|
||||
{
|
||||
var i int;
|
||||
|
||||
/*
|
||||
* key only
|
||||
*/
|
||||
i = 0;
|
||||
for k range a {
|
||||
v := a[k];
|
||||
if v != f(k) {
|
||||
panicln("key array range", k, v, a[k]);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if i != size {
|
||||
panicln("key array size", i);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for k range p {
|
||||
v := p[k];
|
||||
if v != f(k) {
|
||||
panicln("key pointer range", k, v, p[k]);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if i != size {
|
||||
panicln("key pointer size", i);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for k range m {
|
||||
v := m[k];
|
||||
if v != f(k) {
|
||||
panicln("key map range", k, v, m[k]);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if i != size {
|
||||
panicln("key map size", i);
|
||||
}
|
||||
|
||||
/*
|
||||
* key:value
|
||||
*/
|
||||
i = 0;
|
||||
for k:v range a {
|
||||
if v != f(k) {
|
||||
panicln("key:value array range", k, v, a[k]);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if i != size {
|
||||
panicln("key:value array size", i);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for k:v range p {
|
||||
if v != f(k) {
|
||||
panicln("key:value pointer range", k, v, p[k]);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if i != size {
|
||||
panicln("key:value pointer size", i);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for k:v range m {
|
||||
if v != f(k) {
|
||||
panicln("key:value map range", k, v, m[k]);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if i != size {
|
||||
panicln("key:value map size", i);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user