EoPL 読んでた記録の確認とその記録 (3)

留守番しつつ Exercise 1.31 リトライ。とりあえず以下をでっちあげてみた。

(define lexical-address
  (lambda (l)
    (let inner ((l l) (dict '()))
      (cond
       ((null? l) '())
       ((symbol? l) l)
       ((eqv? (car l) 'lambda)
	(list (car l) (cadr l) (inner (caddr l) (cons (caadr l) dict))))
       ((eqv? (car l) 'if)
	(list (car l) (inner (cadr l) dict) (inner (cddr l) dict)))
       (else
	(cons (inner (car l) dict) (inner  (cdr l) dict)))))))

とりあえず試験書きます。
以下のみ、ってことで。

(use gauche.test)

(add-load-path ".")
(load "lexical-address")

(test-start "lexical-address")
(test-section "lexical-address")
(test* "example"
       '(lambda (a b c)
	  (if ((eqv? free) (b : 0 1) (c : 0 2))
	      ((lambda (c)
		 ((cons free) (a : 1 0) (c : 0 0)))
	       (a : 0 0))
	      (b : 0 1)))
       (lexical-address '(lambda (a b c)
			   (if ((eqv? free) (b : 0 1) (c : 0 2))
			       ((lambda (c)
				  ((cons free) (a : 1 0) (c : 0 0)))
				(a : 0 0))
			       (b : 0 1)))))
		 

(test-end)

で、呼び出しかかる前にパス。実装が以下。

(define get-position
  (lambda (sym l)
    (let inner ((sym sym) (l l) (p 0))
      (cond
       ((null? l) #f)
       ((eqv? sym (car l)) p)
       (else
	(inner sym (cdr l) (+ 1 p)))))))

(define get-lexical-address
  (lambda (symbol dict)
    (let inner ((symbol symbol) (dict dict) (d 0) (p 0))
      (if (null? dict)
	  (list symbol 'free)
	  (let ((pos (get-position symbol (car dict))))
	    (if (eqv? pos #f)
		(inner symbol (cdr dict) (+ 1 d) 0)
		(list symbol ': d pos)))))))

(define lexical-address
  (lambda (l)
    (let inner ((l l) (dict '()))
      (cond
       ((null? l) '())
       ((symbol? l) (get-lexical-address l dict))
       ((eqv? (car l) 'lambda)
	(list (car l) (cadr l) (inner (caddr l) (cons (cadr l) dict))))
       ((eqv? (car l) 'if)
	(cons (car l) (cons (inner (cadr l) dict) (inner (cddr l) dict))))
       (else
	(cons (inner (car l) dict) (inner  (cdr l) dict)))))))

if の部分を

(list (car l) (inner (cadr l) dict) (inner cddr l) dict)

とヤッててハマってました。これで元に戻れます。