Gauche
Gauche copied to clipboard
Fix reset/shift and eval combination problem v2
<<本件は、急いでマージする必用はありません。>>
#848 を更新したものです。
現状の HEAD に移植しました。
本件は、以下の問題を修正したものです。
(use gauche.partcont)
(reset (eval '(shift k (k 42)) (current-module)))
;; ==> #<undef> ( 42 になるのが正しい )
(use gauche.partcont)
(define k1 #f)
(reset (guard (e (else e))
(shift k (set! k1 k))
(raise "raised")))
(k1)
;; ==> *** ERROR: attempt to return from a ghost continuation. ( "raised" になるのが正しい )
どちらも、部分継続の終端マーカーのセットと、 Scm_VMDynamicWind() の継続フレーム追加との 競合によるものであり、 reset 実行時に継続フレームを一段追加することで対策しています。
ただ、今見ると、 vm.c の「Fix memory leak of the empty partial continuation.」のところが、 若干あやしいような気もします。
<補足情報> この改造をしないで回避したい場合、 以下のように reset と eval/guard の間に何か命令をはさむとうまくいくことがあります。 ただ、ループにするとメモリリークするので、この方向で一般化はできないようです。
(use gauche.partcont)
(reset (values (eval '(shift k (k 42)) (current-module))))
;; ==> 42
(use gauche.partcont)
(define k1 #f)
(reset (values (guard (e (else e))
(shift k (set! k1 k))
(raise "raised"))))
(k1)
;; ==> "raised"
<テスト結果>
(1) Gauche-effects の effects.scm で、
*use-native-reset*
を #t にして、各サンプルを実行 ==> OK
(2) 以下のメモリリークのテスト ==> OK (出典 : http://okmij.org/ftp/continuations/against-callcc.html#memory-leak ) (これは (use gauche.partcont-meta) だとメモリリークします)
(use gauche.partcont)
(define (leak-test1 identity-thunk)
(let loop ((id (lambda (x) x)))
(loop (id (identity-thunk)))))
(leak-test1 (lambda () (reset (shift k k))))
(3) Kahua の nqueen を実行 ==> OK
(4) https://practical-scheme.net/wiliki/wiliki.cgi?Gauche%3ABugs#H-2dgngv の pcdemo10.scm を実行 ==> OK