SICP 読み (309) 5.5 翻訳系

年末進行をガン無視でトレイスが続いております。(何

つづき

get-value-code がどんな式になるか、が分からんと compile-definition が何を戻すか、は分からんな。get-value-code にセットされるのは

(compile '(lambda (n) (if (= n 1) 1 (* (factorial (- n 1)) n))) 'val 'next)

が戻すナニ。これは compile-lambda に引数がそのまんま渡されます。で、end-with-linkage で戻される以下のリスト

((env) (val) ((assign val
		      (op make-compiles-procedure)
		      (label entry6)
		      (reg env))
	      (goto (label after-lambda7))))

と compile-lambda-body の戻りが tack-on-(略 に渡された後に after-lambda なラベルと append-instruction される予定。

compile-lambda-body

ここでは以下の式

((env proc argl) (env)
 (entry6
  (assign env (op compiled-procedure-env) (reg proc))
  (assign env
	  (op extend-environment)
	  (const (n))
	  (reg argl)
	  (reg env))))

が compile-sequence が戻すリストと append-instruction される。compile-sequence に渡されるのはこのケースだと以下のようになる模様。

(compile-sequence '((if (= n 1) 1 (* (factorial (- n 1)) n))) 'val 'return)

compile-sequence

ここではいきなり last-exp になるはずなんで if なリストが compile に渡されます。以下の形か。

(compile '(if (= n 1) 1 (* (factorial (- n 1)) n)) 'val 'return)

compile-sequence は上記の手続きが戻すリストを戻す形になる模様。

compile-if

そろそろ何か出てきてくれ。ってか else なブロックに再帰呼び出しがあるなぁ。ええと今回の例では、準備なソレとして t-branch には true-branch9 が、f-branch には false-branch10 が、after-if には after-if10 がセットされるはず。
あるいは consequent-linkage には return がセットな模様。
で、まず式を組み立てる前に predicate、consequent、alternative の順で compile されていく模様。まず条件式からいくと

(compile (= n 1) 'val 'next)

が p-code にセット予定。ここあたりから読めてない部分に突入か。きちんとトレイスしてみようかな。最初に proc-code と operand-codes に式がセットされるんですが、proc-code には

(compile = 'proc 'next)

な戻りがソレ。compile-variable が起動。end-with-linkage は以下な形で呼び出され

(end-with-linkage 'next '((env) (proc)
			  ((assign proc
				   (op lookup-variable-value)
				   (const =)
				   (reg env)))))

end-with-linkage では以下を戻す

(preserving '(continue)
	    '((env) (proc)
	      ((assign proc
		       (op lookup-variable-value)
		       (const =)
		       (reg env))))
	    '(() () ()))

これを受け取った preserving が何をするか、というと以下。

  • 渡されたレジスタのリストの一つ一つの要素について
  • 式2 はそのレジスタを必要としているか
  • かつ、式1 はそのレジスタを modify しているか

もし上記の条件が真であれば式1 をそのレジスタの save/restore で囲んで以降の要素について preserving する形か。偽であればレジスタのリストを cdr して繰り返し、という形で save/restore をナニしているのか。
という事は上記のソレは単純に seq1 と seq2 を append-instruction という事になるな。

(append-instruction-sequences  '((env) (proc)
				 ((assign proc
					  (op lookup-variable-value)
					  (const =)
					  (reg env))))
			       '(() () ()))

append-inst(略 は不思議な作りになっている。二つ以上の instruction-sequence に対応していると見て良いのかな。で、上記の呼び出しは結局のトコロ

(append-2-sequences '((env) (proc)
		      ((assign proc
			       (op lookup-variable-value)
			       (const =)
			       (reg env))))
		    '(() () ()))

となる模様。結局のトコロ

'((env) (proc)
  ((assign proc
	   (op lookup-variable-value)
	   (const =)
	   (reg env))))

が戻るんですが、append-2-sequences な手続きの中身が微妙に興味深いので、もう少し見てみます。ちなみに上記のリストが p-code にセットされていると見て良いのかな。

append-2-sequences

make-instruction-sequence に渡す_必要となるレジスタ_には seq1 で必要となるレジスタと (seq2 で必要となるレジスタと seq1 で modify されるレジスタの差集合) の和集合となっている模様。差集合って書いてしまったんですが、seq2 で必要であっても seq1 で modify されてたら候補にならず、という事ですか。これはどーゆー意味かというと、_必要となるレジスタ_として列挙されるものについて重複を除去していると見て良いのでしょうか。list-union も和と言いつつ重複分は除去な形になっているはず。
あるいは_modify されるレジスタ_についても同様に重複なレジスタが除去された形で和集合になっている、と見て良いのでしょうか。
あとは命令列は単純に append されている模様。とは言え、そろそろ掃除にとりかからねばならないらしいので追記は別途。次は consequent なブロックからになりますか。

うーん

append2-sequences の中の make-instruction に渡す最初の引数について微妙なマトメを書いてみたのだけれど、なんとなくオチてない。(オチの問題??
これは実際のソレが出てこないと分からんかなぁ。本当はトレイスする前にイメージできてないと駄目だと思うんですが ... (弱
再度単純にマトメてみると (registers-needed seq2) から (registers-modified seq1) な要素を取り除いて (registers-needed seq1) との和 (ただし重複は除く) を渡している、という書き方で良いのかなぁ。
どうも needed なイメージがまだ微妙。一回全部見回してからの方が良さげ。

しまった

よく見りゃまだ (= n 1) の演算子を lookup しただけだった。続きは operand-codes をナニして以降です。備忘録まで。(とほほ