#| A scheme-exp is either: - (make-num= scheme-exp scheme-exp) - (make-kons scheme-exp scheme-exp) - (make-hd scheme-exp) - (make-tl scheme-exp) - (make-null-test scheme-exp) - (make-app symbol scheme-exp) - symbol - (make-kond scheme-exp scheme-exp scheme-exp) - scheme-val A scheme-val is: - boolean - number - (cons scheme-val scheme-val) - '() A scheme-def is: - (make-def symbol symbol scheme-exp) A list-of-scheme-defs is either: - empty - (cons scheme-def list-of-scheme-defs) |# (define-struct num= (lhs rhs)) (define-struct kons (hd tl)) (define-struct hd (arg)) (define-struct tl (arg)) (define-struct null-test (arg)) (define-struct app (rator rand)) (define-struct kond (test thn els)) (define-struct def (name param body)) ;; evaluate : scheme-exp list-of-scheme-defs -> scheme-val (define (evaluate a-se a-losd) (cond [(num=? a-se) (= (evaluate (num=-lhs a-se) a-losd) (evaluate (num=-rhs a-se) a-losd))] [(kons? a-se) (cons (evaluate (kons-hd a-se) a-losd) (evaluate (kons-tl a-se) a-losd))] [(hd? a-se) (car (evaluate (hd-arg a-se) a-losd))] [(tl? a-se) (cdr (evaluate (tl-arg a-se) a-losd))] [(app? a-se) (let ([def (lookup-def (app-rator a-se) a-losd)]) (evaluate (subst (def-param def) (evaluate (app-rand a-se) a-losd) (def-body def)) a-losd))] [(symbol? a-se) (error 'evaluate "free variable")] [(kond? a-se) (if (evaluate (kond-test a-se) a-losd) (evaluate (kond-thn a-se) a-losd) (evaluate (kond-els a-se) a-losd))] [(null-test? a-se) (null? (evaluate (null-test-arg a-se) a-losd))] [else ;; scheme-val a-se])) ;; lookup-def : symbol list-of-scheme-defs -> def ;; finds the def for name in a-losd, or calls error if there isn't one (define (lookup-def name a-losd) (cond [(null? a-losd) (error 'lookup-def "not found: ~a" name)] [else (if (eq? name (def-name (car a-losd))) (car a-losd) (lookup-def name (cdr a-losd)))])) ;; subst : number or cons symbol scheme-exp -> scheme-exp ;; substitutes val for var in body (define (subst var val body) (cond [(num=? body) (make-num= (subst var val (num=-lhs body)) (subst var val (num=-rhs body)))] [(kons? body) (make-kons (subst var val (kons-hd body)) (subst var val (kons-tl body)))] [(hd? body) (make-hd (subst var val (hd-arg body)))] [(tl? body) (make-tl (subst var val (tl-arg body)))] [(app? body) (make-app (app-rator body) (subst var val (app-rand body)))] [(symbol? body) (if (eq? var body) val body)] [(kond? body) (make-kond (subst var val (kond-test body)) (subst var val (kond-thn body)) (subst var val (kond-els body)))] [(null-test? body) (make-null-test (subst var val (null-test-arg body)))] [else ;; scheme-val body])) ;; examples as tests (subst 'x 1 2) 2 (subst 'x 1 'x) 1 (subst 'x 1 'y) 'y (subst 'x 1 #t) #t (subst 'x 1 (make-num= 'x 'y)) (make-num= 1 'y) (subst 'x 1 (make-kons 'x 'y)) (make-kons 1 'y) (subst 'x 1 '()) '() (subst 'x 1 (make-hd 'x)) (make-hd 1) (subst 'x 1 (make-tl 'x)) (make-hd 1) (subst 'x 1 (make-tl 'x)) (make-tl 1) (subst 'x 1 (make-app 'f 'x)) (make-app 'f 1) (subst 'x 1 (make-kond 'x 'y 'z)) (make-kond 1 'y 'z) (subst 'x 1 (make-null-test 'x)) (make-null-test 1) (define defs (cons (make-def 'f 'x (make-kons 1 'x)) (cons (make-def 'g 'x (make-kons 3 (make-tl 'x))) (cons (make-def 'h 'x (make-num= 'x 1)) '())))) (lookup-def 'f defs) (make-def 'f 'x (make-kons 1 'x)) (lookup-def 'g defs) (make-def 'g 'x (make-kons 3 (make-tl 'x))) (evaluate 2 defs) 2 (evaluate (make-num= 1 2) defs) #f (evaluate (make-num= 1 1) defs) #t (evaluate (make-kons 1 '()) defs) (cons 1 '()) (evaluate (make-hd (make-kons 1 '())) defs) 1 (evaluate (make-tl (make-kons 1 '())) defs) '() (evaluate (make-null-test (make-kons 1 '())) defs) #f (evaluate (make-null-test '()) defs) #t (evaluate (make-kond (make-null-test '()) 1 2) defs) 1 (evaluate (make-kond (make-null-test (make-kons 1 '())) 1 2) defs) 2 (evaluate (make-app 'h '1) defs) #t #| (define (contains-five? a-lon) (cond [(null? a-lon) #f] [else (cond [(= (car a-lon) 5) #t] [else (contains-five? (cdr a-lon))])])) (contains-five? '()) (contains-five? (cons 1 '())) (contains-five? (cons 5 '())) (contains-five? (cons 3 (cons 4 (cons 5 (cons 6 (cons 7 '())))))) |# (define contains-five-def (make-def 'contains-five? 'a-lon (make-kond (make-null-test 'a-lon) #f (make-kond (make-num= (make-hd 'a-lon) 5) #t (make-app 'contains-five? (make-tl 'a-lon)))))) (define test1 (make-app 'contains-five? '())) (define test2 (make-app 'contains-five? (make-kons 1 '()))) (define test3 (make-app 'contains-five? (make-kons 5 '()))) (define test4 (make-app 'contains-five? (make-kons 3 (make-kons 4 (make-kons 5 (make-kons 6 (make-kons 7 '()))))))) (evaluate test1 (cons contains-five-def '())) #f (evaluate test2 (cons contains-five-def '())) #f (evaluate test3 (cons contains-five-def '())) #t (evaluate test4 (cons contains-five-def '())) #t