https://github.com/akkartik/mu/blob/main/shell/macroexpand.mu
1 fn macroexpand expr-ah: (addr handle cell), globals: (addr global-table), trace: (addr trace) {
2 +-- 11 lines: # trace "macroexpand " expr-ah --------------------------------------------------------------------------------------------------------------------------------------------
13
14 {
15 var expanded?/eax: boolean <- macroexpand-iter expr-ah, globals, trace
16 compare expanded?, 0/false
17 loop-if-!=
18 }
19 +-- 11 lines: # trace "=> " expr-ah -----------------------------------------------------------------------------------------------------------------------------------------------------
30 }
31
32
33 fn macroexpand-iter _expr-ah: (addr handle cell), globals: (addr global-table), trace: (addr trace) -> _/eax: boolean {
34 var expr-ah/esi: (addr handle cell) <- copy _expr-ah
35 +-- 11 lines: # trace "macroexpand-iter " expr ------------------------------------------------------------------------------------------------------------------------------------------
46
47 var expr/eax: (addr cell) <- lookup *expr-ah
48 {
49 var nil?/eax: boolean <- nil? expr
50 compare nil?, 0/false
51 break-if-=
52
53 trace-text trace, "mac", "nil"
54 trace-higher trace
55 return 0/false
56 }
57 {
58 var expr-type/eax: (addr int) <- get expr, type
59 compare *expr-type, 0/pair
60 break-if-=
61
62 trace-text trace, "mac", "non-pair"
63 trace-higher trace
64 return 0/false
65 }
66
67 var first-ah/ebx: (addr handle cell) <- get expr, left
68 var rest-ah/ecx: (addr handle cell) <- get expr, right
69 var first/eax: (addr cell) <- lookup *first-ah
70 {
71 var litfn?/eax: boolean <- litfn? first
72 compare litfn?, 0/false
73 break-if-=
74
75 trace-text trace, "mac", "literal function"
76 trace-higher trace
77 return 0/false
78 }
79 {
80 var litmac?/eax: boolean <- litmac? first
81 compare litmac?, 0/false
82 break-if-=
83
84 trace-text trace, "mac", "literal macro"
85 trace-higher trace
86 return 0/false
87 }
88 var result/edi: boolean <- copy 0/false
89
90 $macroexpand-iter:anonymous-function: {
91 var fn?/eax: boolean <- fn? first
92 compare fn?, 0/false
93 break-if-=
94
95 trace-text trace, "mac", "anonymous function"
96
97 var rest/eax: (addr cell) <- lookup *rest-ah
98 {
99 rest-ah <- get rest, right
100 rest <- lookup *rest-ah
101 {
102 var done?/eax: boolean <- nil? rest
103 compare done?, 0/false
104 }
105 break-if-!=
106 var curr-ah/eax: (addr handle cell) <- get rest, left
107 var macro-found?/eax: boolean <- macroexpand-iter curr-ah, globals, trace
108 result <- or macro-found?
109 loop
110 }
111 trace-higher trace
112 return result
113 }
114
115 $macroexpand-iter:quote: {
116
117 var quote?/eax: boolean <- symbol-equal? first, "'"
118 compare quote?, 0/false
119 break-if-=
120
121 trace-text trace, "mac", "quote"
122 trace-higher trace
123 return 0/false
124 }
125 $macroexpand-iter:backquote: {
126
127 var backquote?/eax: boolean <- symbol-equal? first, "`"
128 compare backquote?, 0/false
129 break-if-=
130
131 error trace, "nested backquote not supported yet"
132 trace-higher trace
133 return 0/false
134 }
135 $macroexpand-iter:def: {
136
137 var def?/eax: boolean <- symbol-equal? first, "def"
138 compare def?, 0/false
139 break-if-=
140
141 trace-text trace, "mac", "def"
142 var rest/eax: (addr cell) <- lookup *rest-ah
143 rest-ah <- get rest, right
144 rest <- lookup *rest-ah
145 var val-ah/edx: (addr handle cell) <- get rest, left
146 var macro-found?/eax: boolean <- macroexpand-iter val-ah, globals, trace
147 trace-higher trace
148 return macro-found?
149 }
150 $macroexpand-iter:set: {
151
152 var set?/eax: boolean <- symbol-equal? first, "set"
153 compare set?, 0/false
154 break-if-=
155
156 trace-text trace, "mac", "set"
157 var rest/eax: (addr cell) <- lookup *rest-ah
158 rest-ah <- get rest, right
159 rest <- lookup *rest-ah
160 var val-ah/edx: (addr handle cell) <- get rest, left
161 var macro-found?/eax: boolean <- macroexpand-iter val-ah, globals, trace
162 trace-higher trace
163 return macro-found?
164 }
165
166
167
168
169
170 {
171 var definition-h: (handle cell)
172 var definition-ah/edx: (addr handle cell) <- address definition-h
173 maybe-lookup-symbol-in-globals first, definition-ah, globals, trace
174 var definition/eax: (addr cell) <- lookup *definition-ah
175 compare definition, 0
176 break-if-=
177
178 {
179 var definition-type/eax: (addr int) <- get definition, type
180 compare *definition-type, 0/pair
181 }
182 break-if-!=
183
184 {
185 var definition-car-ah/eax: (addr handle cell) <- get definition, left
186 var definition-car/eax: (addr cell) <- lookup *definition-car-ah
187 var macro?/eax: boolean <- litmac? definition-car
188 compare macro?, 0/false
189 }
190 break-if-=
191
192 var macro-definition-ah/eax: (addr handle cell) <- get definition, right
193
194
195 apply macro-definition-ah, rest-ah, expr-ah, globals, trace, 0/no-screen, 0/no-keyboard, 0/call-number
196 return 1/true
197 }
198
199 trace-text trace, "mac", "recursing into function definition"
200 var curr-ah/ebx: (addr handle cell) <- copy first-ah
201 $macroexpand-iter:loop: {
202
203
204 var macro-found?/eax: boolean <- macroexpand-iter curr-ah, globals, trace
205 result <- or macro-found?
206 var rest/eax: (addr cell) <- lookup *rest-ah
207 {
208 var nil?/eax: boolean <- nil? rest
209 compare nil?, 0/false
210 }
211 break-if-!=
212 curr-ah <- get rest, left
213 rest-ah <- get rest, right
214 loop
215 }
216 return result
217 }
218
219 fn test-macroexpand {
220 var globals-storage: global-table
221 var globals/edx: (addr global-table) <- address globals-storage
222 initialize-globals globals
223
224 var sandbox-storage: sandbox
225 var sandbox/esi: (addr sandbox) <- address sandbox-storage
226 initialize-sandbox-with sandbox, "(def m (litmac litfn () (a b) `(+ ,a ,b)))"
227 edit-sandbox sandbox, 0x13/ctrl-s, globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
228 var trace-ah/eax: (addr handle trace) <- get sandbox, trace
229 var trace/eax: (addr trace) <- lookup *trace-ah
230
231 initialize-sandbox-with sandbox, "(m 3 4)"
232 var gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
233 var gap/eax: (addr gap-buffer) <- lookup *gap-ah
234 var result-h: (handle cell)
235 var result-ah/ebx: (addr handle cell) <- address result-h
236 read-cell gap, result-ah, 0/no-trace
237 var dummy/eax: boolean <- macroexpand-iter result-ah, globals, 0/no-trace
238
239 var _result/eax: (addr cell) <- lookup *result-ah
240 var result/edi: (addr cell) <- copy _result
241
242 initialize-sandbox-with sandbox, "(+ 3 4)"
243 var expected-gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
244 var expected-gap/eax: (addr gap-buffer) <- lookup *expected-gap-ah
245 var expected-h: (handle cell)
246 var expected-ah/ecx: (addr handle cell) <- address expected-h
247 read-cell expected-gap, expected-ah, 0/no-trace
248
249 var expected/eax: (addr cell) <- lookup *expected-ah
250
251 var assertion/eax: boolean <- cell-isomorphic? result, expected, 0/no-trace
252 check assertion, "F - test-macroexpand"
253 }
254
255 fn test-macroexpand-inside-anonymous-fn {
256 var globals-storage: global-table
257 var globals/edx: (addr global-table) <- address globals-storage
258 initialize-globals globals
259
260 var sandbox-storage: sandbox
261 var sandbox/esi: (addr sandbox) <- address sandbox-storage
262 initialize-sandbox-with sandbox, "(def m (litmac litfn () (a b) `(+ ,a ,b)))"
263 edit-sandbox sandbox, 0x13/ctrl-s, globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
264 var trace-ah/eax: (addr handle trace) <- get sandbox, trace
265 var trace/eax: (addr trace) <- lookup *trace-ah
266
267 initialize-sandbox-with sandbox, "(fn() (m 3 4))"
268 var gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
269 var gap/eax: (addr gap-buffer) <- lookup *gap-ah
270 var result-h: (handle cell)
271 var result-ah/ebx: (addr handle cell) <- address result-h
272 read-cell gap, result-ah, 0/no-trace
273 var dummy/eax: boolean <- macroexpand-iter result-ah, globals, 0/no-trace
274
275 var _result/eax: (addr cell) <- lookup *result-ah
276 var result/edi: (addr cell) <- copy _result
277
278 initialize-sandbox-with sandbox, "(fn() (+ 3 4))"
279 var expected-gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
280 var expected-gap/eax: (addr gap-buffer) <- lookup *expected-gap-ah
281 var expected-h: (handle cell)
282 var expected-ah/ecx: (addr handle cell) <- address expected-h
283 read-cell expected-gap, expected-ah, 0/no-trace
284
285 var expected/eax: (addr cell) <- lookup *expected-ah
286
287 var assertion/eax: boolean <- cell-isomorphic? result, expected, 0/no-trace
288 check assertion, "F - test-macroexpand-inside-anonymous-fn"
289 }
290
291 fn test-macroexpand-inside-fn-call {
292 var globals-storage: global-table
293 var globals/edx: (addr global-table) <- address globals-storage
294 initialize-globals globals
295
296 var sandbox-storage: sandbox
297 var sandbox/esi: (addr sandbox) <- address sandbox-storage
298 initialize-sandbox-with sandbox, "(def m (litmac litfn () (a b) `(+ ,a ,b)))"
299 edit-sandbox sandbox, 0x13/ctrl-s, globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
300
301 initialize-sandbox-with sandbox, "((fn() (m 3 4)))"
302 var gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
303 var gap/eax: (addr gap-buffer) <- lookup *gap-ah
304 var result-h: (handle cell)
305 var result-ah/ebx: (addr handle cell) <- address result-h
306 read-cell gap, result-ah, 0/no-trace
307 var dummy/eax: boolean <- macroexpand-iter result-ah, globals, 0/no-trace
308
309 var _result/eax: (addr cell) <- lookup *result-ah
310 var result/edi: (addr cell) <- copy _result
311
312 initialize-sandbox-with sandbox, "((fn() (+ 3 4)))"
313 var expected-gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
314 var expected-gap/eax: (addr gap-buffer) <- lookup *expected-gap-ah
315 var expected-h: (handle cell)
316 var expected-ah/ecx: (addr handle cell) <- address expected-h
317 read-cell expected-gap, expected-ah, 0/no-trace
318
319 var expected/eax: (addr cell) <- lookup *expected-ah
320
321 var assertion/eax: boolean <- cell-isomorphic? result, expected, 0/no-trace
322 check assertion, "F - test-macroexpand-inside-fn-call"
323 }
324
325 fn pending-test-macroexpand-inside-backquote-unquote {
326 var globals-storage: global-table
327 var globals/edx: (addr global-table) <- address globals-storage
328 initialize-globals globals
329
330 var sandbox-storage: sandbox
331 var sandbox/esi: (addr sandbox) <- address sandbox-storage
332 initialize-sandbox-with sandbox, "(def m (litmac litfn () (a b) `(+ ,a ,b)))"
333 edit-sandbox sandbox, 0x13/ctrl-s, globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
334
335 initialize-sandbox-with sandbox, "`(print [result is ] ,(m 3 4)))"
336 var gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
337 var gap/eax: (addr gap-buffer) <- lookup *gap-ah
338 var result-h: (handle cell)
339 var result-ah/ebx: (addr handle cell) <- address result-h
340 read-cell gap, result-ah, 0/no-trace
341 var dummy/eax: boolean <- macroexpand-iter result-ah, globals, 0/no-trace
342 dump-cell-from-cursor-over-full-screen result-ah
343 var _result/eax: (addr cell) <- lookup *result-ah
344 var result/edi: (addr cell) <- copy _result
345
346 initialize-sandbox-with sandbox, "`(print [result is ] ,(+ 3 4)))"
347 var expected-gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
348 var expected-gap/eax: (addr gap-buffer) <- lookup *expected-gap-ah
349 var expected-h: (handle cell)
350 var expected-ah/ecx: (addr handle cell) <- address expected-h
351 read-cell expected-gap, expected-ah, 0/no-trace
352 dump-cell-from-cursor-over-full-screen expected-ah
353 var expected/eax: (addr cell) <- lookup *expected-ah
354
355 var assertion/eax: boolean <- cell-isomorphic? result, expected, 0/no-trace
356 check assertion, "F - test-macroexpand-inside-backquote-unquote"
357 }
358
359 fn pending-test-macroexpand-inside-nested-backquote-unquote {
360 var globals-storage: global-table
361 var globals/edx: (addr global-table) <- address globals-storage
362 initialize-globals globals
363
364 var sandbox-storage: sandbox
365 var sandbox/esi: (addr sandbox) <- address sandbox-storage
366 initialize-sandbox-with sandbox, "(def m (litmac litfn () (a b) `(+ ,a ,b)))"
367 edit-sandbox sandbox, 0x13/ctrl-s, globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
368
369 initialize-sandbox-with sandbox, "`(a ,(m 3 4) `(b ,(m 3 4) ,,(m 3 4)))"
370 var gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
371 var gap/eax: (addr gap-buffer) <- lookup *gap-ah
372 var result-h: (handle cell)
373 var result-ah/ebx: (addr handle cell) <- address result-h
374 read-cell gap, result-ah, 0/no-trace
375 var dummy/eax: boolean <- macroexpand-iter result-ah, globals, 0/no-trace
376 dump-cell-from-cursor-over-full-screen result-ah
377 var _result/eax: (addr cell) <- lookup *result-ah
378 var result/edi: (addr cell) <- copy _result
379
380 initialize-sandbox-with sandbox, "`(a ,(+ 3 4) `(b ,(m 3 4) ,,(+ 3 4)))"
381 var expected-gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
382 var expected-gap/eax: (addr gap-buffer) <- lookup *expected-gap-ah
383 var expected-h: (handle cell)
384 var expected-ah/ecx: (addr handle cell) <- address expected-h
385 read-cell expected-gap, expected-ah, 0/no-trace
386 dump-cell-from-cursor-over-full-screen expected-ah
387 var expected/eax: (addr cell) <- lookup *expected-ah
388
389 var assertion/eax: boolean <- cell-isomorphic? result, expected, 0/no-trace
390 check assertion, "F - test-macroexpand-inside-nested-backquote-unquote"
391 }
392
393