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)); }
なんか今までの見方が微妙だなぁ、と思いつつ色々掘じくりカエしてたんですが、repl.c の先頭に以下なコメントを発見。
/* * Conceptually, repl can be described by the following Scheme code. * * (define (repl reader evaluator printer prompter) * (let loop1 () * (and * (with-error-handler * (lambda (e) (report-error e) #t) * (lambda () * (prompter) * (let loop2 ((exp (reader))) * (if (eof-object? exp) * #f * (begin * (call-with-values * (lambda () (evaluator exp (current-module))) * printer) * (loop2 (reader))))))) * (loop1)))) * * It is implemented using trampoline so that it can run without crossing * C -> Scheme boundary. * * VMRepl -> VMWithErrorHandler -> repl_main -> prompter * -> repl_prompt_cc -> reader -> repl_read_cc -> evaluator * -> repl_eval_cc -> printer -> repl_print_cc -> repl_main */
これはなんとなくイメージできてるな。
話を元に戻す
Scm_ApplyRec と repl_STUB の理解が微妙。
とりあえず repl_STUB は以下なマクロで定義。
static SCM_DEFINE_SUBR(repl_STUB, 0, 1, SCM_OBJ(&repl_NAME), repl_proc, NULL, NULL);
SCM_DEFINE_SUBR マクロは gauche.h で定義。
#define SCM__DEFINE_SUBR_INT(cvar, req, opt, inf, flags, func, inliner, data) \ ScmSubr cvar = { \ SCM__PROCEDURE_INITIALIZER(SCM_CLASS_STATIC_TAG(Scm_ProcedureClass),\ req, opt, SCM_PROC_SUBR, inf, inliner), \ flags, (func), (data) \ } #define SCM_DEFINE_SUBR(cvar, req, opt, inf, func, inliner, data) \ SCM__DEFINE_SUBR_INT(cvar, req, opt, inf, 0, func, inliner, data)
ScmSubr 型の repl_STUB というソレを定義している形になるのか。この C な特殊形式を Scm_ApplyRec がどう評価するのか、がイメージできれば良いんですが。
てーか、Scm_ApplyRec 手続きの先が具体的によく分からのですが、別途以下なコメントの意味を確認予定。
/* 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. */
うーん。