#|
Your task is to extend the interpreter below with `cond'
and the implement the function `contains-five?' in your
interpreter:
(define (contains-five? a-lon)
(cond
[(null? a-lon) #f]
[else (cond
[(= (car a-lon) 5) #t]
[else (contains-five? (cdr a-lon))])]))
and test it with these function calls (already translated below).
(contains-five? '())
(contains-five? (cons 1 '()))
(contains-five? (cons 5 '()))
(contains-five? (cons 3 (cons 4 (cons 5 (cons 6 (cons 7 '()))))))
Be sure to read over the entire assignment and think about
the organization and that data that the program uses
before trying to modify the program.
NB: if you use set!, you are either doing it wrong or
making it more complicated than you have to.
Step 1: add boolean values to scheme-val and add tests for
booleans to the evaluate test suite
Step 2: add conditional expressions to scheme-exp. You
may assume that cond expressions always have
two clauses and always have an `else' clause
as the question in the second clause.
NOTE: use `kond' instead of `cond' in your
define-struct (to avoid collisions with
built in names)
Step 3: make some examples of cond expressions and
add tests to the evaluator test suite and
the subst test suite.
Step 4: extend the evaluate and subst functions to
handle cond expressions.
Step 5: translate the contains-five definition above
to a scheme-def.
Step 6: test your scheme-def and your evaluator by
using the example calls to contains-five?
shown above (already translated below).
|#
#|
DATA DEFINITIONS
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
- scheme-val
A scheme-val is:
- 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 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")]
[(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)]
[(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-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-app 'h '1) defs)
#t
(define cf-test1 (make-app 'contains-five? '()))
(define cf-test2 (make-app 'contains-five? (make-kons 1 '())))
(define cf-test3 (make-app 'contains-five? (make-kons 5 '())))
(define cf-test4 (make-app 'contains-five? (make-kons 3 (make-kons 4 (make-kons 5 (make-kons 6 (make-kons 7 '())))))))