test/dynwind.scm (4)
今日もへろへろ気味なんで微妙かも。昨晩の続きなんですが
;; continuation invoked while inline procedure is prepared. ;; a test to see call/cc won't mess up the VM stack. (define (callcc-test2) (let ((cc #f) (r '())) (let ((s (list 1 2 3 4 (call/cc (lambda (c) (set! cc c) 5)) 6 7 8))) (if (null? r) (begin (set! r s) (cc -1)) (list r s))))) (test "call/cc (inline)" '((1 2 3 4 5 6 7 8) (1 2 3 4 -1 6 7 8)) callcc-test2)
disasm してみる事に。
こんなカンジに。
gosh> (disasm (lambda () (list 1 2 3 (call/cc (lambda (c) (set! cont c) 4)) 5 6))) main_code (name=#f, code=0x8149ee0, size=14, const=2, stack=13): args: #f 0 CONSTI-PUSH(1) 1 CONSTI-PUSH(2) 2 CONSTI-PUSH(3) 3 PRE-CALL(1) 9 5 CLOSURE #<lambda 0> ; (lambda (c) (set! cont c) 4) 7 PUSH-GREF-CALL(1) #<identifier user#call/cc>; (call/cc (lambda (c) (set! cont c) 4)) 9 PUSH 10 CONSTI-PUSH(5) 11 CONSTI(6) 12 LIST(6) ; (list 1 2 3 (call/cc (lambda (c) (set! c ... 13 RET internal_closure_0 (name=#f, code=0x80d7b40, size=5, const=1 stack=0): args: #f 0 LREF0 ; c 1 GSET #<identifier user#cont>; cont 3 CONSTI(4) 4 RET #<undef> gosh>
PRE-CALL って何だ、と言いつつ ReadingGauche の PRE_CALL の項を確認。基本的には
- 戻り先を 9 にしといて
- クロージャを作って val0 にセット
- val を push して call/cc を CALL
コメントにある_VM スタックをめちゃめちゃにしない_というのはどーゆー意味か。あら? そゆ意味では、上記な vm 命令レベルの継続ってどうなってるのかな、と言いつつ色々弄ってると vm.c に Scm_VMCallCC という手続きを発見。
ScmObj Scm_VMCallCC(ScmObj proc) { ScmObj contproc; ScmEscapePoint *ep; ScmVM *vm = theVM; save_cont(vm); ep = SCM_NEW(ScmEscapePoint); ep->prev = NULL; ep->ehandler = SCM_FALSE; ep->cont = vm->cont; ep->handlers = vm->handlers; ep->cstack = vm->cstack; contproc = Scm_MakeSubr(throw_continuation, ep, 0, 1, SCM_MAKE_STR("continuation")); return Scm_VMApply1(proc, contproc); }
上記によれば、subr として_継続_を作ってそれを引数として VMCallCC の引数になっている proc を apply しているように見えます。
(call/cc (lambda (c) (set! cont c) 4))
proc に渡されてるのは上記の call/cc な引数として、その中に渡されるべき継続の c をでっち上げてラストで proc に渡している模様。
気が早いですが、休みに掘ってみようかな、と。
ちなみに
MakeSubr とあったので本当かいな、と言いつつ以下な試験。
gosh> (define cont #f) cont gosh> (list 1 2 3 (call/cc (lambda (c) (set! cont c) 4)) 5 6) (1 2 3 4 5 6) gosh> cont #<subr continuation> gosh>
確かに subr な模様。