SCM_CONDITIONP と ScmError 型

ようやく午後になって作業再開。なんか昨晩ワケワカなまま意識を失なってるな。
途中で SCM_CLASS_CATEGORY に着目しているが何故かは不明。二度手間かもしれませんが、SCM_ISA の中身から再度チェキ。定義は以下

#define SCM_ISA(obj, klass) (SCM_XTYPEP(obj,klass)||Scm_TypeP(SCM_OBJ(obj),klass))

まず SCM_XTYPEP マクロ

#define SCM_XTYPEP(obj, klass) \
    (SCM_PTRP(obj)&&(SCM_OBJ(obj)->tag == SCM_CLASS2TAG(klass)))

これは obj がポインタで klass + 3 が obj の tag 属性と同じ値 (つまり obj は klass のインスタンス) かどうかを判定している。問題にしている SCM_CONDITIONP マクロは

#define SCM_CONDITIONP(obj)        SCM_ISA(obj, SCM_CLASS_CONDITION)

となってて obj が SCM_CLASS_CONDITION クラスのインスタンスかどうかを判定しているのか。

ようやくカン違いに気がつく

ScmError 型の定義が

typedef ScmMessageCondition ScmError;

で ScmMessageCondition は

/* <message-condition> : condition with message. */
typedef struct ScmMessageConditionRec {
    ScmCondition common;
    ScmObj message;             /* message */
} ScmMessageCondition;

で、ヘッダ部分に ScmCondition 型の属性があったからどっかで何とかなるだろう、というカンが邪魔してました。(とほほ
しかも SCM_CLASS_CATEGORY 云々は完全ダウト。答えは昨晩のエントリにヒントあり。Scm_ErrorClass を define している部分

SCM_DEFINE_BASE_CLASS(Scm_ErrorClass, ScmError,
                      message_print, NULL, NULL, 
                      message_allocate, error_cpl+1);

備忘録まで ScmClassRec 構造体の定義 (の一部) を以下に

struct ScmClassRec {
    SCM_INSTANCE_HEADER;
    ScmClassPrintProc     print;
    ScmClassCompareProc   compare;
    ScmClassSerializeProc serialize;
    ScmClassAllocateProc  allocate;
    ScmClass **cpa;             /* class precedence array, NULL terminated */
(以下略

いっちゃん最後の cpa という属性が Scm_SubtypeP() 関数の中で使われている。class precedence ってどう訳すんだろうか。
そりゃ良いとして ScmClass 型の Scm_ErrorClass という領域を静的に確保する SCM_DEFINE_BASE_CLASS マクロに error_cpl+1 を渡しているけど、これが上記の cpa という属性に設定される。では error_cpl って何か、というと

static ScmClass *error_cpl[] = {
    ERROR_CPL,
    NULL
};

ポインタ配列。ERROR_CPL マクロと関連マクロを以下に

#define CONDITION_CPL                           \
    SCM_CLASS_STATIC_PTR(Scm_ConditionClass),   \
    SCM_CLASS_STATIC_PTR(Scm_TopClass)

#define MESSAGE_SERIOUS_CPL \
    SCM_CLASS_STATIC_PTR(Scm_MessageConditionClass), \
    SCM_CLASS_STATIC_PTR(Scm_SeriousConditionClass), \
    CONDITION_CPL

#define ERROR_CPL \
    SCM_CLASS_STATIC_PTR(Scm_ErrorClass),        \
    MESSAGE_SERIOUS_CPL

実際にはこんなカンジでしょうか。

static ScmClass *error_cpl[] = {
    &Scm_ErrorClass,
    &Scm_MessageConditionClass,
    &Scm_SeriousConditionClass,
    &Scm_ConditionClass,
    &Scm_TopClass,
    NULL
};

+1 されている、というのが微妙に謎ですが、とりあえずスルー。これがあるので Scm_TypeP で真が戻る、という事になるはずです。再度引用

int Scm_SubtypeP(ScmClass *sub, ScmClass *type)
{
    ScmClass **p;
    if (sub == type) return TRUE;

    p = sub->cpa;
    while (*p) {
        if (*p++ == type) return TRUE;
    }
    return FALSE;
}

int Scm_TypeP(ScmObj obj, ScmClass *type)
{
    return Scm_SubtypeP(Scm_ClassOf(obj), type);
}

この位さくっと理解しろや、という声が背後及び自分の中から聞こえてまいりますが、これもスルー。とりあえず Reading Gauche 方面に出力開始。