hash.c おさらい
って思ってたんですがちょっとマテ。なんで hash.c なんだったっけ、と冷静になり module.c の中の Scm_FindBinding() 手続き見てて Scm_HashTableRef() 手続きを掘りはじめたのがきっかけだった事が先程判明。
という事で一旦おらさいしてみます。微妙にへろへろですが ...
という事で
洗い出し。
$ grep '^[a-zA-Z]' hash.c typedef struct EntryRec { typedef Entry *SearchProc(ScmHashCore *core, intptr_t key, ScmDictOp op); static unsigned int round2up(unsigned int val); u_long Scm_EqHash(ScmObj obj) u_long Scm_EqvHash(ScmObj obj) u_long Scm_Hash(ScmObj obj) u_long Scm_HashString(ScmString *str, u_long modulo) static Entry *insert_entry(ScmHashCore *table, static Entry *delete_entry(ScmHashCore *table, static Entry *address_access(ScmHashCore *table, static u_long address_hash(const ScmHashCore *ht, intptr_t obj) static int address_cmp(const ScmHashCore *ht, intptr_t key, intptr_t k2) static u_long eqv_hash(const ScmHashCore *table, intptr_t key) static int eqv_cmp(const ScmHashCore *table, intptr_t key, intptr_t k2) static u_long equal_hash(const ScmHashCore *table, intptr_t key) static int equal_cmp(const ScmHashCore *table, intptr_t key, intptr_t k2) static Entry *string_access(ScmHashCore *table, intptr_t k, ScmDictOp op) static u_long string_hash(const ScmHashCore *table, intptr_t key) static int string_cmp(const ScmHashCore *table, intptr_t k1, intptr_t k2) static u_long multiword_hash(const ScmHashCore *table, intptr_t key) static Entry *multiword_access(ScmHashCore *table, intptr_t k, ScmDictOp op) static Entry *general_access(ScmHashCore *table, intptr_t key, ScmDictOp op) static void hash_core_init(ScmHashCore *table, int hash_core_predef_procs(ScmHashType type, void Scm_HashCoreInitSimple(ScmHashCore *core, void Scm_HashCoreInitGeneral(ScmHashCore *core, int Scm_HashCoreTypeToProcs(ScmHashType type, void Scm_HashCoreCopy(ScmHashCore *dst, const ScmHashCore *src) void Scm_HashCoreClear(ScmHashCore *table) ScmDictEntry *Scm_HashCoreSearch(ScmHashCore *table, intptr_t key, int Scm_HashCoreNumEntries(ScmHashCore *table) void Scm_HashIterInit(ScmHashIter *iter, ScmHashCore *table) ScmDictEntry *Scm_HashIterNext(ScmHashIter *iter) static void hash_print(ScmObj obj, ScmPort *port, ScmWriteContext *ctx); SCM_DEFINE_BUILTIN_CLASS(Scm_HashTableClass, hash_print, NULL, NULL, NULL, ScmObj Scm_MakeHashTableSimple(ScmHashType type, int initSize) ScmObj Scm_HashTableCopy(ScmHashTable *src) ScmObj Scm_HashTableRef(ScmHashTable *ht, ScmObj key, ScmObj fallback) ScmObj Scm_HashTableSet(ScmHashTable *ht, ScmObj key, ScmObj value, int flags) ScmObj Scm_HashTableDelete(ScmHashTable *ht, ScmObj key) ScmObj Scm_HashTableKeys(ScmHashTable *table) ScmObj Scm_HashTableValues(ScmHashTable *table) ScmObj Scm_HashTableStat(ScmHashTable *table) static void hash_print(ScmObj obj, ScmPort *port, ScmWriteContext *ctx) static unsigned int round2up(unsigned int val) ScmHashEntry *Scm_HashTableGet(ScmHashTable *ht, ScmObj key) ScmHashEntry *Scm_HashTableAdd(ScmHashTable *ht, ScmObj key, ScmObj value) ScmHashEntry *Scm_HashTablePut(ScmHashTable *ht, ScmObj key, ScmObj value) void Scm__HashIterInitCompat(ScmHashTable *table, ScmHashIter *iter) ScmHashEntry *Scm__HashIterNextCompat(ScmHashIter *iter) ScmObj Scm_MakeHashTableMultiWord(int keysize, int initsize) ScmObj Scm_MakeHashTableFull(ScmClass *klass, int type, ScmHashProc hashfn, ScmObj Scm_MakeHashTable(ScmHashProc *hashfn, $
えーと上記全部が hash.c 内で定義されてる関数な情報でもないですし、漏れがある事もあり得ます。外 (hash.c の) との i/f になっていると思われる手続きは以下?
$ grep '^Scm' hash.c ScmDictEntry *Scm_HashCoreSearch(ScmHashCore *table, intptr_t key, ScmDictEntry *Scm_HashIterNext(ScmHashIter *iter) ScmObj Scm_MakeHashTableSimple(ScmHashType type, int initSize) ScmObj Scm_HashTableCopy(ScmHashTable *src) ScmObj Scm_HashTableRef(ScmHashTable *ht, ScmObj key, ScmObj fallback) ScmObj Scm_HashTableSet(ScmHashTable *ht, ScmObj key, ScmObj value, int flags) ScmObj Scm_HashTableDelete(ScmHashTable *ht, ScmObj key) ScmObj Scm_HashTableKeys(ScmHashTable *table) ScmObj Scm_HashTableValues(ScmHashTable *table) ScmObj Scm_HashTableStat(ScmHashTable *table) ScmHashEntry *Scm_HashTableGet(ScmHashTable *ht, ScmObj key) ScmHashEntry *Scm_HashTableAdd(ScmHashTable *ht, ScmObj key, ScmObj value) ScmHashEntry *Scm_HashTablePut(ScmHashTable *ht, ScmObj key, ScmObj value) ScmHashEntry *Scm__HashIterNextCompat(ScmHashIter *iter) ScmObj Scm_MakeHashTableMultiWord(int keysize, int initsize) ScmObj Scm_MakeHashTableFull(ScmClass *klass, int type, ScmHashProc hashfn, ScmObj Scm_MakeHashTable(ScmHashProc *hashfn, $
特に ScmObj 戻すのなんて絶対 i/f だよな、と。しかし grep ばっかしてねぇで、きちっと読めよって話ですな。あ、駄目だ。void がスルーされてるし
$ grep '^Scm\|^void' hash.c void Scm_HashCoreInitSimple(ScmHashCore *core, void Scm_HashCoreInitGeneral(ScmHashCore *core, void Scm_HashCoreCopy(ScmHashCore *dst, const ScmHashCore *src) void Scm_HashCoreClear(ScmHashCore *table) ScmDictEntry *Scm_HashCoreSearch(ScmHashCore *table, intptr_t key, void Scm_HashIterInit(ScmHashIter *iter, ScmHashCore *table) ScmDictEntry *Scm_HashIterNext(ScmHashIter *iter) ScmObj Scm_MakeHashTableSimple(ScmHashType type, int initSize) ScmObj Scm_HashTableCopy(ScmHashTable *src) ScmObj Scm_HashTableRef(ScmHashTable *ht, ScmObj key, ScmObj fallback) ScmObj Scm_HashTableSet(ScmHashTable *ht, ScmObj key, ScmObj value, int flags) ScmObj Scm_HashTableDelete(ScmHashTable *ht, ScmObj key) ScmObj Scm_HashTableKeys(ScmHashTable *table) ScmObj Scm_HashTableValues(ScmHashTable *table) ScmObj Scm_HashTableStat(ScmHashTable *table) ScmHashEntry *Scm_HashTableGet(ScmHashTable *ht, ScmObj key) ScmHashEntry *Scm_HashTableAdd(ScmHashTable *ht, ScmObj key, ScmObj value) ScmHashEntry *Scm_HashTablePut(ScmHashTable *ht, ScmObj key, ScmObj value) void Scm__HashIterInitCompat(ScmHashTable *table, ScmHashIter *iter) ScmHashEntry *Scm__HashIterNextCompat(ScmHashIter *iter) ScmObj Scm_MakeHashTableMultiWord(int keysize, int initsize) ScmObj Scm_MakeHashTableFull(ScmClass *klass, int type, ScmHashProc hashfn, ScmObj Scm_MakeHashTable(ScmHashProc *hashfn, $
あ。static だったり int 戻すのもあるな。
static unsigned int round2up(unsigned int val); static Entry *insert_entry(ScmHashCore *table, static Entry *delete_entry(ScmHashCore *table, static Entry *address_access(ScmHashCore *table, static u_long address_hash(const ScmHashCore *ht, intptr_t obj) static int address_cmp(const ScmHashCore *ht, intptr_t key, intptr_t k2) static u_long eqv_hash(const ScmHashCore *table, intptr_t key) static int eqv_cmp(const ScmHashCore *table, intptr_t key, intptr_t k2) static u_long equal_hash(const ScmHashCore *table, intptr_t key) static int equal_cmp(const ScmHashCore *table, intptr_t key, intptr_t k2) static Entry *string_access(ScmHashCore *table, intptr_t k, ScmDictOp op) static u_long string_hash(const ScmHashCore *table, intptr_t key) static int string_cmp(const ScmHashCore *table, intptr_t k1, intptr_t k2) static u_long multiword_hash(const ScmHashCore *table, intptr_t key) static Entry *multiword_access(ScmHashCore *table, intptr_t k, ScmDictOp op) static Entry *general_access(ScmHashCore *table, intptr_t key, ScmDictOp op) static void hash_core_init(ScmHashCore *table, int hash_core_predef_procs(ScmHashType type, void Scm_HashCoreInitSimple(ScmHashCore *core, void Scm_HashCoreInitGeneral(ScmHashCore *core, int Scm_HashCoreTypeToProcs(ScmHashType type, void Scm_HashCoreCopy(ScmHashCore *dst, const ScmHashCore *src) void Scm_HashCoreClear(ScmHashCore *table) ScmDictEntry *Scm_HashCoreSearch(ScmHashCore *table, intptr_t key, int Scm_HashCoreNumEntries(ScmHashCore *table) void Scm_HashIterInit(ScmHashIter *iter, ScmHashCore *table) ScmDictEntry *Scm_HashIterNext(ScmHashIter *iter) static void hash_print(ScmObj obj, ScmPort *port, ScmWriteContext *ctx); ScmObj Scm_MakeHashTableSimple(ScmHashType type, int initSize) ScmObj Scm_HashTableCopy(ScmHashTable *src) ScmObj Scm_HashTableRef(ScmHashTable *ht, ScmObj key, ScmObj fallback) ScmObj Scm_HashTableSet(ScmHashTable *ht, ScmObj key, ScmObj value, int flags) ScmObj Scm_HashTableDelete(ScmHashTable *ht, ScmObj key) ScmObj Scm_HashTableKeys(ScmHashTable *table) ScmObj Scm_HashTableValues(ScmHashTable *table) ScmObj Scm_HashTableStat(ScmHashTable *table) static void hash_print(ScmObj obj, ScmPort *port, ScmWriteContext *ctx) static unsigned int round2up(unsigned int val) ScmHashEntry *Scm_HashTableGet(ScmHashTable *ht, ScmObj key) ScmHashEntry *Scm_HashTableAdd(ScmHashTable *ht, ScmObj key, ScmObj value) ScmHashEntry *Scm_HashTablePut(ScmHashTable *ht, ScmObj key, ScmObj value) void Scm__HashIterInitCompat(ScmHashTable *table, ScmHashIter *iter) ScmHashEntry *Scm__HashIterNextCompat(ScmHashIter *iter) ScmObj Scm_MakeHashTableMultiWord(int keysize, int initsize) ScmObj Scm_MakeHashTableFull(ScmClass *klass, int type, ScmHashProc hashfn, ScmObj Scm_MakeHashTable(ScmHashProc *hashfn, $
わはは。なんだこのエントリ。無駄に長いぞ。
アタマに static 付いてるのは i/f になり得ないのでとりあえずスルーとして、コンストラクタくさいのは
- void Scm_HashCoreInitSimple(ScmHashCore *core,
- void Scm_HashCoreInitGeneral(ScmHashCore *core,
- ScmObj Scm_MakeHashTableSimple(ScmHashType type, int initSize)
くらい?
ってか、微妙に gdgd 進めてる感満点でスミマセン。どうやらコンストラクタは Scm_MakeHashTableSimple() 手続きらしくはあるんですが weak.c に定義されてる Scm_MakeWeakHashTableSimple() 手続きもそうらしい。
なんか gdgd 杉なんで
とりあえずコンストラクタと思われる Scm_MakeHashTableSimple() 手続きを起点に掘ってみる事にします。以下なカンジ。
SCM_DEFINE_BUILTIN_CLASS(Scm_HashTableClass, hash_print, NULL, NULL, NULL, SCM_CLASS_DICTIONARY_CPL); ScmObj Scm_MakeHashTableSimple(ScmHashType type, int initSize) { ScmHashTable *z; /* We only allow ScmObj in <hash-table> */ if (type > SCM_HASH_GENERAL) { Scm_Error("Scm_MakeHashTableSimple: wrong type arg: %d", type); } z = SCM_NEW(ScmHashTable); SCM_SET_CLASS(z, SCM_CLASS_HASH_TABLE); Scm_HashCoreInitSimple(&z->core, type, initSize, NULL); z->type = type; return SCM_OBJ(z); }
とりあえず、直上でナニされてるマクロ見てみる。gauche.h にて以下な定義。
/* Define built-in class statically -- full-featured version */ #define SCM_DEFINE_BUILTIN_CLASS(cname, printer, compare, serialize, allocate, cpa) \ SCM__DEFINE_CLASS_COMMON(cname, 0, \ SCM_CLASS_BUILTIN, \ printer, compare, serialize, allocate, cpa)
このあたり、明日きちっとトレイスします。脱線しそうなんで ...
Hash のコンストラクタ
ざくっと以下。
/* We only allow ScmObj in <hash-table> */ if (type > SCM_HASH_GENERAL) { Scm_Error("Scm_MakeHashTableSimple: wrong type arg: %d", type); }
な部分ですが SCM_HASH_GENERAL より type が大きかったらナニ、との事にて定義が hash.h にて以下。
/* Hash types */ typedef enum { SCM_HASH_EQ, SCM_HASH_EQV, SCM_HASH_EQUAL, SCM_HASH_STRING, SCM_HASH_GENERAL, SCM_HASH_WORD } ScmHashType;
上記によれば gauche での hash table な種類は 5 種類らしい。ここも別途で先を確認。
z = SCM_NEW(ScmHashTable); SCM_SET_CLASS(z, SCM_CLASS_HASH_TABLE); Scm_HashCoreInitSimple(&z->core, type, initSize, NULL); z->type = type; return SCM_OBJ(z); }
ポイント高いと思われるのは Scm_HashCoreInitSimple() 手続きですな。
ってか
このあたりも二番煎じな気がしてきた ...
と言いつつ Scm_HashCoreInitSimple() 手続きを見るんですが以下なカンジ。
void Scm_HashCoreInitSimple(ScmHashCore *core, ScmHashType type, unsigned int initSize, void *data) { SearchProc *accessfn; ScmHashProc *hashfn; ScmHashCompareProc *cmpfn; if (hash_core_predef_procs(type, &accessfn, &hashfn, &cmpfn) == FALSE) { Scm_Error("[internal error]: wrong TYPE argument passed to Scm_HashCoreInitSimple: %d", type); } hash_core_init(core, accessfn, hashfn, cmpfn, initSize, data); }
hash_core_predef_procs() 手続きで
- accessfn
- hashfn
- cmpfn
なポインタに適切な手続きのポインタがセットされたら hash_core_init() 手続きでそれらを含めた属性値のセットですかそうですか。