SICP 読み (330) 5.5 翻訳系

三連休だがしかし自習。色々あってどこにも行けず。

問題 5.37

基本的に instruction-sequence の中にある needed だの modified だのというソレは preserving の為にあるはずなんで

(define (preserving regs seq1 seq2)
  (if (null? regs)
      (append-instruction-sequences seq1 seq2)
      (let ((first-reg (car regs)))
;;        (if (and (needs-register? seq2 first-reg)
;;                 (modifies-register? seq1 first-reg))
            (preserving (cdr regs)
             (make-instruction-sequence
              (list-union (list first-reg)
                          (registers-needed seq1))
              (list-difference (registers-modified seq1)
                               (list first-reg))
              (append `((save ,first-reg))
                      (statements seq1)
                      `((restore ,first-reg))))
             seq2)
;;            (preserving (cdr regs) seq1 seq2)))))
	      )))

みたいな乱暴なコトしても良いのでしょうが、もう少しお行儀良く直してみるか。

(define (preserving regs seq1 seq2)
  (if (null? regs)
      (append-instruction-sequences seq1 seq2)
      (let ((first-reg (car regs))
	    (needed (registers-needed seq1))
	    (modified (registers-modified seq1)))
        (cond ((and (needs-register? seq2 first-reg)
		    (modifies-register? seq1 first-reg))
	       (list-union (list first-reg) needed)
	       (list-difference modified (list first-reg))))
	(preserving (cdr regs)
		    (make-instruction-sequence
		     needed
		     modified
		     (append `((save ,first-reg))
			     (statements seq1)
			     `((restore ,first-reg))))
		    seq2))))

微妙。この方が良さげ。

(define (preserving regs seq1 seq2)
  (if (null? regs)
      (append-instruction-sequences seq1 seq2)
      (let ((first-reg (car regs))
	    (add-reg '()))
	(if (and (needs-register? seq2 first-reg)
		 (modifies-register? seq1 first-reg))
	    (append add-reg (list first-reg)))
	(let ((needed (list-union add-reg
				  (registers-needed seq1)))
	      (modified (list-difference (registers-modified seq1)
					 add-reg)))
	  (preserving (cdr regs)
		      (make-instruction-sequence
		       needed
		       modified
		       (append `((save ,first-reg))
			       (statements seq1)
			       `((restore ,first-reg))))
		      seq2)))))

これも微妙かなぁ。ぶっちゃけどれでも良いのでしょうが、試験してみる_単純な式_って微妙だなぁ。とりあえず preserving を呼び出している手続きを列挙してみると

  • end-with-linkage
  • compile-assignment
  • compile-definition
  • compile-if
  • compile-sequence
  • compile-application
    • construct-arglist
    • code-to-get-rest-args

って end-with-linkage は色々なソレが呼び出しているな。

  • self-evaluating
  • quoted
  • variable
  • assignment
  • definition
  • lambda
  • apply

ですか。ってコトは

(compile 1 'val 'return)

なんかでも save/restore してしまうのか。これはどうなんだろう。ちなみにデフォルトの評価器だと以下の statement が出てきた。

((assign val (const 1))
 (goto (reg continue)))

これ、assign の上下に save/restore が付くのか。試験してみたら付いてます。ちなみに使っている preserving は一番上のソレです。これは凄くウザいな。で

(compile '(define a 1) 'val 'return)

してみたら、出るわ出るわ。

((save continue) 
 (save env) 
 (save continue) 
 (assign val (const 1)) 
 (restore continue) 
 (restore env) 
 (perform (op define-variable!) (const a) (reg val) (reg env)) 
 (assign val (const ok)) 
 (restore continue) 
 (goto (reg continue))))

冗長。ちなみにデフォルト評価器では以下

((assign val (const 1)) 
 (perform (op define-variable!) (const a) (reg val) (reg env)) 
 (assign val (const ok)) 
 (goto (reg continue))))

当たり前ですが save/restore はゼロ。上記の define のケースだと

  • 最初に get-value-code にセットする compile (variable の end-with-linkage) で continue の save/restore が追加
  • get-value-code と perform-assign が env で preserving されるので env の save/restore が追加
  • 最後に end-with-linkage されて continue の save/restore が追加

という事になっているワケですか。