|
1 | 1 | #lang racket
|
2 | 2 | (provide (all-defined-out))
|
3 | 3 |
|
4 |
| -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
5 |
| -;;;;;; The grammar of our AST |
6 |
| -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
7 |
| - |
8 |
| -;; type Expr = |
9 |
| -;; | Integer |
10 |
| -;; | Boolean |
11 |
| -;; | Character |
12 |
| -;; | Variable |
13 |
| -;; | String |
14 |
| -;; | Prim1 Expr |
15 |
| -;; | Prim2 Expr Expr |
16 |
| -;; | If Expr Expr Expr |
17 |
| -;; | cond (Clause list) Expr |
18 |
| -;; | Let (Binding list) Expr |
19 |
| -;; | Nil |
20 |
| - |
21 |
| -;; type Prim1 = |
22 |
| -;; | 'add1 | 'sub1 | 'zero? | box | unbox | car | cdr |
23 |
| -;; | 'integer? | 'boolean? | 'char? | 'integer->char | 'char->integer |
24 |
| - |
25 |
| -;; type Prim2 = '+ | '- | cons |
26 |
| - |
27 |
| -;; type Binding = Variable Expr |
28 |
| - |
29 |
| -;; type Variable = Symbol (except 'add1 'sub1 'if, etc.) |
30 |
| - |
31 |
| -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
32 |
| -;;;;;; The AST data structure |
33 |
| -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
34 |
| - |
35 |
| -;; The AST can be viewed as having 'kinds' of nodes. |
36 |
| -;; |
37 |
| -;; * The nodes that represnt an expression themselves |
38 |
| -;; |
39 |
| -;; * The nodes that are part of an expression, but no an expression themselves |
40 |
| - |
41 |
| -;; The below are the former: |
42 |
| - |
43 |
| -(struct int-e (i) #:transparent) |
44 |
| -(struct bool-e (b) #:transparent) |
45 |
| -(struct char-e (c) #:transparent) |
46 |
| -(struct string-e (s) #:transparent) |
47 |
| -(struct var-e (v) #:transparent) |
48 |
| -(struct prim-e (p es) #:transparent) |
49 |
| -(struct if-e (e t f) #:transparent) |
50 |
| -(struct cond-e (cs el) #:transparent) |
51 |
| -(struct let-e (bs b) #:transparent) |
52 |
| -(struct nil-e () #:transparent) |
53 |
| - |
54 |
| -;; The next two are the latter: |
55 |
| - |
56 |
| -;; a clause now takes an _arbitrary_ expression and a body. |
57 |
| -;; This is different than assignment 3! If you want to understand |
58 |
| -;; why, look at the lecture notes for Dupe. |
59 |
| -(struct clause (e body) #:transparent) |
60 |
| - |
61 |
| -;; A binding holds a symbol representing the bound variable and |
62 |
| -;; Expr that represents the value that will be bound to that variable |
63 |
| -(struct binding (v e) #:transparent) |
64 |
| - |
65 |
| -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
66 |
| -;;;;;; AST utility functions (predicates) |
67 |
| -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
68 |
| - |
69 |
| -;; Any -> Boolean |
70 |
| -;; Is x a unary primitive? |
71 |
| -(define (prim1? x) |
72 |
| - (and (symbol? x) |
73 |
| - (memq x '(add1 sub1 abs - integer->char char->integer |
74 |
| - car cdr length box? string? cons? empty? |
75 |
| - box unbox string-length |
76 |
| - char? integer? boolean? zero?)))) |
77 |
| - |
78 |
| -;; Any -> Boolean |
79 |
| -;; Is x a binary primitive? |
80 |
| -(define (prim2? x) |
81 |
| - (and (symbol? x) |
82 |
| - (memq x '(+ cons string-ref make-string char=? |
83 |
| - = <= < char=? boolean=? -)))) |
84 |
| - |
85 |
| -(define (prim? x) |
86 |
| - (or (prim1? x) |
87 |
| - (prim2? x))) |
88 |
| - |
89 |
| -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
90 |
| -;;;;;; AST utility functions (getters) |
91 |
| -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
92 |
| - |
93 |
| -;; Expr -> Value |
94 |
| -(define (get-val v) |
95 |
| - (match v |
96 |
| - [(int-e x) x] |
97 |
| - [(bool-e x) x] |
98 |
| - [(char-e x) x] |
99 |
| - [(string-e x) x] |
100 |
| - [(nil-e) '()])) |
101 |
| - |
102 |
| -;; It will sometimes be useful to get the list of all the variables that are |
103 |
| -;; introduced by a `let` |
104 |
| -;; [Binding] -> [Symbol] |
105 |
| -(define (get-vars bs) |
106 |
| - (match bs |
107 |
| - ['() '()] |
108 |
| - [(cons (binding v _) bs) (cons v (get-vars bs))])) |
109 |
| - |
110 |
| -;; Get all of the _definitions_ from a list of bindings |
111 |
| -;; [Binding] -> [Expr] |
112 |
| -(define (get-defs bs) |
113 |
| - (match bs |
114 |
| - ['() '()] |
115 |
| - [(cons (binding _ def) bs) (cons def (get-defs bs))])) |
116 |
| - |
117 |
| -;; Get all of the predicate expressions from a list of clauses |
118 |
| -;; [Clause] -> [Expr] |
119 |
| -(define (get-preds cs) |
120 |
| - (match cs |
121 |
| - ['() '()] |
122 |
| - [(cons (clause p _) cs) (cons p (get-preds cs))])) |
123 |
| - |
124 |
| -;; Get all of the bodies expressions from a list of clauses |
125 |
| -;; [Clause] -> [Expr] |
126 |
| -(define (get-bods cs) |
127 |
| - (match cs |
128 |
| - ['() '()] |
129 |
| - [(cons (clause _ b) cs) (cons b (get-preds cs))])) |
130 |
| - |
131 |
| - |
132 |
| -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
133 |
| -;;;;;; AST utility functions (printers) |
134 |
| -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
135 |
| - |
136 |
| -;; We have switched to using `#:transparent` above, so this should only be |
137 |
| -;; necessary if you're desperate when debugging :'( |
138 |
| - |
139 |
| -;; Given an AST, construct an sexpr that has the same shape |
140 |
| -(define (ast-debug a) |
141 |
| - (match a |
142 |
| - [(int-e i) `(int-e ,i)] |
143 |
| - [(bool-e b) `(bool-e ,b)] |
144 |
| - [(char-e b) `(char-e ,b)] |
145 |
| - [(string-e s) `(string-e ,s)] |
146 |
| - [(var-e v) `(var-e ,v)] |
147 |
| - [(nil-e) ''()] |
148 |
| - [(prim-e p es) `(prim-e ,p ,@(map ast-debug es))] |
149 |
| - [(if-e e t f) `(if-e ,(ast-debug e) |
150 |
| - ,(ast-debug t) |
151 |
| - ,(ast-debug f))] |
152 |
| - [(cond-e cs f) `(cond-e ,(clauses-debug cs) ,(ast-debug f))] |
153 |
| - [(let-e bs b) `(let-e ,(binding-debug bs) ,(ast-debug b))])) |
154 |
| - |
155 |
| -(define (binding-debug bnds) |
156 |
| - (match bnds |
157 |
| - ['() '()] |
158 |
| - [(cons (binding v e) bnds) `((,v ,(ast-debug e)) ,@(binding-debug bnds))])) |
159 |
| - |
160 |
| -(define (clauses-debug cs) |
161 |
| - (match cs |
162 |
| - ['() '()] |
163 |
| - [(cons (clause e b) cs) `((,(ast-debug e) ,(ast-debug b)) ,@(clauses-debug cs))])) |
| 4 | +;; type Expr = (Eof) |
| 5 | +;; | (Empty) |
| 6 | +;; | (Int Integer) |
| 7 | +;; | (Bool Boolean) |
| 8 | +;; | (Char Character) |
| 9 | +;; | (String String) |
| 10 | +;; | (Prim0 Op0) |
| 11 | +;; | (Prim1 Op1 Expr) |
| 12 | +;; | (Prim2 Op2 Expr Expr) |
| 13 | +;; | (If Expr Expr Expr) |
| 14 | +;; | (Begin Expr Expr) |
| 15 | +;; | (Let Id Expr Expr) |
| 16 | +;; | (Var Id) |
| 17 | +;; type Id = Symbol |
| 18 | +;; type Op0 = 'read-byte |
| 19 | +;; type Op1 = 'add1 | 'sub1 | 'zero? |
| 20 | +;; | 'char? | 'integer->char | 'char->integer |
| 21 | +;; | 'string? | 'string-length |
| 22 | +;; | 'write-byte | 'eof-object? |
| 23 | +;; | 'box | 'car | 'cdr | 'unbox |
| 24 | +;; | 'empty? |
| 25 | +;; | 'box? | 'cons? | |
| 26 | +;; type Op2 = '+ | '- | 'eq? |
| 27 | +;; | 'string-ref | 'make-string |
| 28 | +;; | 'cons |
| 29 | +;; | '= | '< | '<= | 'char=? | 'boolean=? |
| 30 | +(struct Eof () #:prefab) |
| 31 | +(struct Empty () #:prefab) |
| 32 | +(struct Int (i) #:prefab) |
| 33 | +(struct Bool (b) #:prefab) |
| 34 | +(struct Char (c) #:prefab) |
| 35 | +;; Added in HUSTLE+ |
| 36 | +(struct String (s) #:prefab) |
| 37 | +(struct Prim0 (p) #:prefab) |
| 38 | +(struct Prim1 (p e) #:prefab) |
| 39 | +(struct Prim2 (p e1 e2) #:prefab) |
| 40 | +(struct If (e1 e2 e3) #:prefab) |
| 41 | +(struct Begin (e1 e2) #:prefab) |
| 42 | +(struct Let (x e1 e2) #:prefab) |
| 43 | +(struct Var (x) #:prefab) |
0 commit comments