secd machine 分解

SECD マシンの実行過程を分解して見る。

gosh> (run '((lambda (x) (+ x 3)) 4))
  1. s e (NIL LDC 4 CONS LDF (LDC 3 LD (1 . 1) + RTN) AP . c) d
    c の先頭は NILNILNIL をスタックs に積む。
  2. (NIL . s) e (LDC 4 CONS LDF (LDC 3 LD (1 . 1) + RTN) AP . c) d
    c の先頭は LDCLDC は次の数字をスタックsに積む。
  3. (4 NIL . s) e (CONS LDF (LDC 3 LD (1 . 1) + RTN) AP . c) d
    c の先頭は CONS 。CONS はスタックs の二つの要素を cons してスタックs に積む。ここまでで lambda への引数 (4) ができた。
  4. ((4) . s) e (LDF (LDC 3 LD (1 . 1) + RTN) AP . c) d
    c の先頭はLDF。LDF は関数本体(LDC 3 LD (1 . 1) + RTN) と環境とをペアにしてスタックに積む。
  5. (((LDC 3 LD (1 . 1) + RTN) . e) (4 . NIL) . s) e (AP . c) d
    c の先頭はAP。AP は s から環境とパラメータを取り出し e に移した上で、関数本体を c に設定。さらに dump にこの後の処理を退避。
  6. NIL ((4 . NIL) . e) (LDC 3 LD (1 . 1) + RTN) (s e c . d)
    関数本体を実行。c の先頭は LDC なので次の数字をスタック s に積む。
  7. (3 . NIL) ((4 . NIL) . e) (LD (1 . 1) + RTN) (s e c . d)
    c の先頭はLD 。コンパイル時に分かっている x の具体的な値を環境から取り出す。
  8. (4 3 . NIL) ((4 . NIL) . e) (+ RTN) (s e c . d)
    c の先頭は+。スタックsから二つ要素を取り出し、足して、結果をスタックに積む。
  9. (7 . NIL) ((4 . NIL) . e) (RTN) (s e c . d)
    c の先頭は RTN。スタックの先頭要素はそのまま、のこりは退避していた s, e, c, d を戻す。
  10. (7 . s) e c d
    終了。

追記。secd ((3 NIL) e (CONS . c) d) => ((3) e c d) になるように CONS の定義をいじった。

RAP, DUM

再帰的定義のためのインストラクション。うーん、分からん。Optional とか書いてるし放っておいていてもいいかなぁ。

memo

見比べる。

gosh> (disasm (lambda () (+ (* 3 5) (* 6 8))))
main_code (name=#f, code=0xbad40, size=15, const=3, stack=13):
args: #f
     0 PRE-CALL(2) 6
     2 CONSTI-PUSH(3) 
     3 CONSTI-PUSH(5) 
     4 GREF-CALL(2) #<identifier secd#*>; (* 3 5)
     6 PUSH-PRE-CALL(2) 12
     8 CONSTI-PUSH(6) 
     9 CONSTI-PUSH(8) 
    10 GREF-CALL(2) #<identifier secd#*>; (* 6 8)
    12 PUSH-GREF-TAIL-CALL(2) #<identifier secd#+>; (+ (* 3 5) (* 6 8))
    14 RET 
#<undef>
gosh> (run '(+ (* 3 5) (* 6 8)))
;1. s e (LDC 8 LDC 6 * LDC 5 LDC 3 * + . c) d
;2. (8 . s) e (LDC 6 * LDC 5 LDC 3 * + . c) d
;3. (6 8 . s) e (* LDC 5 LDC 3 * + . c) d
;4. (48 . s) e (LDC 5 LDC 3 * + . c) d
;5. (5 48 . s) e (LDC 3 * + . c) d
;6. (3 5 48 . s) e (* + . c) d
;7. (15 48 . s) e (+ . c) d
;8. (63 . s) e c d
((63 . s) e c d)
#f

分かった、 gauchevm の状態が見えていないのが問題だ。当たり前だ。
vm-dump 。これだろうか。