repl.c あたり
面白いんですが整理が大変。とりあえず確認したのは Scm_ApplyRec 手続きからなんですが、ここでは引数で渡されたリストの要素を取り出しながら vm->vals 配列に格納して apply_rec 手続きを呼び出してます。
apply_rec 手続きの定義が以下。
static ScmObj apply_rec(ScmVM *vm, ScmObj proc, int nargs) { ScmObj program; ScmWord code[2]; code[0] = SCM_WORD(SCM_VM_INSN1(SCM_VM_VALUES_APPLY, nargs)); code[1] = SCM_WORD(SCM_VM_INSN(SCM_VM_RET)); vm->val0 = proc; program = vm->base? SCM_OBJ(vm->base) : SCM_OBJ(&internal_apply_compiled_code); return user_eval_inner(program, code); }
いっちゃん下で呼ばれる user_eval_inner で上記の code な配列は PC にセットされて run_loop 手続きが呼び出されてます。vm->val0 に repl_STUB な C 手続きがセットされてるので、これが apply されるはず。
ここが bootstrap なナニですな。
あとなんとなくな理解としては、上記の user_eval_inner 手続きからは戻らないのではないかな。ちょっと確証ないですが。
apply される手続き
repl.c の repl_proc 手続き以降がナニ。この手続きからの戻りは末端で呼び出されてる Scm_VMRepl 手続きの戻り値。Scm_VMRepl 手続きの定義は以下で
ScmObj Scm_VMRepl(ScmObj reader, ScmObj evaluator, ScmObj printer, ScmObj prompter) { ScmObj ehandler, reploop; ScmObj *packet = SCM_NEW_ARRAY(ScmObj, 4); packet[0] = reader; packet[1] = evaluator; packet[2] = printer; packet[3] = prompter; ehandler = Scm_MakeSubr(repl_error_handle, packet, 1, 0, SCM_FALSE); reploop = Scm_MakeSubr(repl_main, packet, 0, 0, SCM_FALSE); Scm_VMPushCC(repl_loop_cc, (void**)packet, 4); return Scm_VMWithErrorHandler(ehandler, reploop); }
継続を repl_loop_cc 手続きにして Scm_VMWithErrorHandler 手続きの戻りを戻す形。これは reploop (repl_main 手続き) の戻り値を戻すはず。
repl_main 手続きの戻り
は何か、というと順に
- repl_main
- repl_prompt_cc
- repl_read_cc
- repl_prompt_cc
という順で呼び出されて repl_read_cc 手続きにて
- repl_eval_cc 手続きが Scm_VMPushCC されて
- Scm_VMEval 手続きが呼び出される
という形。戻りは Scm_VMEVal 手続きの戻り。継続な read_eval_cc 手続きでは結果が出力されて repl_main 手続きが起動されてます。
む、でも継続な repl_eval_cc では Scm_VMEval 手続きの戻りは完全スルーに見えますな。このあたり、もう少しきちんと掘ってみた方が良さげ。