ざっくり見すぎ
なんとなくこうなっていくんだな、というあたりは見えかけてたんですが、なんとなく腑にオチないな、と言いつつ repl_read_cc 手続き (repl.c の L102) 見てて微妙な違和感。
Scm_VMPushCC(repl_eval_cc, data, 4); return Scm_VMEval(result, SCM_FALSE);
よく考えたら普通に push とか言ってますが、スタックから取り出すのは誰だっけ、という事に思い至る。
なんかおかしいぞ、と言いつつ Scm_Repl 手続き (repl.c の L192) に戻って
void Scm_Repl(ScmObj reader, ScmObj evaluator, ScmObj printer, ScmObj prompter) { Scm_ApplyRec(SCM_OBJ(&repl_STUB), SCM_LIST4(reader, evaluator, printer, prompter)); }
Scm_ApplyRec 手続き (vm.c の L1386) を掘削。以下が実装。
ScmObj Scm_ApplyRec(ScmObj proc, ScmObj args) { int nargs = Scm_Length(args), i; ScmVM *vm = theVM; if (nargs < 0) { Scm_Error("improper list not allowed: %S", args); } for (i=0; i<nargs; i++) { if (i == SCM_VM_MAX_VALUES-1) { vm->vals[i] = args; break; } vm->vals[i] = SCM_CAR(args); args = SCM_CDR(args); } return apply_rec(vm, proc, nargs); }
引数を vm->valss に格納して apply_rec をナニ。apply_rec は vm.c の L1374 で定義されてて実装が以下。
/* NB: The ApplyRec family can be called in an inner loop (e.g. the display callback from GLUT.) So we don't want to allocate at all. We put a temporary code vector on C stack. It is OK, since once user_eval_inner returns it would never be reused. However, tools that want to keep a pointer to a code vector would need to be aware of this case. */ 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 が出てきた。良かった (何
しかし
何故にこれまでここに到達できなかったんだろうか。そして user_eval_innser 手続き内で呼び出されてる run_loop 手続きがやたらに短くなっている 0.9。
そして include されてる vminsn.c は vminsn.scm からナニされたコードな模様。
今後
なんとなくこれまで理解が微妙というかあえて掘らなかった部分がなんとなく明らかになったので、以下な部分を確認希望。
- repl のアウトライン
- なんとなく run_loop は 0.8 系ってコトにして
- user_eval_inner までの流れ
- run_loop というか vminsn.scm とか vminsn.c とかの仕組み
- compile.scm
なんか最後らへんは野望ちっくですがどうなるやら。