Scm_VMPushCC() とか POP_CONT とか
いくつか確認してみて余力があれば VMDynamicWind の流れを見てみる方向。
POP_CONT マクロ
C-continuation は継続フレームの argp が NULL、という事は以下の部分が該当すると思われる。
if (CONT->argp == NULL) { \ void *data__[SCM_CCONT_DATA_SIZE]; \ ScmCContinuationProc *after__; \ void **d__ = data__; \ void **s__ = (void**)((ScmObj*)CONT + CONT_FRAME_SIZE); \ int i__ = CONT->size; \ while (i__-- > 0) { \ *d__++ = *s__++; \ } \ after__ = (ScmCContinuationProc*)CONT->pc; \ if (IN_STACK_P((ScmObj*)CONT)) SP = (ScmObj*)CONT; \ ENV = CONT->env; \ ARGP = SP; \ PC = PC_TO_RETURN; \ CONT = CONT->prev; \ BASE = CONT->base; \ VAL0 = CALL_CCONT(after__, VAL0, data__); \ } else if (IN_STACK_P((ScmObj*)CONT)) { \
げ。最後のソレがハードル高い。どーゆー意味だ。
とりあえず整理
これって Scm_VMPushCC() を先に確認した方が良いな。という事で
Scm_VMPushCC() 手続き
コメントがナニ。
/* Arrange C function AFTER to be called after the procedure returns. * Usually followed by Scm_VMApply* function. */
プロタイプが以下なカンジ
void Scm_VMPushCC(ScmCContinuationProc *after, void **data, int datasize)
ちなみに ScmContinuationProc の定義が gauche/vm.h で以下
typedef ScmObj ScmCContinuationProc(ScmObj result, void **data);
ええと after を手続きから戻った後に呼び出されるようにしといて、大抵 Scm_VMapply* が後にナニ、という事かなぁ。Scm_VMDynamicWind() な末端は以下です。
Scm_VMPushCC(dynwind_before_cc, data, 3); return Scm_VMApply0(before);
ひええ。この時点で val0 がどうなってるか、は現時点で微妙かも。とりあえず、Scm_VMPushCC() 手続きはざっくりベースで
- ScmCContinuationProc な手続きを継続フレームの PC に設定
- data なソレを引数として stack に積む
な後に VMapply* で何かをした後に上記で push した手続きに戻る、という事かと。
戻ってみる
例えば VMDynamicWind からだと関数定義が以下で
ScmObj Scm_VMDynamicWind(ScmObj before, ScmObj body, ScmObj after) { void *data[3]; /* NB: we don't check types of arguments, since we allo object-apply hooks can be used for them. */ data[0] = (void*)before; data[1] = (void*)body; data[2] = (void*)after; Scm_VMPushCC(dynwind_before_cc, data, 3); return Scm_VMApply0(before); }
before が適用された後の継続が dynwind_before_cc という事になるのか。val0 は不明なので実際な例が無いと微妙。
明日
アタマを冷して確認して先を検討予定ッス。(とほほ