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() 関数

絶対このあたりログを残してるな、と思いつつ投入。