throw_cont_body 手続き
通常時の継続な手続きオブジェクトの本体がこれ。
最初は handlers が pair な場合の処理の意味が全然分かりませんでしたが、おかげ様でイメージできるようになりました。この手続き、ざっくりベースで
if (handlers がペア) { (caar handlers) を呼び出す準備をしつつ (cdr handler) を処理する用意をして handler 手続きを呼び出した後に残りを処理するよう継続を設定 } 継続手続きとしての処理を行なって値を戻す
みたいなカンジ。朝、ぼさっと運転してて handlers がペアだった場合、どこからどうやって戻るんだろうか、という事に気がついて車を降りた後に確認。
handlers は throw_cont_calculate_handlers() 手続きで作られるんですが、ここを追い掛けるリキは現時点でないッス。
handlers がリストのケイス
handlers なリストをめくりつつ、caar な要素を呼び出す。vm->handlers には cdar な要素をセットしておく (詳細未確認ですが、何か (例外とか) があった場合に巻き戻して云々な保険に見えます)。
で、最終的に handlers が NULL になったらどうするんだろ、と思っていたらそのまんま
* now, install the target continuation
な処理をして終了、なのか。
リストをめくりつつ、な根拠
throw_cont_body() 手続きの以下な部分
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);
data な配列に格納されたナニを引数フレームに push しといて throw_cont_cc()手続きをスタックに push。で handler な手続きをナニ。
ちなみに件の throw_cont_cc() 手続きの定義が以下。
static ScmObj throw_cont_cc(ScmObj result, void **data) { ScmObj handlers = SCM_OBJ(data[0]); ScmEscapePoint *ep = (ScmEscapePoint *)data[1]; ScmObj args = SCM_OBJ(data[2]); return throw_cont_body(handlers, ep, args); }
どんどんカワを剥いでいる模様。全部ナニしたら上記の通り、install the target continuation して終了なはず。