メモ

昨晩遅くまで飲酒 && 今朝は子供の行事でへろへろ。色々な意味で微妙ですがソース読みに着手。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);
}

明日はゆっくりするらしいので、こっから先、とゆーコトで。