Scm_FindBinding 手続き (2)
ええと、昨晩のエントリは若干微妙?
# でもないのか ... (何
とりあえず引数 flags の末端 bit の on/off がポイント。一応 SCM_BINDING_STAY_IN_MODULE の定義を以下に。
gauche.h
/* Flags for Scm_FindBinding and Scm_GlobalVariableRef */ enum { /* do not search parent/imported */ SCM_BINDING_STAY_IN_MODULE = (1L<<0) };
ちょっとへろへろなので機械的に掘ってみます。module.c にて定義されている Scm_FindBinding() 関数の以下部分が起点。
v = Scm_HashTableRef(m->table, SCM_OBJ(symbol), SCM_FALSE);
Scm_HashTableRef() 関数に渡している引数は以下
- 引数の ScmModule *module の table 属性
- 引数の ScmSymbol *symbol を ScmObj でキャストしたナニ
- SCM_FALSE
この関数の定義は hash.c にて以下。
ScmObj Scm_HashTableRef(ScmHashTable *ht, ScmObj key, ScmObj fallback) { ScmDictEntry *e = Scm_HashCoreSearch(SCM_HASH_TABLE_CORE(ht), (intptr_t)key, SCM_DICT_GET); if (!e) return fallback; else return SCM_DICT_VALUE(e); }
えーと、Scm_HashCoreSearch() の戻りが NULL だったら fallback が戻りますが、このケイスでは SCM_FALSE が戻りますな。
戻りがそうでない場合はどうか、というと SCM_DICT_VALUE の定義が以下。
#define SCM_DICT_VALUE(entry) SCM_OBJ((entry)->value)
あ、ScmDictEntry の定義は直上で以下。
/* * Common part of the entry. This is for the lower layer. */ typedef struct ScmDictEntryRec { const intptr_t key; intptr_t value; } ScmDictEntry;
intptr_t 微妙ですが void * なソレと見とく。と、Scm_HashCoreSearch() 手続きの戻りが NULL 以外の場合は e (ScmDictEntry 型) の value 属性の値 (汎用ポインタ型) が戻る、と。
戻り先では
if (SCM_GLOCP(v)) {
戻った値が Scm_GolcClass 型のポインタで
gloc = SCM_GLOC(v); if (!SCM_UNBOUNDP(gloc->value)) goto found;
戻った値の value 属性が unbound でなければ found に jmp している。とりあえず直感的に Hash の値を戻してるな、というのは分かりますな。
もう少し
Scm_HashCoreSearch() を掘ってみる。hash.c にて以下。
ScmDictEntry *Scm_HashCoreSearch(ScmHashCore *table, intptr_t key, ScmDictOp op) { SearchProc *p = (SearchProc*)table->accessfn; return (ScmDictEntry*)p(table, key, op); }
ええと、呼び出しなソレをもっかい確認した方が良いな。
ScmDictEntry *e = Scm_HashCoreSearch(SCM_HASH_TABLE_CORE(ht), (intptr_t)key, SCM_DICT_GET);
スデに呼び出し時に ScmHashTable 型の core 属性の値を渡してます。これは struct ScmHashCoreRec 型になってて accessfn 属性の定義が以下。
void *accessfn; /* actual type hidden */
これを SearchProc * 型の p に代入して手続き呼び出してます。えーと、SearchProc 型って何だば、というと定義は hash.c で以下。
# だんだん類似のエントリ投入済みな気がしてきましたが続行
typedef Entry *SearchProc(ScmHashCore *core, intptr_t key, ScmDictOp op);
この定義は Entry * を戻す引数が (ScmHashCore *core, intptr_t key, ScmDictOp op) な関数ポインタという事になるはず。
もうすこしツッコむと struct ScmHashCoreRec 構造体の定義の一部は以下のようになってて
void *accessfn; /* actual type hidden */ ScmHashProc *hashfn; ScmHashCompareProc *cmpfn; void *data;
accessfn はあえて void * で定義されてるんですが、このあたりも意味があるんでしょうね。今のトコロは何故にここまで抽象化 (?) しないと駄目なのかが不明。
そしてここから以降で実際にどんな手続きが呼び出されるか、がマスクされとります。
そろそろ限界
accessfn で M-s してたら hash_core_predef_procs() という手続きを発見。とりあえずこれを呼び出してるのが以下。
- Scm_HashCoreInitSimple() 関数
- hash_core_predef_procs() 関数
絶対このあたりログを残してるな、と思いつつ投入。