Toy VM (15) - SECD マシンでの継続
SECD マシンで継続について(わたしが理解したことを)書こう。
トップレベルの扱いが異なっているため、 gauche と同じ結果になっていない。が、とりあえず。
追記。どうもまだバグがある気がしてきた。
;; debug を nil にして実行 SECD> (secd-eval '(let ((save #f)) (write (+ 3 (call/cc (lambda (cc) (set! save cc) 5)))) (write (save 10))) :debug nil) ;; 8 ;; 13 NIL ;; debug を t にして実行 SECD> (secd-eval '(let ((save #f)) (write (+ 3 (call/cc (lambda (cc) (set! save cc) 5)))) (write (save 10))) :debug t) STATE: S = S0 E = E0 C = (:NIL :LDC :SCHEME-F :CONS :LDF (:LDCT (:LDC 3 :+ :WRITE) :LDF (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) :AP :LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) :AP :STOP . C0) D = D0 ;;; 初期状態。「継続」オブジェクトは、コンパイル時に決まっている。(:LDC 3 :+ :WRITE) で、call/cc の呼び出し後に行う処理になっている。 STATE MATCH (S E (NIL . C) D) -> ((NIL . S) E C D) S = S0 E = E0 C = (:LDC :SCHEME-F :CONS :LDF (:LDCT (:LDC 3 :+ :WRITE) :LDF (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) :AP :LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) :AP :STOP . C0) D = D0 STATE: S = (NIL . S0) E = E0 C = (:LDC :SCHEME-F :CONS :LDF (:LDCT (:LDC 3 :+ :WRITE) :LDF (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) :AP :LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) :AP :STOP . C0) D = D0 ;;; STATE MATCH (S E (LDC X . C) D) -> ((X . S) E C D) S = (NIL . S0) E = E0 X = :SCHEME-F C = (:CONS :LDF (:LDCT (:LDC 3 :+ :WRITE) :LDF (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) :AP :LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) :AP :STOP . C0) D = D0 STATE: S = (:SCHEME-F NIL . S0) E = E0 C = (:CONS :LDF (:LDCT (:LDC 3 :+ :WRITE) :LDF (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) :AP :LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) :AP :STOP . C0) D = D0 ;;; STATE MATCH ((B A . S) E (CONS . C) D) -> (((B . A) . S) E C D) B = :SCHEME-F A = NIL S = S0 E = E0 C = (:LDF (:LDCT (:LDC 3 :+ :WRITE) :LDF (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) :AP :LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) :AP :STOP . C0) D = D0 STATE: S = ((:SCHEME-F) . S0) E = E0 C = (:LDF (:LDCT (:LDC 3 :+ :WRITE) :LDF (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) :AP :LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) :AP :STOP . C0) D = D0 ;;; STATE MATCH (S E (LDF c' . C) D) -> (((CLOS c' . E) . S) E C D) S = ((:SCHEME-F) . S0) E = E0 c' = (:LDCT (:LDC 3 :+ :WRITE) :LDF (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) :AP :LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) C = (:AP :STOP . C0) D = D0 STATE: S = ((:CLOS (:LDCT (:LDC 3 :+ :WRITE) :LDF (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) :AP :LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) . E0) (:SCHEME-F) . S0) E = E0 C = (:AP :STOP . C0) D = D0 ;;; STATE MATCH (((CLOS c' . e') V . S) E (AP . C) D) -> (NIL (V . e') c' (S E C . D)) c' = (:LDCT (:LDC 3 :+ :WRITE) :LDF (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) :AP :LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) e' = E0 V = (:SCHEME-F) S = S0 E = E0 C = (:STOP . C0) D = D0 STATE: S = NIL E = ((:SCHEME-F) . E0) C = (:LDCT (:LDC 3 :+ :WRITE) :LDF (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) :AP :LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) ;;; STATE MATCH (S E (LDCT c' . C) D) -> ((((CONT S E c' . D)) . S) E C D) S = NIL E = ((:SCHEME-F) . E0) c' = (:LDC 3 :+ :WRITE) C = (:LDF (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) :AP :LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) STATE: S = (((:CONT NIL ((:SCHEME-F) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0))) E = ((:SCHEME-F) . E0) C = (:LDF (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) :AP :LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) ;;; 継続をスタックに積む。(:CONT s e c' . d) STATE MATCH (S E (LDF c' . C) D) -> (((CLOS c' . E) . S) E C D) S = (((:CONT NIL ((:SCHEME-F) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0))) E = ((:SCHEME-F) . E0) c' = (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) C = (:AP :LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) STATE: S = ((:CLOS (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) . #1=((:SCHEME-F) . E0)) ((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0))) E = ((:SCHEME-F) . E0) C = (:AP :LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) ;;; STATE MATCH (((CLOS c' . e') V . S) E (AP . C) D) -> (NIL (V . e') c' (S E C . D)) c' = (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) e' = ((:SCHEME-F) . E0) V = ((:CONT NIL ((:SCHEME-F) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) S = NIL E = ((:SCHEME-F) . E0) C = (:LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) STATE: S = NIL E = (((:CONT NIL #1=((:SCHEME-F) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . #1#) C = (:LD (1 . 1) :SET (2 . 1) :LDC 5 :RTN) D = (NIL ((:SCHEME-F) . E0) (:LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) S0 E0 (:STOP . C0) . D0) ;;; STATE MATCH (S E (LD (M . N) . C) D) -> ((X . S) E C D) S = NIL E = (((:CONT NIL #1=((:SCHEME-F) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . #1#) M = 1 N = 1 C = (:SET (2 . 1) :LDC 5 :RTN) D = (NIL ((:SCHEME-F) . E0) (:LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) S0 E0 (:STOP . C0) . D0) RHS VAR X = (:CONT NIL ((:SCHEME-F) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0) STATE: S = ((:CONT NIL ((:SCHEME-F) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) E = (((:CONT NIL #1=((:SCHEME-F) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . #1#) C = (:SET (2 . 1) :LDC 5 :RTN) D = (NIL ((:SCHEME-F) . E0) (:LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) S0 E0 (:STOP . C0) . D0) ;;; STATE MATCH ((X . S) E (SET (M . N) . C) D) -> (S e' C D) X = #1=(:CONT NIL ((#1#) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0) S = NIL E = ((#1=(:CONT NIL #2=((#1#) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . #2#) M = 2 N = 1 C = (:LDC 5 :RTN) D = (NIL #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) . #2=(S0 E0 (:STOP . C0) . D0))) . E0) (:LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) . #2#) RHS VAR e' = ((#1=(:CONT NIL #2=((#1#) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . #2#) STATE: S = NIL E = ((#1=(:CONT NIL #2=((#1#) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . #2#) C = (:LDC 5 :RTN) D = (NIL #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) . #2=(S0 E0 (:STOP . C0) . D0))) . E0) (:LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) . #2#) ;;; STATE MATCH (S E (LDC X . C) D) -> ((X . S) E C D) S = NIL E = ((#1=(:CONT NIL #2=((#1#) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . #2#) X = 5 C = (:RTN) D = (NIL #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) . #2=(S0 E0 (:STOP . C0) . D0))) . E0) (:LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) . #2#) STATE: S = (5) E = ((#1=(:CONT NIL #2=((#1#) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . #2#) C = (:RTN) D = (NIL #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) . #2=(S0 E0 (:STOP . C0) . D0))) . E0) (:LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) . #2#) ;;; STATE MATCH ((X . Z) e' (RTN . c') (S E C . D)) -> ((X . S) E C D) X = 5 Z = NIL e' = ((#1=(:CONT NIL #2=((#1#) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . #2#) c' = NIL S = NIL E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) STATE: S = (5) E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:LDC 3 :+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) ;;; STATE MATCH (S E (LDC X . C) D) -> ((X . S) E C D) S = (5) E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) X = 3 C = (:+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) STATE: S = (3 5) E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:+ :WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) ;;; STATE MATCH ((A B . S) E (+ . C) D) -> ((X . S) E C D) A = 3 B = 5 S = NIL E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) RHS VAR X = 8 STATE: S = (8) E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:WRITE :NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) ;; 8 ;;; STATE MATCH ((X . S) E (WRITE . C) D) -> (S E C D) X = 8 S = NIL E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) RHS VAR DUM = NIL STATE: S = NIL E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:NIL :LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) ;;; STATE MATCH (S E (NIL . C) D) -> ((NIL . S) E C D) S = NIL E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) STATE: S = (NIL) E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:LDC 10 :CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) ;;; STATE MATCH (S E (LDC X . C) D) -> ((X . S) E C D) S = (NIL) E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) X = 10 C = (:CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) STATE: S = (10 NIL) E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:CONS :LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) ;;; STATE MATCH ((B A . S) E (CONS . C) D) -> (((B . A) . S) E C D) B = 10 A = NIL S = NIL E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) STATE: S = ((10)) E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:LD (1 . 1) :AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) ;;; STATE MATCH (S E (LD (M . N) . C) D) -> ((X . S) E C D) S = ((10)) E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) M = 1 N = 1 C = (:AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) RHS VAR X = #1=(:CONT NIL ((#1#) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0) STATE: S = (#1=(:CONT NIL ((#1#) . E0) (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0) (10)) E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:AP :WRITE :RTN) D = (S0 E0 (:STOP . C0) . D0) ;;; STATE MATCH (((CONT S E C . D) (V) . s') e' (AP . c') d') -> ((V . S) E C D) S = NIL E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:LDC 3 :+ :WRITE) D = (S0 E0 (:STOP . C0) . D0) V = 10 s' = NIL e' = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) c' = (:WRITE :RTN) d' = (S0 E0 (:STOP . C0) . D0) STATE: S = (10) E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:LDC 3 :+ :WRITE) D = (S0 E0 (:STOP . C0) . D0) ;;; STATE MATCH (S E (LDC X . C) D) -> ((X . S) E C D) S = (10) E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) X = 3 C = (:+ :WRITE) D = (S0 E0 (:STOP . C0) . D0) STATE: S = (3 10) E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:+ :WRITE) D = (S0 E0 (:STOP . C0) . D0) ;;; STATE MATCH ((A B . S) E (+ . C) D) -> ((X . S) E C D) A = 3 B = 10 S = NIL E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:WRITE) D = (S0 E0 (:STOP . C0) . D0) RHS VAR X = 13 STATE: S = (13) E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = (:WRITE) D = (S0 E0 (:STOP . C0) . D0) ;; 13 ;;; STATE MATCH ((X . S) E (WRITE . C) D) -> (S E C D) X = 13 S = NIL E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = NIL D = (S0 E0 (:STOP . C0) . D0) RHS VAR DUM = NIL STATE: S = NIL E = #1=(((:CONT NIL #1# (:LDC 3 :+ :WRITE) S0 E0 (:STOP . C0) . D0)) . E0) C = NIL D = (S0 E0 (:STOP . C0) . D0) NIL