SICP 読み (372) 5.5 翻訳系

問題 5.50

よく考えたら手続きを定義しただけで中身が手続きとして実行されていない事に気がついた。なるべく一発で済むような形でなんとかなれば良いのですが。
と言いつつ面倒なのでやっぱ一つづつ (を
って、こちら方面は昨晩のソレが盛り込まれていなかった。(とほほ
盛り込み完了。まず self-evaluating なソレから

gosh> (start eceval)

(total-pushes = 1501 maximum-depth = 111)
;;; EC-Eval value:
ok

;;; EC-Eval input:
1

(total-pushes = 0 maximum-depth = 0)
;;; EC-Eval value:
1

;;; EC-Eval input:

次は変数の定義と lookup を

;;; EC-Eval input:
(define x 1)

(total-pushes = 3 maximum-depth = 3)
;;; EC-Eval value:
ok

;;; EC-Eval input:
x

(total-pushes = 0 maximum-depth = 0)
;;; EC-Eval value:
1

;;; EC-Eval input:

足し算とかかけ算とか

(+ x 1)

(total-pushes = 8 maximum-depth = 5)
;;; EC-Eval value:
2

;;; EC-Eval input:
(* x 2)

(total-pushes = 8 maximum-depth = 5)
;;; EC-Eval value:
2

;;; EC-Eval input:

quote してみる

;;; EC-Eval input:
'(1 2 3)

(total-pushes = 0 maximum-depth = 0)
;;; EC-Eval value:
(1 2 3)

;;; EC-Eval input:
(define y '(1 2 3))

(total-pushes = 3 maximum-depth = 3)
;;; EC-Eval value:
ok

;;; EC-Eval input:
y

(total-pushes = 0 maximum-depth = 0)
;;; EC-Eval value:
(1 2 3)

;;; EC-Eval input:

set! してみる

;;; EC-Eval input:
(set! x 2)

(total-pushes = 3 maximum-depth = 3)
;;; EC-Eval value:
ok

;;; EC-Eval input:
x

(total-pushes = 0 maximum-depth = 0)
;;; EC-Eval value:
2

;;; EC-Eval input:

factorial を定義してみるか

;;; EC-Eval input:
(define (factorial n) (if (= n 1) 1 (* (factorial (- n 1)) n)))

(total-pushes = 3 maximum-depth = 3)
;;; EC-Eval value:
ok

;;; EC-Eval input:

そして呼び出す

;;; EC-Eval input:
(factorial 1)

(total-pushes = 16 maximum-depth = 8)
;;; EC-Eval value:
1

;;; EC-Eval input:
(factorial 2)

(total-pushes = 48 maximum-depth = 13)
;;; EC-Eval value:
2

;;; EC-Eval input:
(factorial 3)

(total-pushes = 80 maximum-depth = 18)
;;; EC-Eval value:
6

;;; EC-Eval input:
(factorial 4)

(total-pushes = 112 maximum-depth = 23)
;;; EC-Eval value:
24

;;; EC-Eval input:
(factorial 5)

(total-pushes = 144 maximum-depth = 28)
;;; EC-Eval value:
120

;;; EC-Eval input:

この時点で通過してないのは and、or、not、begin、cond くらいでしょうか。これはしかしよく考えてみると色々試せるな。
てーか、実行させる時点で unbound variable が出てくると思ったらそうでもないな。

コンパイル待ち中

なので set-breakpoint 試してみたいんですがラベル探すのが凄く面倒。とりあえず define-variable が entry315 らしい。これで試してみるか。

gosh> (set-breakpoint eceval 'entry315 1)

ってこれ、gdb みたく next みたいなナニが欲しいなぁ。あるいは eval の先頭で止めりゃいいのかなぁ。
てーか、これは本当に動いているのだろうか ...

gosh> (set-breakpoint eceval 'entry315 1)
((entry315 1))
gosh> (start eceval)

(total-pushes = 1501 maximum-depth = 111)
;;; EC-Eval value:
ok

;;; EC-Eval input:
(define x 1)

(total-pushes = 3 maximum-depth = 3)
;;; EC-Eval value:
ok

;;; EC-Eval input:

駄目ぢゃん。よく見るとコンパイルした scheme の手続きに対人間なインターフェースな手続きが無ひ。コピー元が駄目ッスか。とほほほ。

以下の手続きを末端に追加

(define input-prompt ";;; M-Eval input:")
(define output-prompt ";;; M-Eval value:")

(define (driver-loop)
  (prompt-for-input input-prompt)
  (let ((input (read)))
    (let ((output (eval input the-global-environment)))
      (announce-output output-prompt)
      (user-print output)))
  (driver-loop))

(define (prompt-for-input string)
  (newline) (newline) (display string) (newline))

(define (announce-output string)
  (newline) (display string) (newline))

(define (user-print object)
  (if (compound-procedure? object)
      (display (list 'compound-procedure
                     (procedure-parameters object)
                     (procedure-body object)
                     '<procedure-env>))
      (display object)))

(define the-global-environment (setup-environment))

(driver-loop)

やれやれ。あと以下の手続きを ch5-eceval-support.scm の primitive-procedures に追加

  • newline
  • display
  • read

で M-Eval なプロンプトが出た。

gosh> (start eceval)


;;; M-Eval input:

;;; M-Eval input:
1

;;; M-Eval value:
*** ERROR: Unbound variable pair?
Stack Trace:
_______________________________________
  0  (map (lambda (p) (p)) aprocs)
        At line 499 of "./ch5-regsim.scm"
  1  value-proc

  2  (set-contents! target (value-proc))
        At line 371 of "./ch5-regsim.scm"
  3  (instruction-execution-proc (car insts))
        At line 192 of "./ch5-regsim.scm"
gosh> 

どはー。やっぱアマかった。これはまだまだ先やっさ。