SICP 読み (376) 5.5 翻訳系
ぬ。よく見りゃ primitive-procedures の中身にいちいち cadr 付けるんじゃなくって primitive-implementation 手続きを直せば良い、とゆー事に以下の下書きある程度書いた時点で気がついた。わはは。
こんな感じ??
(define (primitive-implementation proc) (cadadr l))
なんか自分ながらにアホすぎて情無い。パニクってると手抜きを忘れてしまうな。
問題 5.50
一応問題なく動作している模様ですが、自分てきに微妙な部分を整理。まず、評価器の起動は以下のようにしています。
(add-load-path ".") (load "load-eceval-compiler") (load "ch5-compiler") (load "objectCode.txt") (define true #t) (define false #f) (set! the-global-environment (setup-environment)) (set-register-contents! eceval 'val (assemble objectCode eceval)) (set-register-contents! eceval 'flag true) ;; 必要であれば breakpoint 設定したり trace-on したり (start eceval)
compile.scm
上記で load している objcectCode.txt ですが、以下の手続きを評価して戻ってくるナニをリダイレクトしてファイルに吐き出した物
(add-load-path ".") (load "load-eceval-compiler") (load "ch5-compiler") (define true #t) (define false #f) (let f ((l (statements (compile '(begin (define apply-in-underlying-scheme apply) (define (map f l) (if (null? l) '() (cons (f (car l)) (map f (cdr l))))) ;; 以下、4.1.2 のソース ) 'val 'return)))) (cond ((not (null? l)) (display (car l)) (display " ") (display "\n") (f (cdr l)))))
今よくよく見てみると上記の手続きは微妙だなぁ (多分リダイレクトしたいから display を使ったんだろうな)。で、上記で吐き出された objectCode.txt を以下のように修正
(define objectCode '( ;; 出力された手続き ))
この objectCode が assemble されて val レジスタに set! された挙句に eceval の external-entry から行ってらっしゃい、になっている模様 (flag も true が設定)
external-entry (perform (op initialize-stack)) (assign env (op get-global-environment)) (assign continue (label print-result)) (goto (reg val))
ちなみに objectCode.txt を手直しする時に
(assign val (const Unknown procedure type -- APPLY))
とか
(assign val (const ;;; M-Eval input:))
とかってなってる部分も修正の必要あり。手直しってあたりが微妙ですが。本当は ch5-compiler.scm あたりに手を入れて自動でやんないと駄目ってのは分かってるんですが。
以降も日本語微妙ですが自分用にマトメ投入予定ですがどうなるか。
compile.scm 追加
setup-environment 手続きが戻す環境を作るために使われる primitive-procedures に束縛されるリストの要素は
(手続きの名前 手続きオブジェクト)
の形となっているが、手続きオブジェクトの解決にはこのレイヤの下の層で動作している eceval が持つ環境が使われる。例えば以下のような形
'(primitive #<subr car>)
になるのでこのまま setup-envronment するとこの環境の中の primitive-procedure-objects の要素はこのような形になる。
'(primitive (primitive #<subr car>))
このまま持つのであれば primitive-implementation 手続きで要素の cadr の cadr を戻すように修正しておけば良いし、環境のサイズ的に微妙という場合には先に cadr して手続きオブジェクトのみをそれぞれの要素に格納しておけば良い (これは昨日なエントリで使った手法か)。
ch5-compiler.scm
ここでは scheme な命令列を regsim が理解できる命令列 (アセンブラ) に変換 (翻訳) するための手続きが一式定義されている。上記の objectCode はこの中で定義されている compile 手続きによって変換されたもの。
ch5-eceval-compiler.scm
テキストでは_積極制御評価器 [eceval]_と名前が付けられている scheme のシミュレータが定義される。これは scheme の中で動く仮想計算機 [regsim] の中で動作している。又、この仮想計算機の動作を開始させる手続きも定義されている。
ch5-eceval-support.scm
compile.scm で定義されている評価器の op な手続きはここで定義される環境から lookup される。この中にはコンパイルされる手続きのために定義されている手続きや eceval が呼び出す手続きの定義が混在している。
ch5-regsim.scm
仮想レジスタ計算機な手続きが定義。assemble という名前の (これも翻訳??) 手続きもあり、この手続きを通さないと仮想レジスタ計算機なアセンブラで書いた手続きを仮想レジスタ計算機が実行する事はできない。
ch5-syntax.scm
これは ch5-eceval-compiler.scm で用意されている評価器のための手続き定義かな。ch5-compiler.scm も使っているかも。
蛇足
さくっとイメージできない部分がまだ微妙にあるなあ ...
追記
まだ primitive な手続きが足らないらしい。
;;; M-Eval input: (let ((a 1) (b 2)) (+ a b)) *** ERROR: Unbound variable append Stack Trace:
てーか、何故に設定した breakpoint で止まらないか、というのも検証してみたい。
追記 (2008/2/22)
なんかナチュラルぶちかましてました。
(define (primitive-implementation proc) (cadadr l))
ではなくて
(define (primitive-implementation proc) (cadadr proc))
じゃんか。とほほほ。