update xhash (orderd map)

This commit is contained in:
Yuichi Nishiwaki 2014-09-16 16:44:44 +09:00
parent db5a4e367b
commit 1b36b5d2ff
7 changed files with 123 additions and 127 deletions

View File

@ -62,7 +62,7 @@ static analyze_state *
new_analyze_state(pic_state *pic) new_analyze_state(pic_state *pic)
{ {
analyze_state *state; analyze_state *state;
xh_iter it; xh_entry *it;
state = pic_alloc(pic, sizeof(analyze_state)); state = pic_alloc(pic, sizeof(analyze_state));
state->pic = pic; state->pic = pic;
@ -98,9 +98,8 @@ new_analyze_state(pic_state *pic)
/* push initial scope */ /* push initial scope */
push_scope(state, pic_nil_value()); push_scope(state, pic_nil_value());
xh_begin(&it, &pic->globals); for (it = xh_begin(&pic->globals); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) { pic_sym sym = xh_key(it, pic_sym);
pic_sym sym = xh_key(it.e, pic_sym);
xv_push(&state->scope->locals, &sym); xv_push(&state->scope->locals, &sym);
} }

30
dict.c
View File

@ -222,13 +222,12 @@ pic_dict_dictionary_map(pic_state *pic)
struct pic_proc *proc; struct pic_proc *proc;
struct pic_dict *dict; struct pic_dict *dict;
pic_value item, list = pic_nil_value(); pic_value item, list = pic_nil_value();
xh_iter it; xh_entry *it;
pic_get_args(pic, "ld", &proc, &dict); pic_get_args(pic, "ld", &proc, &dict);
xh_begin(&it, &dict->hash); for (it = xh_begin(&dict->hash); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) { item = pic_cons(pic, xh_key(it, pic_value), xh_val(it, pic_value));
item = pic_cons(pic, xh_key(it.e, pic_value), xh_val(it.e, pic_value));
pic_push(pic, pic_apply1(pic, proc, item), list); pic_push(pic, pic_apply1(pic, proc, item), list);
} }
@ -241,15 +240,14 @@ pic_dict_dictionary_for_each(pic_state *pic)
struct pic_proc *proc; struct pic_proc *proc;
struct pic_dict *dict; struct pic_dict *dict;
pic_value item; pic_value item;
xh_iter it; xh_entry *it;
pic_get_args(pic, "ld", &proc, &dict); pic_get_args(pic, "ld", &proc, &dict);
xh_begin(&it, &dict->hash); for (it = xh_begin(&dict->hash); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) {
int ai = pic_gc_arena_preserve(pic); int ai = pic_gc_arena_preserve(pic);
item = pic_cons(pic, xh_key(it.e, pic_value), xh_val(it.e, pic_value)); item = pic_cons(pic, xh_key(it, pic_value), xh_val(it, pic_value));
pic_apply1(pic, proc, item); pic_apply1(pic, proc, item);
pic_gc_arena_restore(pic, ai); pic_gc_arena_restore(pic, ai);
@ -263,13 +261,12 @@ pic_dict_dictionary_to_alist(pic_state *pic)
{ {
struct pic_dict *dict; struct pic_dict *dict;
pic_value item, alist = pic_nil_value(); pic_value item, alist = pic_nil_value();
xh_iter it; xh_entry *it;
pic_get_args(pic, "d", &dict); pic_get_args(pic, "d", &dict);
xh_begin(&it, &dict->hash); for (it = xh_begin(&dict->hash); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) { item = pic_cons(pic, xh_key(it, pic_value), xh_val(it, pic_value));
item = pic_cons(pic, xh_key(it.e, pic_value), xh_val(it.e, pic_value));
pic_push(pic, item, alist); pic_push(pic, item, alist);
} }
@ -298,14 +295,13 @@ pic_dict_dictionary_to_plist(pic_state *pic)
{ {
struct pic_dict *dict; struct pic_dict *dict;
pic_value plist = pic_nil_value(); pic_value plist = pic_nil_value();
xh_iter it; xh_entry *it;
pic_get_args(pic, "d", &dict); pic_get_args(pic, "d", &dict);
xh_begin(&it, &dict->hash); for (it = xh_begin(&dict->hash); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) { pic_push(pic, xh_key(it, pic_value), plist);
pic_push(pic, xh_key(it.e, pic_value), plist); pic_push(pic, xh_val(it, pic_value), plist);
pic_push(pic, xh_val(it.e, pic_value), plist);
} }
return pic_reverse(pic, plist); return pic_reverse(pic, plist);

35
gc.c
View File

@ -475,32 +475,29 @@ gc_mark_object(pic_state *pic, struct pic_object *obj)
} }
case PIC_TT_DATA: { case PIC_TT_DATA: {
struct pic_data *data = (struct pic_data *)obj; struct pic_data *data = (struct pic_data *)obj;
xh_iter it; xh_entry *it;
xh_begin(&it, &data->storage); for (it = xh_begin(&data->storage); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) { gc_mark(pic, xh_val(it, pic_value));
gc_mark(pic, xh_val(it.e, pic_value));
} }
break; break;
} }
case PIC_TT_DICT: { case PIC_TT_DICT: {
struct pic_dict *dict = (struct pic_dict *)obj; struct pic_dict *dict = (struct pic_dict *)obj;
xh_iter it; xh_entry *it;
xh_begin(&it, &dict->hash); for (it = xh_begin(&dict->hash); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) { gc_mark(pic, xh_key(it, pic_value));
gc_mark(pic, xh_key(it.e, pic_value)); gc_mark(pic, xh_val(it, pic_value));
gc_mark(pic, xh_val(it.e, pic_value));
} }
break; break;
} }
case PIC_TT_RECORD: { case PIC_TT_RECORD: {
struct pic_record *rec = (struct pic_record *)obj; struct pic_record *rec = (struct pic_record *)obj;
xh_iter it; xh_entry *it;
xh_begin(&it, &rec->hash); for (it = xh_begin(&rec->hash); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) { gc_mark(pic, xh_val(it, pic_value));
gc_mark(pic, xh_val(it.e, pic_value));
} }
break; break;
} }
@ -563,7 +560,7 @@ gc_mark_phase(pic_state *pic)
pic_value *stack; pic_value *stack;
pic_callinfo *ci; pic_callinfo *ci;
size_t i, j; size_t i, j;
xh_iter it; xh_entry *it;
/* block */ /* block */
if (pic->blk) { if (pic->blk) {
@ -593,15 +590,13 @@ gc_mark_phase(pic_state *pic)
} }
/* global variables */ /* global variables */
xh_begin(&it, &pic->globals); for (it = xh_begin(&pic->globals); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) { gc_mark(pic, xh_val(it, pic_value));
gc_mark(pic, xh_val(it.e, pic_value));
} }
/* macro objects */ /* macro objects */
xh_begin(&it, &pic->macros); for (it = xh_begin(&pic->macros); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) { gc_mark_object(pic, xh_val(it, struct pic_object *));
gc_mark_object(pic, xh_val(it.e, struct pic_object *));
} }
/* error handlers */ /* error handlers */

View File

@ -1,5 +1,5 @@
#ifndef XHASH_H__ #ifndef XHASH_H
#define XHASH_H__ #define XHASH_H
/* /*
* Copyright (c) 2013-2014 by Yuichi Nishiwaki <yuichi.nishiwaki@gmail.com> * Copyright (c) 2013-2014 by Yuichi Nishiwaki <yuichi.nishiwaki@gmail.com>
@ -27,6 +27,7 @@ extern "C" {
typedef struct xh_entry { typedef struct xh_entry {
struct xh_entry *next; struct xh_entry *next;
int hash; int hash;
struct xh_entry *fw, *bw;
const char *key; /* == val + XHASH_ALIGN(vwidth) */ const char *key; /* == val + XHASH_ALIGN(vwidth) */
char val[]; char val[];
} xh_entry; } xh_entry;
@ -42,15 +43,16 @@ typedef struct xhash {
size_t size, count, kwidth, vwidth; size_t size, count, kwidth, vwidth;
xh_hashf hashf; xh_hashf hashf;
xh_equalf equalf; xh_equalf equalf;
xh_entry *chain;
void *data; void *data;
} xhash; } xhash;
static inline void xh_init_(xhash *x, size_t, size_t, xh_hashf, xh_equalf, void *); /** Protected Methods:
static inline xh_entry *xh_get_(xhash *x, const void *key); * static inline void xh_init_(xhash *x, size_t, size_t, xh_hashf, xh_equalf, void *);
static inline xh_entry *xh_put_(xhash *x, const void *key, void *val); * static inline xh_entry *xh_get_(xhash *x, const void *key);
static inline void xh_del_(xhash *x, const void *key); * static inline xh_entry *xh_put_(xhash *x, const void *key, void *val);
static inline void xh_clear(xhash *x); * static inline void xh_del_(xhash *x, const void *key);
static inline void xh_destroy(xhash *x); */
/* string map */ /* string map */
static inline void xh_init_str(xhash *x, size_t width); static inline void xh_init_str(xhash *x, size_t width);
@ -70,14 +72,12 @@ static inline xh_entry *xh_get_int(xhash *x, int key);
static inline xh_entry *xh_put_int(xhash *x, int key, void *); static inline xh_entry *xh_put_int(xhash *x, int key, void *);
static inline void xh_del_int(xhash *x, int key); static inline void xh_del_int(xhash *x, int key);
typedef struct xh_iter { static inline size_t xh_size(xhash *x);
xhash *x; static inline void xh_clear(xhash *x);
xh_entry *e, *next; static inline void xh_destroy(xhash *x);
size_t bidx;
} xh_iter;
static inline void xh_begin(xh_iter *it, xhash *x); static inline xh_entry *xh_begin(xhash *x);
static inline int xh_next(xh_iter *it); static inline xh_entry *xh_next(xh_entry *e);
static inline void static inline void
@ -98,6 +98,7 @@ xh_init_(xhash *x, size_t kwidth, size_t vwidth, xh_hashf hashf, xh_equalf equal
x->vwidth = vwidth; x->vwidth = vwidth;
x->hashf = hashf; x->hashf = hashf;
x->equalf = equalf; x->equalf = equalf;
x->chain = NULL;
x->data = data; x->data = data;
xh_bucket_realloc(x, XHASH_INIT_SIZE); xh_bucket_realloc(x, XHASH_INIT_SIZE);
@ -123,21 +124,22 @@ static inline void
xh_resize_(xhash *x, size_t newsize) xh_resize_(xhash *x, size_t newsize)
{ {
xhash y; xhash y;
xh_iter it; xh_entry *it;
size_t idx; size_t idx;
xh_init_(&y, x->kwidth, x->vwidth, x->hashf, x->equalf, x->data); xh_init_(&y, x->kwidth, x->vwidth, x->hashf, x->equalf, x->data);
xh_bucket_realloc(&y, newsize); xh_bucket_realloc(&y, newsize);
xh_begin(&it, x); for (it = xh_begin(x); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) { idx = ((unsigned)it->hash) % y.size;
idx = ((unsigned)it.e->hash) % y.size;
/* reuse entry object */ /* reuse entry object */
it.e->next = y.buckets[idx]; it->next = y.buckets[idx];
y.buckets[idx] = it.e; y.buckets[idx] = it;
y.count++; y.count++;
} }
y.chain = x->chain;
free(x->buckets); free(x->buckets);
/* copy all members from y to x */ /* copy all members from y to x */
@ -169,6 +171,16 @@ xh_put_(xhash *x, const void *key, void *val)
memcpy((void *)e->key, key, x->kwidth); memcpy((void *)e->key, key, x->kwidth);
memcpy(e->val, val, x->vwidth); memcpy(e->val, val, x->vwidth);
if (x->chain == NULL) {
x->chain = e;
e->fw = e->bw = NULL;
} else {
x->chain->fw = e;
e->bw = x->chain;
e->fw = NULL;
x->chain = e;
}
x->count++; x->count++;
return x->buckets[idx] = e; return x->buckets[idx] = e;
@ -179,28 +191,54 @@ xh_del_(xhash *x, const void *key)
{ {
int hash; int hash;
size_t idx; size_t idx;
xh_entry *e, *d; xh_entry *p, *q, *r;
hash = x->hashf(key, x->data); hash = x->hashf(key, x->data);
idx = ((unsigned)hash) % x->size; idx = ((unsigned)hash) % x->size;
if (x->buckets[idx]->hash == hash && x->equalf(key, x->buckets[idx]->key, x->data)) { if (x->buckets[idx]->hash == hash && x->equalf(key, x->buckets[idx]->key, x->data)) {
e = x->buckets[idx]->next; q = x->buckets[idx];
free(x->buckets[idx]); if (q->fw) {
x->buckets[idx] = e; q->fw->bw = q->bw;
}
if (q->bw) {
q->bw->fw = q->fw;
}
if (x->chain == q) {
x->chain = q->bw;
}
r = q->next;
free(q);
x->buckets[idx] = r;
} }
else { else {
for (e = x->buckets[idx]; ; e = e->next) { for (p = x->buckets[idx]; ; p = p->next) {
if (e->next->hash == hash && x->equalf(key, e->next->key, x->data)) if (p->next->hash == hash && x->equalf(key, p->next->key, x->data))
break; break;
} }
d = e->next->next; q = p->next;
free(e->next); if (q->fw) {
e->next = d; q->fw->bw = q->bw;
}
if (q->bw) {
q->bw->fw = q->fw;
}
if (x->chain == q) {
x->chain = q->bw;
}
r = q->next;
free(q);
p->next = r;
} }
x->count--; x->count--;
} }
static inline size_t
xh_size(xhash *x)
{
return x->count;
}
static inline void static inline void
xh_clear(xhash *x) xh_clear(xhash *x)
{ {
@ -217,6 +255,7 @@ xh_clear(xhash *x)
x->buckets[i] = NULL; x->buckets[i] = NULL;
} }
x->chain = NULL;
x->count = 0; x->count = 0;
} }
@ -361,43 +400,16 @@ xh_del_int(xhash *x, int key)
/** iteration */ /** iteration */
static inline void static inline xh_entry *
xh_begin(xh_iter *it, xhash *x) xh_begin(xhash *x)
{ {
size_t bidx; return x->chain;
it->x = x;
for (bidx = 0; bidx < x->size; ++bidx) {
if (x->buckets[bidx])
break;
}
it->e = NULL;
it->next = x->buckets[bidx];
it->bidx = bidx;
} }
static inline int static inline xh_entry *
xh_next(xh_iter *it) xh_next(xh_entry *e)
{ {
size_t bidx; return e->bw;
if (! it->next) {
return 0;
}
it->e = it->next;
if (it->next->next) {
it->next = it->next->next;
return 1;
}
for (bidx = it->bidx + 1; bidx < it->x->size; ++bidx) {
if (it->x->buckets[bidx])
break;
}
it->next = it->x->buckets[bidx];
it->bidx = bidx;
return 1;
} }
#if defined(__cplusplus) #if defined(__cplusplus)

23
lib.c
View File

@ -71,7 +71,7 @@ import_table(pic_state *pic, pic_value spec, xhash *imports)
xhash table; xhash table;
pic_value val; pic_value val;
pic_sym sym, id, tag; pic_sym sym, id, tag;
xh_iter it; xh_entry *it;
xh_init_int(&table, sizeof(pic_sym)); xh_init_int(&table, sizeof(pic_sym));
@ -97,11 +97,10 @@ import_table(pic_state *pic, pic_value spec, xhash *imports)
} }
if (tag == pic->sPREFIX) { if (tag == pic->sPREFIX) {
import_table(pic, pic_cadr(pic, spec), &table); import_table(pic, pic_cadr(pic, spec), &table);
xh_begin(&it, &table); for (it = xh_begin(&table); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) {
val = pic_list_ref(pic, spec, 2); val = pic_list_ref(pic, spec, 2);
sym = pic_intern_str(pic, pic_format(pic, "~s~s", val, pic_sym_value(xh_key(it.e, pic_sym)))); sym = pic_intern_str(pic, pic_format(pic, "~s~s", val, pic_sym_value(xh_key(it, pic_sym))));
xh_put_int(imports, sym, &xh_val(it.e, pic_sym)); xh_put_int(imports, sym, &xh_val(it, pic_sym));
} }
goto exit; goto exit;
} }
@ -117,9 +116,8 @@ import_table(pic_state *pic, pic_value spec, xhash *imports)
if (! lib) { if (! lib) {
pic_errorf(pic, "library not found: ~a", spec); pic_errorf(pic, "library not found: ~a", spec);
} }
xh_begin(&it, &lib->exports); for (it = xh_begin(&lib->exports); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) { xh_put_int(imports, xh_key(it, pic_sym), &xh_val(it, pic_sym));
xh_put_int(imports, xh_key(it.e, pic_sym), &xh_val(it.e, pic_sym));
} }
exit: exit:
@ -130,20 +128,19 @@ static void
import(pic_state *pic, pic_value spec) import(pic_state *pic, pic_value spec)
{ {
xhash imports; xhash imports;
xh_iter it; xh_entry *it;
xh_init_int(&imports, sizeof(pic_sym)); /* pic_sym to pic_sym */ xh_init_int(&imports, sizeof(pic_sym)); /* pic_sym to pic_sym */
import_table(pic, spec, &imports); import_table(pic, spec, &imports);
xh_begin(&it, &imports); for (it = xh_begin(&imports); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) {
#if DEBUG #if DEBUG
printf("* importing %s as %s\n", pic_symbol_name(pic, xh_key(it.e, pic_sym)), pic_symbol_name(pic, xh_val(it.e, pic_sym))); printf("* importing %s as %s\n", pic_symbol_name(pic, xh_key(it, pic_sym)), pic_symbol_name(pic, xh_val(it, pic_sym)));
#endif #endif
pic_put_rename(pic, pic->lib->env, xh_key(it.e, pic_sym), xh_val(it.e, pic_sym)); pic_put_rename(pic, pic->lib->env, xh_key(it, pic_sym), xh_val(it, pic_sym));
} }
xh_destroy(&imports); xh_destroy(&imports);

View File

@ -177,7 +177,7 @@ pic_open(int argc, char *argv[], char **envp)
void void
pic_close(pic_state *pic) pic_close(pic_state *pic)
{ {
xh_iter it; xh_entry *it;
/* invoke exit handlers */ /* invoke exit handlers */
while (pic->blk) { while (pic->blk) {
@ -221,9 +221,8 @@ pic_close(pic_state *pic)
free(pic->arena); free(pic->arena);
/* free symbol names */ /* free symbol names */
xh_begin(&it, &pic->sym_names); for (it = xh_begin(&pic->sym_names); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) { free(xh_val(it, char *));
free(xh_val(it.e, char *));
} }
xh_destroy(&pic->sym_names); xh_destroy(&pic->sym_names);

10
write.c
View File

@ -209,8 +209,7 @@ write_core(struct writer_control *p, pic_value obj)
pic_state *pic = p->pic; pic_state *pic = p->pic;
xFILE *file = p->file; xFILE *file = p->file;
size_t i; size_t i;
xh_entry *e; xh_entry *e, *it;
xh_iter it;
int c; int c;
float f; float f;
@ -334,12 +333,11 @@ write_core(struct writer_control *p, pic_value obj)
break; break;
case PIC_TT_DICT: case PIC_TT_DICT:
xfprintf(file, "#.(dictionary"); xfprintf(file, "#.(dictionary");
xh_begin(&it, &pic_dict_ptr(obj)->hash); for (it = xh_begin(&pic_dict_ptr(obj)->hash); it != NULL; it = xh_next(it)) {
while (xh_next(&it)) {
xfprintf(file, " '"); xfprintf(file, " '");
write_core(p, xh_key(it.e, pic_value)); write_core(p, xh_key(it, pic_value));
xfprintf(file, " '"); xfprintf(file, " '");
write_core(p, xh_val(it.e, pic_value)); write_core(p, xh_val(it, pic_value));
} }
xfprintf(file, ")"); xfprintf(file, ")");
break; break;