-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlec5_f1wae.rkt
96 lines (73 loc) · 2.63 KB
/
lec5_f1wae.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#lang plai
(define-type F1WAE
[num (n number?)]
[add (l F1WAE?) (r F1WAE?)]
[sub (l F1WAE?) (r F1WAE?)]
[with (name symbol?) (value F1WAE?) (body F1WAE?)]
[id (name symbol?)]
[app (fname symbol?) (arg F1WAE?)])
(define-type FunDef
[fundef (fname symbol?) (argname symbol?) (fbody F1WAE?)])
; sexp -> FunDef
(define (parse-f sexp)
(match sexp
[(list 'deffun (list fname argname) body) (fundef fname argname (parse body))]))
; sexp -> F1WAE
(define (parse sexp)
(match sexp
[(? number?) (num sexp)]
[(list '+ l r) (add (parse l) (parse r))]
[(list '- l r) (sub (parse l) (parse r))]
[(list 'with (list x i) b) (with x (parse i) (parse b))]
[(? symbol?) (id sexp)]
[(list f a) (app f (parse a))]
[else (error 'parse "bad syntax")]))
; F1WAE list-of-fundef -> number
(define (interp f1wae fds)
(type-case F1WAE f1wae
[num (n) n]
[add (l r) (+ (interp l fds) (interp r fds))]
[sub (l r) (- (interp l fds) (interp r fds))]
[with (x i b) (interp (subst b x (interp i fds)) fds)]
[id (x) (error 'interp "free variable ~a" x)]
[app (f a)
(local [(define target-f (lookup f fds))]
(interp (subst (fundef-fbody target-f) (fundef-argname target-f) (interp a fds))
fds))]))
; F1WAE symbol number -> WAE
(define (subst body name value)
(type-case F1WAE body
[num (n) body]
[add (l r) (add (subst l name value) (subst r name value))]
[sub (l r) (sub (subst l name value) (subst r name value))]
[with (x i b) (with x
(subst i name value)
(if (symbol=? x name)
b
(subst b name value)))]
[id (x) (if (symbol=? x name) (num value) body)]
[app (f a) (app f (subst a name value))]))
; symbol list-of-fundefs -> fundef
(define (lookup f fds)
(cond
[(empty? fds) (error 'lookup "no function exist")]
[else (if (symbol=? f (fundef-fname (first fds)))
(first fds)
(lookup f (rest fds)))]))
(define (run sexp1 fds)
(interp (parse sexp1) fds))
(define functions
(list
(parse-f '{deffun {twice x} {+ x x}})
(parse-f '{deffun {plus5 x} {+ x 5}})
(parse-f '{deffun {x y} y})
(parse-f '{deffun {+ x} x})
(parse-f '{deffun {f f} f})
(parse-f '{deffun {scopetest x} {+ y x}})))
(run '{+ 3 {- 6 5}} functions)
(run '{with {x {+ {with {x 9} x} 2}} {with {x 4} {+ x 2}}} functions)
(run '{- {with {x 10} {twice x}} {plus5 2}} functions)
(run '{with {x 5} {x 7}} functions)
(run '{+ 3} functions)
(run '{f 5} functions)
(run '{with {y 2} {scopetest 10}} functions)