|
2 | 2 | (provide (all-defined-out)) |
3 | 3 | (require (only-in "interp.rkt" prim? value? interp-prim)) |
4 | 4 |
|
| 5 | +;; type LEnv = (Listof Variable) |
| 6 | +;; type VEnv = (Listof Value) |
| 7 | + |
| 8 | +;; Expr -> Answer |
| 9 | +(define (interp e) |
| 10 | + (interp-env (translate e) '())) |
| 11 | + |
5 | 12 | ;; Expr -> IExpr |
6 | 13 | (define (translate e) |
7 | 14 | (translate-e e '())) |
|
17 | 24 | ,(translate-e e1) |
18 | 25 | ,(translate-e e2))] |
19 | 26 | [(? symbol? x) |
20 | | - (lexical-address x r)] |
| 27 | + `(address ,(lexical-address x r))] |
21 | 28 | [`(let ((,x ,e0)) ,e1) |
22 | | - `(let ((_ ,(translate e0 r))) |
23 | | - ,(translate e1 (cons x r)))])) |
| 29 | + `(let ((_ ,(translate-e e0 r))) |
| 30 | + ,(translate-e e1 (cons x r)))])) |
| 31 | + |
| 32 | +;; IExpr VEnv -> Answer |
| 33 | +(define (interp-env e r) |
| 34 | + (match e |
| 35 | + [(? value? v) v] |
| 36 | + [(list (? prim? p) e) |
| 37 | + (let ((a (interp-env e r))) |
| 38 | + (interp-prim p a))] |
| 39 | + [`(if ,e0 ,e1 ,e2) |
| 40 | + (match (interp-env e0 r) |
| 41 | + ['err 'err] |
| 42 | + [v |
| 43 | + (if v |
| 44 | + (interp-env e1 r) |
| 45 | + (interp-env e2 r))])] |
| 46 | + [`(address ,i) |
| 47 | + (list-ref r i)] |
| 48 | + [`(let ((_ ,e0)) ,e1) |
| 49 | + (match (interp-env e0 r) |
| 50 | + ['err 'err] |
| 51 | + [v |
| 52 | + (interp-env e1 (cons v r))])])) |
24 | 53 |
|
25 | 54 | ;; Variable LEnv -> Natural |
26 | 55 | (define (lexical-address x r) |
27 | 56 | (match r |
28 | 57 | ['() (error "unbound variable")] |
29 | 58 | [(cons y r) |
30 | 59 | (match (symbol=? x y) |
31 | | - [#t (length r)] |
32 | | - [#f (lexical-address x r)])])) |
| 60 | + [#t 0] |
| 61 | + [#f (add1 (lexical-address x r))])])) |
| 62 | + |
| 63 | +(module+ test |
| 64 | + (require rackunit) |
| 65 | + (check-equal? (translate '(let ((x 0)) x)) |
| 66 | + '(let ((_ 0)) (address 0))) |
| 67 | + (check-equal? (translate '(let ((x 0)) (let ((y 1)) x))) |
| 68 | + '(let ((_ 0)) (let ((_ 1)) (address 1)))) |
| 69 | + (check-equal? (translate '(let ((x 0)) (let ((y 1)) y))) |
| 70 | + '(let ((_ 0)) (let ((_ 1)) (address 0)))) |
| 71 | + (check-equal? (translate '(let ((x 0)) |
| 72 | + (let ((y x)) |
| 73 | + y))) |
| 74 | + '(let ((_ 0)) (let ((_ (address 0))) (address 0)))) |
| 75 | + |
| 76 | + (check-equal? (interp 5) 5) |
| 77 | + (check-equal? (interp '(let ((x 0)) x)) 0) |
| 78 | + (check-equal? (interp '(let ((x 0)) (let ((y 1)) x))) 0) |
| 79 | + (check-equal? (interp '(let ((x 0)) (let ((y 1)) y))) 1) |
| 80 | + (check-equal? (interp '(let ((x 0)) (let ((y x)) y))) 0)) |
0 commit comments