SICP 読み (337) 5.5 翻訳系

問題 5.39

残りをヤッツケてみる事に。ええと

  • *unassigned* ならエラー
  • lexical-address-set! の実装

ですか。とりあえず試験を書こう。微妙に忘れてたりして9.22 gauche.test - 単体テストを見つつ。
で、でっち上げたのが以下

(use gauche.test)

(add-load-path ".")
(load "5.39.scm")

(test-start "5.39")

(test-section "lookup")
(let ((env (extend-environment 
	    '(y z) 
	    '(1 2)
	    (extend-environment
	     '(a b c d e)
	     '(3 4 5 6 7)
	     (extend-environment
	      '(x y)
	      '(8 9)
	      '())))))
  (test* "x is 8 (2 0)" 8 (lexical-address-lookup '(2 0) env))
  (test* "y is 1 (0 0)" 1 (lexical-address-lookup '(0 0) env))
  (test* "c is 5 (1 2)" 5 (lexical-address-lookup '(1 2) env)))

(test-section "set!")
(let ((env (extend-environment 
	    '(y z) 
	    '(1 2)
	    (extend-environment
	     '(a b c d e)
	     '(3 4 5 6 7)
	     (extend-environment
	      '(x y)
	      '(8 9)
	      '())))))
  (lexical-address-set! '(2 0) 10 env)
  (test* "x is 10 (2 0)" 10 (lexical-address-lookup '(2 0) env))
  (lexical-address-set! '(0 0) 20 env)
  (test* "x is 20 (0 0)" 20 (lexical-address-lookup '(0 0) env))
  (lexical-address-set! '(1 2) 30 env)
  (test* "x is 30 (1 2)" 30 (lexical-address-lookup '(1 2) env)))

(test-section "*unassigned*")
(let ((env (extend-environment '(x y) '(*unassigned 0) '())))
  (test* "(0 0) is *unassigned*" *test-error* (lambda ()
						(lexical-address-lookup
						 '(0 0) env)))
  (test* "(0 1) is 0" 0 (lexical-address-lookup '(0 1) env)))

(test-end)

うーむ。とりあえず以下の手続きを書いて

(load "load-eceval-compiler")
(load "ch5-compiler")
(define true #t)
(define false #f)

(define (lexical-address-lookup add env)
  (let ((result (list-ref (cdr (list-ref env (car add))) (cadr add))))
    (if (eq? '*unassigned* result)
	(error "variable is unassigned -- " result)
	result)))

(define (lexical-address-set! add val env)
  (define (scan n l)
    (if (= n 0)
	(set-car! l val)
	(scan (- n 1) (cdr l))))
  (scan (cadr add) (cdr (list-ref env (car add)))))

試験してみたんですがパスしない。

$ make
Testing 5.39 ...                                                 failed.
discrepancies found.  Errors are:
test (0 0) is *unassigned*: expects #<error> => got #<closure (#f #f)>
$

何故だ、と言いつつリファレンス見てみたら

  • 試験な手続きが手動な thunk だったら test
  • test* は試験する手続きを thunk にしてくれる

という記述あり。*unassigned* な試験は正しくは以下な模様。

(test-section "*unassigned*")
(let ((env (extend-environment '(x y) (list '*unassigned* 0) '())))
  (test* "(0 0) is *unassigned*" *test-error* (lexical-address-lookup
					       '(0 0) env))
  (test* "(0 1) is 0" 0 (lexical-address-lookup '(0 1) env)))

この後天性記憶不全の進行具合はレベル的にどうなのでしょうか。(誰

追記

ちなみに上記の試験はバグ入り。修正したのを書くの忘れてました。不具合があった試験は

(let ((env (extend-environment '(x y) '(*unassigned 0) '())))

ってなってました。「*unassigned」です。これも直上の試験に修正する時に盛り込んでおります。