https://github.com/akkartik/mu/blob/main/shell/evaluate.mu
1
2
3
4
5 fn evaluate _in: (addr handle cell), out: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell), call-number: int {
6
7 check-stack
8 {
9 var screen-cell/eax: (addr handle cell) <- copy screen-cell
10 compare screen-cell, 0
11 break-if-=
12 var screen-cell-addr/eax: (addr cell) <- lookup *screen-cell
13 compare screen-cell-addr, 0
14 break-if-=
15
16 show-stack-state
17 }
18
19 {
20 compare trace, 0
21 break-if-=
22 var error?/eax: boolean <- has-errors? trace
23 compare error?, 0/false
24 break-if-=
25 return
26 }
27 var in/esi: (addr handle cell) <- copy _in
28
29 {
30 compare screen-cell, 0
31 break-if-=
32 var tmp/eax: int <- copy call-number
33 tmp <- and 0xf
34 compare tmp, 0
35 break-if-!=
36 var screen-cell/eax: (addr handle cell) <- copy screen-cell
37 var screen-cell-addr/eax: (addr cell) <- lookup *screen-cell
38 compare screen-cell-addr, 0
39 break-if-=
40 var screen-obj-ah/eax: (addr handle screen) <- get screen-cell-addr, screen-data
41 var screen-obj/eax: (addr screen) <- lookup *screen-obj-ah
42 compare screen-obj, 0
43 break-if-=
44 var y/ecx: int <- render-screen 0/screen, screen-obj, 0x70/xmin, 1/ymin
45 }
46
47
48
49
50
51
52 +-- 14 lines: # trace "evaluate " in " in environment " env -----------------------------------------------------------------------------------------------------------------------------
66 trace-lower trace
67 var in-addr/eax: (addr cell) <- lookup *in
68 {
69 var nil?/eax: boolean <- nil? in-addr
70 compare nil?, 0/false
71 break-if-=
72
73 trace-text trace, "eval", "nil"
74 copy-object _in, out
75 trace-higher trace
76 return
77 }
78 var in-type/ecx: (addr int) <- get in-addr, type
79 compare *in-type, 1/number
80 {
81 break-if-!=
82
83 trace-text trace, "eval", "number"
84 copy-object _in, out
85 trace-higher trace
86 return
87 }
88 compare *in-type, 3/stream
89 {
90 break-if-!=
91
92 trace-text trace, "eval", "stream"
93 copy-object _in, out
94 trace-higher trace
95 return
96 }
97 compare *in-type, 2/symbol
98 {
99 break-if-!=
100 trace-text trace, "eval", "symbol"
101 debug-print "a", 7/fg, 0xc5/bg=blue-bg
102 lookup-symbol in-addr, out, env-h, globals, trace, screen-cell, keyboard-cell
103 debug-print "z", 7/fg, 0xc5/bg=blue-bg
104 trace-higher trace
105 return
106 }
107 compare *in-type, 5/screen
108 {
109 break-if-!=
110 trace-text trace, "eval", "screen"
111 copy-object _in, out
112 trace-higher trace
113 return
114 }
115 compare *in-type, 6/keyboard
116 {
117 break-if-!=
118 trace-text trace, "eval", "keyboard"
119 copy-object _in, out
120 trace-higher trace
121 return
122 }
123
124 $evaluate:anonymous-function: {
125
126 var expr/esi: (addr cell) <- copy in-addr
127
128 var in-addr/edx: (addr cell) <- copy in-addr
129 var first-ah/ecx: (addr handle cell) <- get in-addr, left
130 var first/eax: (addr cell) <- lookup *first-ah
131 var fn?/eax: boolean <- fn? first
132 compare fn?, 0/false
133 break-if-=
134
135 trace-text trace, "eval", "anonymous function"
136 var rest-ah/eax: (addr handle cell) <- get in-addr, right
137 var tmp: (handle cell)
138 var tmp-ah/edi: (addr handle cell) <- address tmp
139 new-pair tmp-ah, env-h, *rest-ah
140 new-pair out, *first-ah, *tmp-ah
141 trace-higher trace
142 return
143 }
144
145 $evaluate:quote: {
146
147 var expr/esi: (addr cell) <- copy in-addr
148
149 var first-ah/ecx: (addr handle cell) <- get in-addr, left
150 var rest-ah/edx: (addr handle cell) <- get in-addr, right
151 var first/eax: (addr cell) <- lookup *first-ah
152 var quote?/eax: boolean <- symbol-equal? first, "'"
153 compare quote?, 0/false
154 break-if-=
155
156 trace-text trace, "eval", "quote"
157 copy-object rest-ah, out
158 trace-higher trace
159 return
160 }
161 $evaluate:def: {
162
163 var expr/esi: (addr cell) <- copy in-addr
164
165 var first-ah/ecx: (addr handle cell) <- get in-addr, left
166 var rest-ah/edx: (addr handle cell) <- get in-addr, right
167 var first/eax: (addr cell) <- lookup *first-ah
168 var def?/eax: boolean <- symbol-equal? first, "def"
169 compare def?, 0/false
170 break-if-=
171
172 trace-text trace, "eval", "def"
173 trace-text trace, "eval", "evaluating second arg"
174 var rest/eax: (addr cell) <- lookup *rest-ah
175 var first-arg-ah/ecx: (addr handle cell) <- get rest, left
176 {
177 var first-arg/eax: (addr cell) <- lookup *first-arg-ah
178 var first-arg-type/eax: (addr int) <- get first-arg, type
179 compare *first-arg-type, 2/symbol
180 break-if-=
181 error trace, "first arg to def must be a symbol"
182 trace-higher trace
183 return
184 }
185 rest-ah <- get rest, right
186 rest <- lookup *rest-ah
187 var second-arg-ah/edx: (addr handle cell) <- get rest, left
188 debug-print "P", 4/fg, 0xc5/bg=blue-bg
189 increment call-number
190 evaluate second-arg-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
191 debug-print "Q", 4/fg, 0xc5/bg=blue-bg
192 trace-text trace, "eval", "saving global binding"
193 var first-arg/eax: (addr cell) <- lookup *first-arg-ah
194 var first-arg-data-ah/eax: (addr handle stream byte) <- get first-arg, text-data
195 var first-arg-data/eax: (addr stream byte) <- lookup *first-arg-data-ah
196 var tmp-string: (handle array byte)
197 var tmp-ah/edx: (addr handle array byte) <- address tmp-string
198 rewind-stream first-arg-data
199 stream-to-array first-arg-data, tmp-ah
200 var first-arg-data-string/eax: (addr array byte) <- lookup *tmp-ah
201 var out2/edi: (addr handle cell) <- copy out
202 assign-or-create-global globals, first-arg-data-string, *out2, trace
203 trace-higher trace
204 return
205 }
206 $evaluate:set: {
207
208 var expr/esi: (addr cell) <- copy in-addr
209
210 var first-ah/ecx: (addr handle cell) <- get in-addr, left
211 var rest-ah/edx: (addr handle cell) <- get in-addr, right
212 var first/eax: (addr cell) <- lookup *first-ah
213 var set?/eax: boolean <- symbol-equal? first, "set"
214 compare set?, 0/false
215 break-if-=
216
217 trace-text trace, "eval", "set"
218 trace-text trace, "eval", "evaluating second arg"
219 var rest/eax: (addr cell) <- lookup *rest-ah
220 var first-arg-ah/ecx: (addr handle cell) <- get rest, left
221 {
222 var first-arg/eax: (addr cell) <- lookup *first-arg-ah
223 var first-arg-type/eax: (addr int) <- get first-arg, type
224 compare *first-arg-type, 2/symbol
225 break-if-=
226 error trace, "first arg to set must be a symbol"
227 trace-higher trace
228 return
229 }
230 rest-ah <- get rest, right
231 rest <- lookup *rest-ah
232 var second-arg-ah/edx: (addr handle cell) <- get rest, left
233 debug-print "P", 4/fg, 0xc5/bg=blue-bg
234 increment call-number
235 evaluate second-arg-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
236 debug-print "Q", 4/fg, 0xc5/bg=blue-bg
237 trace-text trace, "eval", "mutating binding"
238 var first-arg/eax: (addr cell) <- lookup *first-arg-ah
239 var first-arg-data-ah/eax: (addr handle stream byte) <- get first-arg, text-data
240 var first-arg-data/eax: (addr stream byte) <- lookup *first-arg-data-ah
241 mutate-binding first-arg-data, out, env-h, globals, trace
242 trace-higher trace
243 return
244 }
245 $evaluate:and: {
246 var expr/esi: (addr cell) <- copy in-addr
247
248 var first-ah/ecx: (addr handle cell) <- get in-addr, left
249 var rest-ah/edx: (addr handle cell) <- get in-addr, right
250 var first/eax: (addr cell) <- lookup *first-ah
251 var and?/eax: boolean <- symbol-equal? first, "and"
252 compare and?, 0/false
253 break-if-=
254
255 trace-text trace, "eval", "and"
256 trace-text trace, "eval", "evaluating first arg"
257 var rest/eax: (addr cell) <- lookup *rest-ah
258 var first-arg-ah/ecx: (addr handle cell) <- get rest, left
259 debug-print "R2", 4/fg, 0xc5/bg=blue-bg
260 increment call-number
261 evaluate first-arg-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
262 debug-print "S2", 4/fg, 0xc5/bg=blue-bg
263
264 var out-ah/eax: (addr handle cell) <- copy out
265 var out-a/eax: (addr cell) <- lookup *out-ah
266 var nil?/eax: boolean <- nil? out-a
267 compare nil?, 0/false
268 {
269 break-if-=
270 return
271 }
272 var rest/eax: (addr cell) <- lookup *rest-ah
273 rest-ah <- get rest, right
274 rest <- lookup *rest-ah
275 var second-ah/eax: (addr handle cell) <- get rest, left
276 debug-print "T2", 4/fg, 0xc5/bg=blue-bg
277 increment call-number
278 evaluate second-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
279 debug-print "U2", 4/fg, 0xc5/bg=blue-bg
280 trace-higher trace
281 return
282 }
283 $evaluate:or: {
284 var expr/esi: (addr cell) <- copy in-addr
285
286 var first-ah/ecx: (addr handle cell) <- get in-addr, left
287 var rest-ah/edx: (addr handle cell) <- get in-addr, right
288 var first/eax: (addr cell) <- lookup *first-ah
289 var or?/eax: boolean <- symbol-equal? first, "or"
290 compare or?, 0/false
291 break-if-=
292
293 trace-text trace, "eval", "or"
294 trace-text trace, "eval", "evaluating first arg"
295 var rest/eax: (addr cell) <- lookup *rest-ah
296 var first-arg-ah/ecx: (addr handle cell) <- get rest, left
297 debug-print "R2", 4/fg, 0xc5/bg=blue-bg
298 increment call-number
299 evaluate first-arg-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
300 debug-print "S2", 4/fg, 0xc5/bg=blue-bg
301
302 var out-ah/eax: (addr handle cell) <- copy out
303 var out-a/eax: (addr cell) <- lookup *out-ah
304 var nil?/eax: boolean <- nil? out-a
305 compare nil?, 0/false
306 {
307 break-if-!=
308 return
309 }
310 var rest/eax: (addr cell) <- lookup *rest-ah
311 rest-ah <- get rest, right
312 rest <- lookup *rest-ah
313 var second-ah/eax: (addr handle cell) <- get rest, left
314 debug-print "T2", 4/fg, 0xc5/bg=blue-bg
315 increment call-number
316 evaluate second-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
317 debug-print "U2", 4/fg, 0xc5/bg=blue-bg
318 trace-higher trace
319 return
320 }
321 $evaluate:if: {
322
323 var expr/esi: (addr cell) <- copy in-addr
324
325 var first-ah/ecx: (addr handle cell) <- get in-addr, left
326 var rest-ah/edx: (addr handle cell) <- get in-addr, right
327 var first/eax: (addr cell) <- lookup *first-ah
328 var if?/eax: boolean <- symbol-equal? first, "if"
329 compare if?, 0/false
330 break-if-=
331
332 trace-text trace, "eval", "if"
333 trace-text trace, "eval", "evaluating first arg"
334 var rest/eax: (addr cell) <- lookup *rest-ah
335 var first-arg-ah/ecx: (addr handle cell) <- get rest, left
336 var guard-h: (handle cell)
337 var guard-ah/esi: (addr handle cell) <- address guard-h
338 debug-print "R", 4/fg, 0xc5/bg=blue-bg
339 increment call-number
340 evaluate first-arg-ah, guard-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
341 debug-print "S", 4/fg, 0xc5/bg=blue-bg
342 rest-ah <- get rest, right
343 rest <- lookup *rest-ah
344 var branch-ah/edi: (addr handle cell) <- get rest, left
345 var guard-a/eax: (addr cell) <- lookup *guard-ah
346 var skip-to-third-arg?/eax: boolean <- nil? guard-a
347 compare skip-to-third-arg?, 0/false
348 {
349 break-if-=
350 trace-text trace, "eval", "skipping to third arg"
351 var rest/eax: (addr cell) <- lookup *rest-ah
352 rest-ah <- get rest, right
353 rest <- lookup *rest-ah
354 branch-ah <- get rest, left
355 }
356 debug-print "T", 4/fg, 0xc5/bg=blue-bg
357 increment call-number
358 evaluate branch-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
359 debug-print "U", 4/fg, 0xc5/bg=blue-bg
360 trace-higher trace
361 return
362 }
363 $evaluate:while: {
364
365 var expr/esi: (addr cell) <- copy in-addr
366
367 var first-ah/ecx: (addr handle cell) <- get in-addr, left
368 var rest-ah/edx: (addr handle cell) <- get in-addr, right
369 var first/eax: (addr cell) <- lookup *first-ah
370 var first-type/ecx: (addr int) <- get first, type
371 compare *first-type, 2/symbol
372 break-if-!=
373 var sym-data-ah/eax: (addr handle stream byte) <- get first, text-data
374 var sym-data/eax: (addr stream byte) <- lookup *sym-data-ah
375 var while?/eax: boolean <- stream-data-equal? sym-data, "while"
376 compare while?, 0/false
377 break-if-=
378
379 trace-text trace, "eval", "while"
380 var rest/eax: (addr cell) <- lookup *rest-ah
381 var first-arg-ah/ecx: (addr handle cell) <- get rest, left
382 rest-ah <- get rest, right
383 var guard-h: (handle cell)
384 var guard-ah/esi: (addr handle cell) <- address guard-h
385 $evaluate:while:loop-execution: {
386 {
387 compare trace, 0
388 break-if-=
389 var error?/eax: boolean <- has-errors? trace
390 compare error?, 0/false
391 break-if-!= $evaluate:while:loop-execution
392 }
393 trace-text trace, "eval", "loop termination check"
394 debug-print "V", 4/fg, 0xc5/bg=blue-bg
395 increment call-number
396 evaluate first-arg-ah, guard-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
397 debug-print "W", 4/fg, 0xc5/bg=blue-bg
398 var guard-a/eax: (addr cell) <- lookup *guard-ah
399 var done?/eax: boolean <- nil? guard-a
400 compare done?, 0/false
401 break-if-!=
402 evaluate-exprs rest-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
403 loop
404 }
405 trace-text trace, "eval", "loop terminated"
406 trace-higher trace
407 return
408 }
409 trace-text trace, "eval", "function call"
410 trace-text trace, "eval", "evaluating list elements"
411 trace-lower trace
412 var evaluated-list-storage: (handle cell)
413 var evaluated-list-ah/esi: (addr handle cell) <- address evaluated-list-storage
414 var curr-out-ah/edx: (addr handle cell) <- copy evaluated-list-ah
415 var curr/ecx: (addr cell) <- copy in-addr
416 $evaluate-list:loop: {
417 allocate-pair curr-out-ah
418 var nil?/eax: boolean <- nil? curr
419 compare nil?, 0/false
420 break-if-!=
421
422 var curr-out/eax: (addr cell) <- lookup *curr-out-ah
423 var left-out-ah/edi: (addr handle cell) <- get curr-out, left
424 var left-ah/esi: (addr handle cell) <- get curr, left
425 debug-print "A", 4/fg, 0xc5/bg=blue-bg
426 increment call-number
427 evaluate left-ah, left-out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
428 debug-print "B", 4/fg, 0xc5/bg=blue-bg
429
430 curr-out-ah <- get curr-out, right
431 var right-ah/eax: (addr handle cell) <- get curr, right
432 var right/eax: (addr cell) <- lookup *right-ah
433 curr <- copy right
434 loop
435 }
436 trace-higher trace
437 var evaluated-list/eax: (addr cell) <- lookup *evaluated-list-ah
438 var function-ah/ecx: (addr handle cell) <- get evaluated-list, left
439 var args-ah/edx: (addr handle cell) <- get evaluated-list, right
440 debug-print "C", 4/fg, 0xc5/bg=blue-bg
441 apply function-ah, args-ah, out, globals, trace, screen-cell, keyboard-cell, call-number
442 debug-print "Y", 4/fg, 0xc5/bg=blue-bg
443 trace-higher trace
444 +-- 11 lines: # trace "=> " out ---------------------------------------------------------------------------------------------------------------------------------------------------------
455 debug-print "Z", 4/fg, 0xc5/bg=blue-bg
456 }
457
458 fn apply _f-ah: (addr handle cell), args-ah: (addr handle cell), out: (addr handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell), call-number: int {
459 var f-ah/eax: (addr handle cell) <- copy _f-ah
460 var _f/eax: (addr cell) <- lookup *f-ah
461 var f/esi: (addr cell) <- copy _f
462
463 {
464 var f-type/eax: (addr int) <- get f, type
465 compare *f-type, 4/primitive-function
466 break-if-!=
467 apply-primitive f, args-ah, out, globals, trace
468 return
469 }
470
471 +-- 14 lines: # trace "apply anonymous function " f " in environment " env --------------------------------------------------------------------------------------------------------------
485 trace-lower trace
486 {
487 var f-type/ecx: (addr int) <- get f, type
488 compare *f-type, 0/pair
489 break-if-!=
490 var first-ah/eax: (addr handle cell) <- get f, left
491 var first/eax: (addr cell) <- lookup *first-ah
492 var fn?/eax: boolean <- fn? first
493 compare fn?, 0/false
494 break-if-=
495 var rest-ah/esi: (addr handle cell) <- get f, right
496 var rest/eax: (addr cell) <- lookup *rest-ah
497 var callee-env-ah/edx: (addr handle cell) <- get rest, left
498 rest-ah <- get rest, right
499 rest <- lookup *rest-ah
500 var params-ah/ecx: (addr handle cell) <- get rest, left
501 var body-ah/eax: (addr handle cell) <- get rest, right
502 debug-print "D", 7/fg, 0xc5/bg=blue-bg
503 apply-function params-ah, args-ah, body-ah, out, *callee-env-ah, globals, trace, screen-cell, keyboard-cell, call-number
504 debug-print "Y", 7/fg, 0xc5/bg=blue-bg
505 trace-higher trace
506 return
507 }
508 error trace, "unknown function"
509 }
510
511 fn apply-function params-ah: (addr handle cell), args-ah: (addr handle cell), body-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell), call-number: int {
512
513 var new-env-h: (handle cell)
514 var new-env-ah/esi: (addr handle cell) <- address new-env-h
515 push-bindings params-ah, args-ah, env-h, new-env-ah, trace
516
517 evaluate-exprs body-ah, out, new-env-h, globals, trace, screen-cell, keyboard-cell, call-number
518 }
519
520 fn evaluate-exprs _exprs-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell), call-number: int {
521
522 var exprs-ah/ecx: (addr handle cell) <- copy _exprs-ah
523 $evaluate-exprs:loop: {
524 var exprs/eax: (addr cell) <- lookup *exprs-ah
525
526 {
527 var exprs-nil?/eax: boolean <- nil? exprs
528 compare exprs-nil?, 0/false
529 break-if-!= $evaluate-exprs:loop
530 }
531
532 {
533 var curr-ah/eax: (addr handle cell) <- get exprs, left
534 debug-print "E", 7/fg, 0xc5/bg=blue-bg
535 increment call-number
536 evaluate curr-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
537 debug-print "X", 7/fg, 0xc5/bg=blue-bg
538 }
539
540 exprs-ah <- get exprs, right
541 loop
542 }
543
544 }
545
546
547
548
549
550
551
552
553
554
555
556
557 fn push-bindings _params-ah: (addr handle cell), _args-ah: (addr handle cell), old-env-h: (handle cell), env-ah: (addr handle cell), trace: (addr trace) {
558 var params-ah/edx: (addr handle cell) <- copy _params-ah
559 var args-ah/ebx: (addr handle cell) <- copy _args-ah
560 var _params/eax: (addr cell) <- lookup *params-ah
561 var params/esi: (addr cell) <- copy _params
562 {
563 var params-nil?/eax: boolean <- nil? params
564 compare params-nil?, 0/false
565 break-if-=
566
567 trace-text trace, "eval", "done with push-bindings"
568 copy-handle old-env-h, env-ah
569 return
570 }
571
572 +-- 16 lines: # trace "pushing bindings from " params " to " args -----------------------------------------------------------------------------------------------------------------------
588 trace-lower trace
589 var params-type/eax: (addr int) <- get params, type
590 compare *params-type, 2/symbol
591 {
592 break-if-!=
593 trace-text trace, "eval", "symbol; binding to all remaining args"
594
595 var new-binding-storage: (handle cell)
596 var new-binding-ah/eax: (addr handle cell) <- address new-binding-storage
597 new-pair new-binding-ah, *params-ah, *args-ah
598
599 new-pair env-ah, *new-binding-ah, old-env-h
600 trace-higher trace
601 return
602 }
603 compare *params-type, 0/pair
604 {
605 break-if-=
606 error trace, "cannot bind a non-symbol"
607 trace-higher trace
608 return
609 }
610 var _args/eax: (addr cell) <- lookup *args-ah
611 var args/edi: (addr cell) <- copy _args
612
613 var args-type/eax: (addr int) <- get args, type
614 compare *args-type, 0/pair
615 {
616 break-if-=
617 error trace, "args not in a proper list"
618 trace-higher trace
619 return
620 }
621 var intermediate-env-storage: (handle cell)
622 var intermediate-env-ah/edx: (addr handle cell) <- address intermediate-env-storage
623 var first-param-ah/eax: (addr handle cell) <- get params, left
624 var first-arg-ah/ecx: (addr handle cell) <- get args, left
625 push-bindings first-param-ah, first-arg-ah, old-env-h, intermediate-env-ah, trace
626 var remaining-params-ah/eax: (addr handle cell) <- get params, right
627 var remaining-args-ah/ecx: (addr handle cell) <- get args, right
628 push-bindings remaining-params-ah, remaining-args-ah, *intermediate-env-ah, env-ah, trace
629 trace-higher trace
630 }
631
632 fn lookup-symbol sym: (addr cell), out: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell) {
633
634 {
635 compare trace, 0
636 break-if-=
637 var stream-storage: (stream byte 0x800)
638 var stream/ecx: (addr stream byte) <- address stream-storage
639 write stream, "look up "
640 var sym2/eax: (addr cell) <- copy sym
641 var sym-data-ah/eax: (addr handle stream byte) <- get sym2, text-data
642 var sym-data/eax: (addr stream byte) <- lookup *sym-data-ah
643 rewind-stream sym-data
644 write-stream stream, sym-data
645 write stream, " in "
646 var env-ah/eax: (addr handle cell) <- address env-h
647 print-cell env-ah, stream, 0/no-trace
648 trace trace, "eval", stream
649 }
650 trace-lower trace
651 var _env/eax: (addr cell) <- lookup env-h
652 var env/ebx: (addr cell) <- copy _env
653
654 {
655 var env-type/ecx: (addr int) <- get env, type
656 compare *env-type, 0/pair
657 break-if-=
658 error trace, "eval found a non-list environment"
659 trace-higher trace
660 return
661 }
662
663 {
664 var env-nil?/eax: boolean <- nil? env
665 compare env-nil?, 0/false
666 break-if-=
667 debug-print "b", 7/fg, 0xc5/bg=blue-bg
668 lookup-symbol-in-globals sym, out, globals, trace, screen-cell, keyboard-cell
669 debug-print "x", 7/fg, 0xc5/bg=blue-bg
670 trace-higher trace
671 +-- 15 lines: # trace "=> " out " (global)" ---------------------------------------------------------------------------------------------------------------------------------------------
686 debug-print "y", 7/fg, 0xc5/bg=blue-bg
687 return
688 }
689
690 var env-head-storage: (handle cell)
691 var env-head-ah/eax: (addr handle cell) <- address env-head-storage
692 car env, env-head-ah, 0/no-trace
693 var _env-head/eax: (addr cell) <- lookup *env-head-ah
694 var env-head/ecx: (addr cell) <- copy _env-head
695
696 {
697 var env-head-type/eax: (addr int) <- get env-head, type
698 compare *env-head-type, 0/pair
699 break-if-=
700 error trace, "environment is not a list of (key . value) pairs"
701 trace-higher trace
702 return
703 }
704
705 var curr-key-storage: (handle cell)
706 var curr-key-ah/eax: (addr handle cell) <- address curr-key-storage
707 car env-head, curr-key-ah, trace
708 var curr-key/eax: (addr cell) <- lookup *curr-key-ah
709
710 {
711 var curr-key-type/eax: (addr int) <- get curr-key, type
712 compare *curr-key-type, 2/symbol
713 break-if-=
714 error trace, "environment contains a binding for a non-symbol"
715 trace-higher trace
716 return
717 }
718
719 var match?/eax: boolean <- cell-isomorphic? curr-key, sym, trace
720 compare match?, 0/false
721 {
722 break-if-=
723 cdr env-head, out, 0/no-trace
724 +-- 15 lines: # trace "=> " out " (match)" ----------------------------------------------------------------------------------------------------------------------------------------------
739 trace-higher trace
740 return
741 }
742
743 var env-tail-storage: (handle cell)
744 var env-tail-ah/eax: (addr handle cell) <- address env-tail-storage
745 cdr env, env-tail-ah, trace
746 lookup-symbol sym, out, *env-tail-ah, globals, trace, screen-cell, keyboard-cell
747 trace-higher trace
748 +-- 15 lines: # trace "=> " out " (recurse)" --------------------------------------------------------------------------------------------------------------------------------------------
763 }
764
765 fn test-lookup-symbol-in-env {
766
767 var val-storage: (handle cell)
768 var val-ah/ecx: (addr handle cell) <- address val-storage
769 new-integer val-ah, 3
770 var key-storage: (handle cell)
771 var key-ah/edx: (addr handle cell) <- address key-storage
772 new-symbol key-ah, "a"
773 var env-storage: (handle cell)
774 var env-ah/ebx: (addr handle cell) <- address env-storage
775 new-pair env-ah, *key-ah, *val-ah
776
777 var nil-storage: (handle cell)
778 var nil-ah/ecx: (addr handle cell) <- address nil-storage
779 allocate-pair nil-ah
780 new-pair env-ah, *env-ah, *nil-ah
781
782 var tmp-storage: (handle cell)
783 var tmp-ah/edx: (addr handle cell) <- address tmp-storage
784 new-symbol tmp-ah, "a"
785 var in/eax: (addr cell) <- lookup *tmp-ah
786 lookup-symbol in, tmp-ah, *env-ah, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard
787 var result/eax: (addr cell) <- lookup *tmp-ah
788 var result-type/edx: (addr int) <- get result, type
789 check-ints-equal *result-type, 1/number, "F - test-lookup-symbol-in-env/0"
790 var result-value-addr/eax: (addr float) <- get result, number-data
791 var result-value/eax: int <- convert *result-value-addr
792 check-ints-equal result-value, 3, "F - test-lookup-symbol-in-env/1"
793 }
794
795 fn test-lookup-symbol-in-globals {
796 var globals-storage: global-table
797 var globals/edi: (addr global-table) <- address globals-storage
798 initialize-globals globals
799
800 var nil-storage: (handle cell)
801 var nil-ah/ecx: (addr handle cell) <- address nil-storage
802 allocate-pair nil-ah
803
804 var tmp-storage: (handle cell)
805 var tmp-ah/ebx: (addr handle cell) <- address tmp-storage
806 new-symbol tmp-ah, "+"
807 var in/eax: (addr cell) <- lookup *tmp-ah
808 lookup-symbol in, tmp-ah, *nil-ah, globals, 0/no-trace, 0/no-screen, 0/no-keyboard
809 var result/eax: (addr cell) <- lookup *tmp-ah
810 var result-type/edx: (addr int) <- get result, type
811 check-ints-equal *result-type, 4/primitive-function, "F - test-lookup-symbol-in-globals/0"
812 var result-value/eax: (addr int) <- get result, index-data
813 check-ints-equal *result-value, 1/add, "F - test-lookup-symbol-in-globals/1"
814 }
815
816 fn mutate-binding name: (addr stream byte), val: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace) {
817
818 {
819 compare trace, 0
820 break-if-=
821 var stream-storage: (stream byte 0x800)
822 var stream/ecx: (addr stream byte) <- address stream-storage
823 write stream, "bind "
824 rewind-stream name
825 write-stream stream, name
826 write stream, " to "
827 print-cell val, stream, 0/no-trace
828 write stream, " in "
829 var env-ah/eax: (addr handle cell) <- address env-h
830 print-cell env-ah, stream, 0/no-trace
831 trace trace, "eval", stream
832 }
833 trace-lower trace
834 var _env/eax: (addr cell) <- lookup env-h
835 var env/ebx: (addr cell) <- copy _env
836
837 {
838 var env-type/ecx: (addr int) <- get env, type
839 compare *env-type, 0/pair
840 break-if-=
841 error trace, "eval found a non-list environment"
842 trace-higher trace
843 return
844 }
845
846 {
847 var env-nil?/eax: boolean <- nil? env
848 compare env-nil?, 0/false
849 break-if-=
850 debug-print "b", 3/fg, 0xc5/bg=blue-bg
851 mutate-binding-in-globals name, val, globals, trace
852 debug-print "x", 3/fg, 0xc5/bg=blue-bg
853 trace-higher trace
854 +-- 15 lines: # trace "=> " val " (global)" ---------------------------------------------------------------------------------------------------------------------------------------------
869 debug-print "y", 3/fg, 0xc5/bg=blue-bg
870 return
871 }
872
873 var env-head-storage: (handle cell)
874 var env-head-ah/eax: (addr handle cell) <- address env-head-storage
875 car env, env-head-ah, 0/no-trace
876 var _env-head/eax: (addr cell) <- lookup *env-head-ah
877 var env-head/ecx: (addr cell) <- copy _env-head
878
879 {
880 var env-head-type/eax: (addr int) <- get env-head, type
881 compare *env-head-type, 0/pair
882 break-if-=
883 error trace, "environment is not a list of (key . value) pairs"
884 trace-higher trace
885 return
886 }
887
888 var curr-key-storage: (handle cell)
889 var curr-key-ah/eax: (addr handle cell) <- address curr-key-storage
890 car env-head, curr-key-ah, trace
891 var curr-key/eax: (addr cell) <- lookup *curr-key-ah
892
893 {
894 var curr-key-type/eax: (addr int) <- get curr-key, type
895 compare *curr-key-type, 2/symbol
896 break-if-=
897 error trace, "environment contains a binding for a non-symbol"
898 trace-higher trace
899 return
900 }
901
902 var curr-key-data-ah/eax: (addr handle stream byte) <- get curr-key, text-data
903 var curr-key-data/eax: (addr stream byte) <- lookup *curr-key-data-ah
904 var match?/eax: boolean <- streams-data-equal? curr-key-data, name
905 compare match?, 0/false
906 {
907 break-if-=
908 var dest/eax: (addr handle cell) <- get env-head, right
909 copy-object val, dest
910 trace-text trace, "eval", "=> done"
911 trace-higher trace
912 return
913 }
914
915 var env-tail-storage: (handle cell)
916 var env-tail-ah/eax: (addr handle cell) <- address env-tail-storage
917 cdr env, env-tail-ah, trace
918 mutate-binding name, val, *env-tail-ah, globals, trace
919 trace-higher trace
920 }
921
922 fn car _in: (addr cell), out: (addr handle cell), trace: (addr trace) {
923 trace-text trace, "eval", "car"
924 trace-lower trace
925 var in/eax: (addr cell) <- copy _in
926
927 {
928 var in-type/ecx: (addr int) <- get in, type
929 compare *in-type, 0/pair
930 break-if-=
931 error trace, "car on a non-list"
932 trace-higher trace
933 return
934 }
935
936 {
937 var in-nil?/eax: boolean <- nil? in
938 compare in-nil?, 0/false
939 break-if-=
940 error trace, "car on nil"
941 trace-higher trace
942 return
943 }
944 var in-left/eax: (addr handle cell) <- get in, left
945 copy-object in-left, out
946 trace-higher trace
947 return
948 }
949
950 fn cdr _in: (addr cell), out: (addr handle cell), trace: (addr trace) {
951 trace-text trace, "eval", "cdr"
952 trace-lower trace
953 var in/eax: (addr cell) <- copy _in
954
955 {
956 var in-type/ecx: (addr int) <- get in, type
957 compare *in-type, 0/pair
958 break-if-=
959 error trace, "car on a non-list"
960 trace-higher trace
961 return
962 }
963
964 {
965 var in-nil?/eax: boolean <- nil? in
966 compare in-nil?, 0/false
967 break-if-=
968 error trace, "car on nil"
969 trace-higher trace
970 return
971 }
972 var in-right/eax: (addr handle cell) <- get in, right
973 copy-object in-right, out
974 trace-higher trace
975 return
976 }
977
978 fn cell-isomorphic? _a: (addr cell), _b: (addr cell), trace: (addr trace) -> _/eax: boolean {
979 trace-text trace, "eval", "cell-isomorphic?"
980 trace-lower trace
981 var a/esi: (addr cell) <- copy _a
982 var b/edi: (addr cell) <- copy _b
983
984 var a-type-addr/eax: (addr int) <- get a, type
985 var b-type-addr/ecx: (addr int) <- get b, type
986 var b-type/ecx: int <- copy *b-type-addr
987 compare b-type, *a-type-addr
988 {
989 break-if-=
990 trace-higher trace
991 trace-text trace, "eval", "=> false (type)"
992 return 0/false
993 }
994
995
996 compare b-type, 1/number
997 {
998 break-if-!=
999 var a-val-addr/eax: (addr float) <- get a, number-data
1000 var b-val-addr/ecx: (addr float) <- get b, number-data
1001 var a-val/xmm0: float <- copy *a-val-addr
1002 compare a-val, *b-val-addr
1003 {
1004 break-if-=
1005 trace-higher trace
1006 trace-text trace, "eval", "=> false (numbers)"
1007 return 0/false
1008 }
1009 trace-higher trace
1010 trace-text trace, "eval", "=> true (numbers)"
1011 return 1/true
1012 }
1013 compare b-type, 2/symbol
1014 {
1015 break-if-!=
1016 var b-val-ah/eax: (addr handle stream byte) <- get b, text-data
1017 var _b-val/eax: (addr stream byte) <- lookup *b-val-ah
1018 var b-val/ecx: (addr stream byte) <- copy _b-val
1019 var a-val-ah/eax: (addr handle stream byte) <- get a, text-data
1020 var a-val/eax: (addr stream byte) <- lookup *a-val-ah
1021 var tmp-array: (handle array byte)
1022 var tmp-ah/edx: (addr handle array byte) <- address tmp-array
1023 rewind-stream a-val
1024 stream-to-array a-val, tmp-ah
1025 var tmp/eax: (addr array byte) <- lookup *tmp-ah
1026 var match?/eax: boolean <- stream-data-equal? b-val, tmp
1027 trace-higher trace
1028 {
1029 compare match?, 0/false
1030 break-if-=
1031 trace-text trace, "eval", "=> true (symbols)"
1032 }
1033 {
1034 compare match?, 0/false
1035 break-if-!=
1036 trace-text trace, "eval", "=> false (symbols)"
1037 }
1038 return match?
1039 }
1040
1041 {
1042
1043 var _b-nil?/eax: boolean <- nil? b
1044 var b-nil?/ecx: boolean <- copy _b-nil?
1045 var a-nil?/eax: boolean <- nil? a
1046
1047 {
1048 compare a-nil?, 0/false
1049 break-if-=
1050 compare b-nil?, 0/false
1051 break-if-=
1052 trace-higher trace
1053 trace-text trace, "eval", "=> true (nils)"
1054 return 1/true
1055 }
1056
1057 {
1058 compare a-nil?, 0/false
1059 break-if-=
1060 trace-higher trace
1061 trace-text trace, "eval", "=> false (b != nil)"
1062 return 0/false
1063 }
1064
1065 {
1066 compare b-nil?, 0/false
1067 break-if-=
1068 trace-higher trace
1069 trace-text trace, "eval", "=> false (a != nil)"
1070 return 0/false
1071 }
1072 }
1073
1074 var a-tmp-storage: (handle cell)
1075 var a-tmp-ah/edx: (addr handle cell) <- address a-tmp-storage
1076 var b-tmp-storage: (handle cell)
1077 var b-tmp-ah/ebx: (addr handle cell) <- address b-tmp-storage
1078
1079 car a, a-tmp-ah, trace
1080 car b, b-tmp-ah, trace
1081 {
1082 var _a-tmp/eax: (addr cell) <- lookup *a-tmp-ah
1083 var a-tmp/ecx: (addr cell) <- copy _a-tmp
1084 var b-tmp/eax: (addr cell) <- lookup *b-tmp-ah
1085 var result/eax: boolean <- cell-isomorphic? a-tmp, b-tmp, trace
1086 compare result, 0/false
1087 break-if-!=
1088 trace-higher trace
1089 trace-text trace, "eval", "=> false (car mismatch)"
1090 return 0/false
1091 }
1092
1093 cdr a, a-tmp-ah, trace
1094 cdr b, b-tmp-ah, trace
1095 var _a-tmp/eax: (addr cell) <- lookup *a-tmp-ah
1096 var a-tmp/ecx: (addr cell) <- copy _a-tmp
1097 var b-tmp/eax: (addr cell) <- lookup *b-tmp-ah
1098 var result/eax: boolean <- cell-isomorphic? a-tmp, b-tmp, trace
1099 trace-higher trace
1100 return result
1101 }
1102
1103 fn fn? _x: (addr cell) -> _/eax: boolean {
1104 var x/esi: (addr cell) <- copy _x
1105 var type/eax: (addr int) <- get x, type
1106 compare *type, 2/symbol
1107 {
1108 break-if-=
1109 return 0/false
1110 }
1111 var contents-ah/eax: (addr handle stream byte) <- get x, text-data
1112 var contents/eax: (addr stream byte) <- lookup *contents-ah
1113 var result/eax: boolean <- stream-data-equal? contents, "fn"
1114 return result
1115 }
1116
1117 fn test-evaluate-is-well-behaved {
1118 var t-storage: trace
1119 var t/esi: (addr trace) <- address t-storage
1120 initialize-trace t, 0x10, 0/visible
1121
1122 var env-storage: (handle cell)
1123 var env-ah/ecx: (addr handle cell) <- address env-storage
1124 allocate-pair env-ah
1125
1126 var tmp-storage: (handle cell)
1127 var tmp-ah/edx: (addr handle cell) <- address tmp-storage
1128 new-symbol tmp-ah, "a"
1129 evaluate tmp-ah, tmp-ah, *env-ah, 0/no-globals, t, 0/no-screen, 0/no-keyboard, 0/call-number
1130
1131 check-trace-contains t, "error", "unbound symbol: a", "F - test-evaluate-is-well-behaved"
1132 }
1133
1134 fn test-evaluate-number {
1135
1136 var env-storage: (handle cell)
1137 var env-ah/ecx: (addr handle cell) <- address env-storage
1138 allocate-pair env-ah
1139
1140 var tmp-storage: (handle cell)
1141 var tmp-ah/edx: (addr handle cell) <- address tmp-storage
1142 new-integer tmp-ah, 3
1143 evaluate tmp-ah, tmp-ah, *env-ah, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
1144
1145 var result/eax: (addr cell) <- lookup *tmp-ah
1146 var result-type/edx: (addr int) <- get result, type
1147 check-ints-equal *result-type, 1/number, "F - test-evaluate-number/0"
1148 var result-value-addr/eax: (addr float) <- get result, number-data
1149 var result-value/eax: int <- convert *result-value-addr
1150 check-ints-equal result-value, 3, "F - test-evaluate-number/1"
1151 }
1152
1153 fn test-evaluate-symbol {
1154
1155 var val-storage: (handle cell)
1156 var val-ah/ecx: (addr handle cell) <- address val-storage
1157 new-integer val-ah, 3
1158 var key-storage: (handle cell)
1159 var key-ah/edx: (addr handle cell) <- address key-storage
1160 new-symbol key-ah, "a"
1161 var env-storage: (handle cell)
1162 var env-ah/ebx: (addr handle cell) <- address env-storage
1163 new-pair env-ah, *key-ah, *val-ah
1164
1165 var nil-storage: (handle cell)
1166 var nil-ah/ecx: (addr handle cell) <- address nil-storage
1167 allocate-pair nil-ah
1168 new-pair env-ah, *env-ah, *nil-ah
1169
1170 var tmp-storage: (handle cell)
1171 var tmp-ah/edx: (addr handle cell) <- address tmp-storage
1172 new-symbol tmp-ah, "a"
1173 evaluate tmp-ah, tmp-ah, *env-ah, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
1174 var result/eax: (addr cell) <- lookup *tmp-ah
1175 var result-type/edx: (addr int) <- get result, type
1176 check-ints-equal *result-type, 1/number, "F - test-evaluate-symbol/0"
1177 var result-value-addr/eax: (addr float) <- get result, number-data
1178 var result-value/eax: int <- convert *result-value-addr
1179 check-ints-equal result-value, 3, "F - test-evaluate-symbol/1"
1180 }
1181
1182 fn test-evaluate-primitive-function {
1183 var globals-storage: global-table
1184 var globals/edi: (addr global-table) <- address globals-storage
1185 initialize-globals globals
1186 var nil-storage: (handle cell)
1187 var nil-ah/ecx: (addr handle cell) <- address nil-storage
1188 allocate-pair nil-ah
1189 var add-storage: (handle cell)
1190 var add-ah/ebx: (addr handle cell) <- address add-storage
1191 new-symbol add-ah, "+"
1192
1193 var tmp-storage: (handle cell)
1194 var tmp-ah/esi: (addr handle cell) <- address tmp-storage
1195 evaluate add-ah, tmp-ah, *nil-ah, globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
1196
1197 var result/eax: (addr cell) <- lookup *tmp-ah
1198 var result-type/edx: (addr int) <- get result, type
1199 check-ints-equal *result-type, 4/primitive-function, "F - test-evaluate-primitive-function/0"
1200 var result-value/eax: (addr int) <- get result, index-data
1201 check-ints-equal *result-value, 1/add, "F - test-evaluate-primitive-function/1"
1202 }
1203
1204 fn test-evaluate-primitive-function-call {
1205 var t-storage: trace
1206 var t/edi: (addr trace) <- address t-storage
1207 initialize-trace t, 0x100, 0/visible
1208
1209 var nil-storage: (handle cell)
1210 var nil-ah/ecx: (addr handle cell) <- address nil-storage
1211 allocate-pair nil-ah
1212 var one-storage: (handle cell)
1213 var one-ah/edx: (addr handle cell) <- address one-storage
1214 new-integer one-ah, 1
1215 var add-storage: (handle cell)
1216 var add-ah/ebx: (addr handle cell) <- address add-storage
1217 new-symbol add-ah, "+"
1218
1219 var tmp-storage: (handle cell)
1220 var tmp-ah/esi: (addr handle cell) <- address tmp-storage
1221 new-pair tmp-ah, *one-ah, *nil-ah
1222 new-pair tmp-ah, *one-ah, *tmp-ah
1223 new-pair tmp-ah, *add-ah, *tmp-ah
1224
1225
1226 var globals-storage: global-table
1227 var globals/edx: (addr global-table) <- address globals-storage
1228 initialize-globals globals
1229
1230 evaluate tmp-ah, tmp-ah, *nil-ah, globals, t, 0/no-screen, 0/no-keyboard, 0/call-number
1231
1232
1233 var result/eax: (addr cell) <- lookup *tmp-ah
1234 var result-type/edx: (addr int) <- get result, type
1235 check-ints-equal *result-type, 1/number, "F - test-evaluate-primitive-function-call/0"
1236 var result-value-addr/eax: (addr float) <- get result, number-data
1237 var result-value/eax: int <- convert *result-value-addr
1238 check-ints-equal result-value, 2, "F - test-evaluate-primitive-function-call/1"
1239 }