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 方面に出力開始。