call/cc - Scheme VM を書く

call/cc を実装。
ヒープベース VM とはちと違う。

  • conti で stack を丸ごと保存
  • nuate で stack を戻す
  • return で戻した stack から復帰

という流れ。

Scheme 版では以下のようなテストが通るようになった。

  (test* "call/cc" 4 (evaluate '(call/cc (lambda (c) (c 4)))))
  (test* "call/cc" 3
                   (evaluate
                    '((lambda (cont)
                        (if (call/cc (lambda (c) (set! cont c)))
                            (cont #f)
                            3)) '())))
  (test* "call/cc jump" 102
                        (evaluate
                         '((lambda (cont)
                             (if (call/cc (lambda (c) (set! cont c)))
                                 ((lambda ()
                                    ((lambda ()
                                       (cont #f)
                                       ))
                                    ))
                                 102)) '())))

C++ 版でもやることは同じ。
スタックマシンは native スタックではなくヒープに確保した仮想スタックを使うので bottom/top を知るのはとても簡単。
保存も復帰も楽。
Scheme で書く -> C++ に移植はロジックのバグはほぼ Scheme 側で解決されているので開発効率が良いな。