forked from IUCompilerCourse/Essentials-of-Compilation
-
Notifications
You must be signed in to change notification settings - Fork 0
/
s-expr-example.rkt
146 lines (127 loc) · 2.92 KB
/
s-expr-example.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#lang racket
(require racket/match)
(require racket/fixnum)
(define assert
(lambda (msg b)
(if (not b)
(begin
(display "ERROR: ")
(display msg)
(newline))
(void))))
(define ast1.4 `(- 8))
(define ast1.1 `(+ 50 ,ast1.4))
(match ast1.1
[`(,op ,child1 ,child2)
(print op) (newline)
(print child1) (newline)
(print child2)])
(define (arith-kind arith)
(match arith
[(? fixnum?) `int]
[`(- ,c1) `neg]
[`(+ ,c1 ,c2) `add]))
(arith-kind `50)
(arith-kind `(- 8))
(arith-kind `(+ 50 (- 8)))
(define (arith? sexp)
(match sexp
[(? fixnum?) #t]
[`(+ ,e1 ,e2)
(and (arith? e1) (arith? e2))]
[`(- ,e) (arith? e)]
[else #f]))
(arith? `(+ 50 (- 8)))
(arith? `(- 50 (+ 8)))
(define (interp-R0 e)
(match e
[(? fixnum?) e]
[`(read)
(let ([r (read)])
(cond [(fixnum? r) r]
[else (error 'interp-R0 "input was not an integer" r)]))]
[`(- ,(app interp-R0 v))
(fx- 0 v)]
[`(+ ,(app interp-R0 v1) ,(app interp-R0 v2))
(fx+ v1 v2)]
))
(interp-R0 ast1.1)
;(interp-R0 `(+ (read) (- 8)))
(define (pe-neg r)
(match r
[(? fixnum?) (fx- 0 r)]
[else `(- ,r)]
))
(define (pe-add r1 r2)
(match (list r1 r2)
[`(,n1 ,n2)
#:when (and (fixnum? n1) (fixnum? n2))
(fx+ r1 r2)]
[else
`(+ ,r1 ,r2)]
))
(define (pe-arith e)
(match e
[(? fixnum?) e]
[`(read)
`(read)]
[`(- ,e1)
(pe-neg (pe-arith e1))]
[`(+ ,e1 ,e2)
(pe-add (pe-arith e1) (pe-arith e2))]
))
;; e ::= (read) | (- (read)) | (+ e e)
;; r ::= n | (+ n e) | e
(define (pe-neg2 r)
(match r
[(? fixnum?) (fx- 0 r)]
[`(+ ,n ,e2)
#:when (fixnum? n)
`(+ ,(fx- 0 n) ,(pe-neg2 e2))]
[`(read) `(- (read))]
[`(- ,e2) e2]
[`(+ ,e1 ,e2)
`(+ ,(pe-neg2 e1) ,(pe-neg2 e2))]
))
(define (pe-add2 r1 r2)
(match r1
[(? fixnum?)
(match r2
[(? fixnum?) (fx+ r1 r2)]
[`(+ ,n2 ,e2) #:when (fixnum? n2)
`(+ ,(fx+ r1 n2) ,e2)]
[else `(+ ,r1 ,r2)])]
[`(+ ,n1 ,e1)
(match r2
[(? fixnum?) `(+ (fx+ n1 r2) ,e1)]
[`(+ ,n2 ,e2) #:when (fixnum? n2)
`(+ ,(fx+ n1 n2) (+ ,e1 ,e2))]
[else `(+ ,r1 ,r2)])]
[else
(match r2
[(? fixnum?) `(+ ,r2 ,r1)]
[else `(+ ,r1 ,r2)])]
))
(define (pe-arith2 e)
(match e
[(? fixnum?) e]
[`(read)
`(read)]
[`(- ,e1)
(pe-neg2 (pe-arith2 e1))]
[`(+ ,e1 ,e2)
(pe-add2 (pe-arith2 e1) (pe-arith2 e2))]
))
(define (test-pe pe p)
(assert "testing pe-arith" (equal? (interp-R0 p)
(interp-R0 (pe p)))))
(if #f
(begin
(test-pe pe-arith `(+ (read) (- (+ 5 3))))
(test-pe pe-arith `(+ 1 (+ (read) 1)))
(test-pe pe-arith `(- (+ (read) (- 5))))
(test-pe pe-arith2 `(+ (read) (- (+ 5 3))))
(test-pe pe-arith2 `(+ 1 (+ (read) 1)))
(test-pe pe-arith2 `(- (+ (read) (- 5))))
)
(void))