下書きというかメモというか
とりあえず throw_cont_calculate_handlers() は一旦スルー。
今の所、ガワだけあって中身を投入しないといかんのは
- Scm_VMCallCC()
- throw_cont_body()
- throw_continuation()
な模様。ただ、throw_continuation() は Rewind C stack なナニが微妙なので完了は不可能。とりあえず以下に下書きというか検討メモを。
throw_cont_body() 手続き
この手続きのポイントとしては引数の handlers が空リストで無かった場合に handlers が空になるまで下記のコードで繰り返しを表現してる部分?
if (SCM_PAIRP(handlers)) { ScmObj handler, chain; SCM_ASSERT(SCM_PAIRP(SCM_CAR(handlers))); handler = SCM_CAAR(handlers); chain = SCM_CDAR(handlers); data[0] = (void*)SCM_CDR(handlers); data[1] = (void*)ep; data[2] = (void*)args; Scm_VMPushCC(throw_cont_cc, data, 3); vm->handlers = chain; return Scm_VMApply0(handler); }
でも肝心な_継続_の起動ってそれ以降だったりするんですが。
で、上記が繰り返しになるのは Scm_VMPushCC() に throw_cont_cc() を渡すナニがポイント。渡してる data も実質 throw_cont_body() の引数で data[0] には (cdr handlers) が渡されてるのが scheme 的なリストを手繰る繰り返しで良いカンジ。
どっかで見たと思ったら末尾再帰っぽい。わははは。
あと、リストの先頭要素の car が次に呼び出す手続きで、cdr がその手続きの handlers になってるあたりも面白い。このあたりは throw_cont_calculate_handlers() が仕込んでいる部分だったりするんですが。
残り
継続って Scm_VMCallCC() で作られる以下のソレが
contproc = Scm_MakeSubr(throw_continuation, ep, 0, 1, SCM_MAKE_STR("continuation"));
渡される一引数な手続きの中でグローバルなナニに束縛されて、それが呼び出された時点で、という事なんですが、件の継続手続きには引数は一つしか指定できません。
# なんか日本語微妙になりつつあります
正確に言うと指定できないというよりも無視されるのか。まず、上記の throw_continuation() の呼び出しが以下。
VAL0 = SCM_SUBR(VAL0)->func(ARGP, argc, SCM_SUBR(VAL0)->data);
で、上記の ARGP がどのように扱われてるかというと
ScmObj args = argframe[0];
ってコトで先頭一つだけ。他は無視なのか。あとはそれが
- 要素一つのリスト
- 要素 1 未満
- それ以外
という仕切りで処理。
下書き
ここで終わると微妙だな、と思いつつ明日も仕事だったり。
とりあえず上記を纏めてみるとどうなるか。とりあえず箇条書きで。
- 引数 handlers が空リストでなければそれが空になるまで cadr を apply する
- 引数 handlers が空リストであれば
- PC に RET を設定
- CONT に引数で渡された ep の cont 属性を設定
- vm->handlers に引数で渡された ep の handlers 属性を設定
した後に渡された引数なリストの要素が
- 一つであれば car を戻す
- 一つ未満であれば SCM_UNDEFINED を戻す
- 複数であれば多値を戻す
む。handlers なナニな記述が足りてませんがもう限界。