メモ
昨晩遅くまで飲酒 && 今朝は子供の行事でへろへろ。色々な意味で微妙ですがソース読みに着手。Hash なソレが出てきてたりするのでメモを取りつつ読んでみる
と言いつつ昼寝
今日は休むか、と言いつつ昼寝前に プログラミング Gauche のモジュールの章を確認。成程ね、と言いつつ意識を失なって晩飯の支度に至る。
その後
だらだらと module.c を眺める。あと gauche.h で定義されてる ScmModuleRec 構造体の定義を以下にメモ
struct ScmModuleRec { SCM_HEADER; ScmSymbol *name; ScmObj imported; /* list of imported modules */ ScmObj exported; /* list of exported symbols */ int exportAll; /* TRUE if (export-all) */ ScmObj parents; /* direct parent modules */ ScmObj mpl; /* module precedence list */ ScmObj depended; /* list of modules that are depended by this module for compilation */ ScmHashTable *table; /* binding table */ };
プログラミング Gauche のモジュールの章的にふむふむってカンジ。課題の Scm_FindModule() は基本的に引数な flags が
- 0x1 との and が 0 以外
- そうでない (0x1 との and が 0)
という形で処理が分岐している。ざっくりベースで言うと
- find に失敗した場合モジュールが作られる
- find に失敗した場合 NULL が戻る
な形になっている風に読める。とは言えその先が問題で具体的に作るって何だよ、と。
なんとなく
create な場合には空っぽなモジュールオブジェクトが modules に追加されるんだろな、というのはなんとなく分かる。違うかも、ですが。
でも何故に create しない場合は Scm_HashTableRef で良くって、そうでない場合は Scm_HashCoreSearch を使うのか、が微妙。
ScmHashTable 型
ScmHashTableRec 構造体の定義が以下
struct ScmHashTableRec { SCM_HEADER; ScmHashType type; ScmHashCore core; };
ええと create とそうではないナニの違いは
- ただの lookup (create ではない) の時は ScmHashTable 型を Scm_HashTableRef に渡す
- そうでない場合 (create な時) は core 属性を Scm_HashCoreSearch に渡す
みたい。そういえば小飼弾さんのエントリにリストで hash が云々なエントリがありましたな。(違
って掘ってみたら Scm_HashTableRef も内部で Scm_HashCoreSearch 呼んでます。これは抽象化され杉でその先がナニ。
ScmDictEntry *Scm_HashCoreSearch(ScmHashCore *table, intptr_t key, ScmDictOp op) { SearchProc *p = (SearchProc*)table->accessfn; return (ScmDictEntry*)p(table, key, op); }
あるいは ScmHashCore 型なソレがどんなか、というと
struct ScmHashCoreRec { void **buckets; int numBuckets; int numEntries; int numBucketsLog2; void *accessfn; /* actual type hidden */ ScmHashProc *hashfn; ScmHashCompareProc *cmpfn; void *data; };
これはこれは、としか言いようがないな。抽象度高すぎ。
具体的に、な部分で掘り下げてみると、例えば lookup_module_create 関数で Scm_HashCoreSearch の戻りの value 属性が 0 だった場合の処理で SCM_DICT_SET_VALUE マクロに渡している make_module(name) なソレがあやしげ。
static ScmObj make_module(ScmSymbol *name) { ScmModule *m; m = SCM_NEW(ScmModule); SCM_SET_CLASS(m, SCM_CLASS_MODULE); init_module(m, name); return SCM_OBJ(m); }
さらに怪しいのは init_module 関数で直上で定義。
static void init_module(ScmModule *m, ScmSymbol *name) { m->name = name; m->imported = m->exported = m->depended = SCM_NIL; m->exportAll = FALSE; m->parents = defaultParents; m->mpl = Scm_Cons(SCM_OBJ(m), defaultMpl); m->table = SCM_HASH_TABLE(Scm_MakeHashTableSimple(SCM_HASH_EQ, 0)); }
table 属性にセットされているソレは何か、というと
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); }
な戻りを ScmHashTable 型にキャストしてセットしとりますな。上記なソレ的にはフォーカスを当るべきなのは 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); }
明日はゆっくりするらしいので、こっから先、とゆーコトで。