Skip to content

Commit cca48f0

Browse files
committed
SICP (Manual) concrete evaluator arithmetic OK
1 parent 84b7343 commit cca48f0

File tree

2 files changed

+61
-13
lines changed

2 files changed

+61
-13
lines changed

references/sicp/instructors-manual/concrete-test.rkt

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,22 @@
44
"concrete.rkt")
55

66
(check-false (ASSQ 'x '()) "Empty bindings")
7-
(check-equal? (ASSQ 'x '([x 8])) '(x 8) "First binding")
8-
(check-equal? (ASSQ 'x '([y 7] [x 8])) '(x 8) "Older binding")
9-
(check-equal? (ASSQ 'z '([x 8])) #f "No binding")
7+
(check-equal? (ASSQ 'x '([x . 8])) '(x . 8) "First binding")
8+
(check-equal? (ASSQ 'x '([y . 7] [x . 8])) '(x . 8) "Older binding")
9+
(check-equal? (ASSQ 'z '([x . 8])) #f "No binding")
1010

11+
(check-equal? (MAKE-FRAME '(a) '(1)) '([a . 1]) "Smalest frame")
12+
(check-equal? (EXTEND-ENVIRONMENT '(a b) '(1 2) '()) '(([a . 1] [b . 2])))
13+
(check-equal? (EXTEND-ENVIRONMENT '() '() '()) '(()) )
1114

1215
(check-exn (regexp "Unbound variable 'x") (lambda ()
13-
(LOOKUP-VARIABLE-VALUE 'x '())) "Wrong error")
16+
(LOOKUP-VARIABLE-VALUE 'x '())))
1417
; WIP:
15-
; (check-equal? (LOOKUP-VARIABLE-VALUE 'x '([x 8])) 8)
18+
(check-equal? (LOOKUP-VARIABLE-VALUE 'x '(([x . 8]))) 8)
19+
20+
(check-equal? (MAKE-FRAME '(a) '(1)) '([a . 1]) "Smalest frame")
21+
22+
(check-equal? (EVAL 1 '()) 1)
23+
(check-equal? (EVAL 'x (EXTEND-ENVIRONMENT '(x) '(8) '())) 8)
24+
(check-equal? (EVAL '(+ 3 4) (MAKE-BUILTINS)) 7)
25+
(check-equal? (EVAL '(+ (* 3 4) (* 5 6)) (MAKE-BUILTINS)) 42)

references/sicp/instructors-manual/concrete.rkt

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,57 @@
99
; Function names changed to ALL-CAPS to avoid potential
1010
; confusion with functions provided by Racket.
1111

12+
(define (EVAL exp environ)
13+
;; dispatch on expression type
14+
(cond [(number? exp) exp] ; self-evaluating
15+
[(symbol? exp)
16+
(LOOKUP-VARIABLE-VALUE exp environ)]
17+
[else
18+
(apply (EVAL (car exp) environ) ; operator
19+
(LIST-OF-VALUES (cdr exp) ; operands
20+
environ))]))
21+
22+
23+
(define (LIST-OF-VALUES exps environ)
24+
(if (null? exps)
25+
'()
26+
(cons (EVAL (car exps) environ)
27+
(LIST-OF-VALUES (cdr exps) environ))))
28+
29+
(define (EXTEND-ENVIRONMENT vars values base-environ)
30+
(cons (MAKE-FRAME vars values) base-environ))
31+
32+
(define (MAKE-FRAME vars values)
33+
(cond [(and (null? vars) (null? values)) '()]
34+
[(null? vars) (error "Too many arguments" values)]
35+
[(null? values) (error "Too few arguments" vars)]
36+
[else
37+
(cons (cons (car vars) (car values)) ; make binding
38+
(MAKE-FRAME (cdr vars) (cdr values)))]))
39+
40+
(define (LOOKUP-VARIABLE-VALUE var environ)
41+
(if (null? environ)
42+
(error "Unbound variable" var)
43+
(let ([binding (ASSQ var (car environ))]) ; look in first frame
44+
(if (eq? binding #f)
45+
(LOOKUP-VARIABLE-VALUE var (cdr environ))
46+
(cdr binding)))))
47+
1248
(define (ASSQ var bindings)
1349
(cond [(null? bindings) #f]
1450
[(eq? var (caar bindings)) (car bindings)]
1551
[else (ASSQ var (cdr bindings))]))
1652

17-
(define (LOOKUP-VARIABLE-VALUE var env)
18-
(if (null? env)
19-
(error "Unbound variable" var)
20-
(let ([binding (ASSQ var (car env))])
21-
(if (eq? binding #f)
22-
(LOOKUP-VARIABLE-VALUE var (cdr env))
23-
(cdr binding)))))
53+
(define (MAKE-BUILTINS)
54+
(EXTEND-ENVIRONMENT
55+
'(+ - * /)
56+
(list + - * /)
57+
'()))
2458

2559
; Needed to support rackunit tests in concrete-test.rkt.
2660
(provide ASSQ
27-
LOOKUP-VARIABLE-VALUE)
61+
LOOKUP-VARIABLE-VALUE
62+
EXTEND-ENVIRONMENT
63+
MAKE-FRAME
64+
EVAL
65+
MAKE-BUILTINS)

0 commit comments

Comments
 (0)