EoPL 読んでた記録の確認とその記録 (8)
Ex.2.8 です。ちょっとカン違いしてたのですが、以下は #t なんですね。
> (occurs-bound? 'x '(lambda (y) y))
occurs-bound? は以下なカンジ。
(define occurs-bound? (lambda (var exp) (cases lexical-address exp (lit-exp (datum) #f) (lex-info (id depth position) #t) (free-info (id) #f) (if-exp (test-exp true-exp false-exp) (or (occurs-bound? var test-exp) (occurs-bound? var true-exp) (occurs-bound? var false-exp))) (lambda-exp (id body) (or (occurs-bound? var body) (and (eqv? var id) (occurs-free? var body)))) (app-exp (rator rand) (or (occurs-bound? var rator) (occurs-bound? var rand))))))
む
以下な試験にパスしてるんだけど良いのだろうか。とりあえずこれでヨシとして free-vars および bound-vars を云々してみます。
test-occurs-bound.scm
(add-load-path ".") (load "occurs-bound") (load "parse-expression") (test-start "occurs-bound") (test-section "occurs-bound") (test* "not bound" #f (occurs-bound? 'x (parse-expression 5))) (test* "not bound (2)" #f (occurs-bound? 'x (parse-expression 'x))) (test* "not bound (2)" #f (occurs-bound? 'x (parse-expression 'y))) (test* "not bound (3)" #f (occurs-bound? 'x (parse-expression '(lambda (y) x)))) (test* "not bound (3)" #f (occurs-bound? 'x (parse-expression '(if (null? x) 1 2)))) (test* "not bound (3)" #f (occurs-bound? 'x (parse-expression '(if (null? y) x 2)))) (test* "not bound (3)" #f (occurs-bound? 'x (parse-expression '(if (null? y) 1 x)))) (test* "lambda exp (occurs-bound)" #t (occurs-bound? 'x (parse-expression '(lambda (x) x)))) (test* "lambda exp (not-bound)" #f (occurs-bound? 'x (parse-expression '(lambda (x) y)))) (test* "lambda exp (occurs-bound)" #t (occurs-bound? 'x (parse-expression '(lambda (y) y)))) (test* "app exp (occurs-bound)" #t (occurs-bound? 'x (parse-expression '((lambda (x) x) y)))) (test* "app exp" #t (occurs-bound? 'x (parse-expression '((lambda (y) y) x)))) (test* "app exp (not-bound)" #f (occurs-bound? 'x (parse-expression '((lambda (x) y) y)))) (test-end)
test-occurs-free.scm
(use gauche.test) (add-load-path ".") (load "occurs-free") (load "parse-expression") (test-start "occurs-free") (test-section "occurs-free") (test* "literal" #t (occurs-free? 'x (parse-expression 5))) (test* "variable" #t (occurs-free? 'x (parse-expression 'x))) (test* "variable" #t (occurs-free? 'x (parse-expression 'y))) (test* "if exp" #t (occurs-free? 'x (parse-expression '(if (null? x) 1 2)))) (test* "if exp (2)" #t (occurs-free? 'x (parse-expression '(if (null? y) x 2)))) (test* "if exp (3)" #t (occurs-free? 'x (parse-expression '(if (null? y) 1 x)))) (test* "lambda exp" #f (occurs-free? 'x (parse-expression '(lambda (x) x)))) (test* "lambda exp" #t (occurs-free? 'x (parse-expression '(lambda (x) y)))) (test* "lambda exp" #t (occurs-free? 'x (parse-expression '(lambda (y) x)))) (test* "app exp" #t (occurs-free? 'x (parse-expression '((lambda (x) x) y)))) (test* "app exp" #t (occurs-free? 'x (parse-expression '((lambda (y) y) x)))) (test* "app exp (not-bound)" #t (occurs-free? 'x (parse-expression '((lambda (x) y) y)))) (test-end)
なんとなく実装てきに微妙感満点なのですがorz
とりあえずここでエントリ投入します。追記はできないと思われます。