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 show-stack-state
9
10 {
11 compare trace, 0
12 break-if-=
13 var error?/eax: boolean <- has-errors? trace
14 compare error?, 0/false
15 break-if-=
16 return
17 }
18 var in/esi: (addr handle cell) <- copy _in
19
20 {
21 compare screen-cell, 0
22 break-if-=
23 var tmp/eax: int <- copy call-number
24 tmp <- and 0x3f
25 compare tmp, 0
26 break-if-!=
27 var screen-cell/eax: (addr handle cell) <- copy screen-cell
28 var screen-cell-addr/eax: (addr cell) <- lookup *screen-cell
29 compare screen-cell-addr, 0
30 break-if-=
31 var screen-obj-ah/eax: (addr handle screen) <- get screen-cell-addr, screen-data
32 var screen-obj/eax: (addr screen) <- lookup *screen-obj-ah
33 compare screen-obj, 0
34 break-if-=
35 var y/ecx: int <- render-screen 0/screen, screen-obj, 0x70/xmin, 2/ymin
36 }
37
38
39
40
41
42
43 +-- 14 lines: # trace "evaluate " in " in environment " env -----------------------------------------------------------------------------------------------------------------------------
57 trace-lower trace
58 var in-addr/eax: (addr cell) <- lookup *in
59 {
60 var nil?/eax: boolean <- nil? in-addr
61 compare nil?, 0/false
62 break-if-=
63
64 trace-text trace, "eval", "nil"
65 copy-object _in, out
66 trace-higher trace
67 return
68 }
69 var in-type/ecx: (addr int) <- get in-addr, type
70 compare *in-type, 1/number
71 {
72 break-if-!=
73
74 trace-text trace, "eval", "number"
75 copy-object _in, out
76 trace-higher trace
77 return
78 }
79 compare *in-type, 2/symbol
80 {
81 break-if-!=
82 trace-text trace, "eval", "symbol"
83 debug-print "a", 7/fg, 0/bg
84 lookup-symbol in-addr, out, env-h, globals, trace, screen-cell, keyboard-cell
85 debug-print "z", 7/fg, 0/bg
86 trace-higher trace
87 return
88 }
89 compare *in-type, 5/screen
90 {
91 break-if-!=
92 trace-text trace, "eval", "screen"
93 copy-object _in, out
94 trace-higher trace
95 return
96 }
97 compare *in-type, 6/keyboard
98 {
99 break-if-!=
100 trace-text trace, "eval", "keyboard"
101 copy-object _in, out
102 trace-higher trace
103 return
104 }
105
106 $evaluate:anonymous-function: {
107
108 var expr/esi: (addr cell) <- copy in-addr
109
110 var in-addr/edx: (addr cell) <- copy in-addr
111 var first-ah/ecx: (addr handle cell) <- get in-addr, left
112 var first/eax: (addr cell) <- lookup *first-ah
113 var fn?/eax: boolean <- fn? first
114 compare fn?, 0/false
115 break-if-=
116
117 trace-text trace, "eval", "anonymous function"
118 var rest-ah/eax: (addr handle cell) <- get in-addr, right
119 var tmp: (handle cell)
120 var tmp-ah/edi: (addr handle cell) <- address tmp
121 new-pair tmp-ah, env-h, *rest-ah
122 new-pair out, *first-ah, *tmp-ah
123 trace-higher trace
124 return
125 }
126
127 $evaluate:quote: {
128
129 var expr/esi: (addr cell) <- copy in-addr
130
131 var first-ah/ecx: (addr handle cell) <- get in-addr, left
132 var rest-ah/edx: (addr handle cell) <- get in-addr, right
133 var first/eax: (addr cell) <- lookup *first-ah
134 var first-type/ecx: (addr int) <- get first, type
135 compare *first-type, 2/symbol
136 break-if-!=
137 var sym-data-ah/eax: (addr handle stream byte) <- get first, text-data
138 var sym-data/eax: (addr stream byte) <- lookup *sym-data-ah
139 var quote?/eax: boolean <- stream-data-equal? sym-data, "'"
140 compare quote?, 0/false
141 break-if-=
142
143 trace-text trace, "eval", "quote"
144 copy-object rest-ah, out
145 trace-higher trace
146 return
147 }
148 $evaluate:set: {
149
150 var expr/esi: (addr cell) <- copy in-addr
151
152 var first-ah/ecx: (addr handle cell) <- get in-addr, left
153 var rest-ah/edx: (addr handle cell) <- get in-addr, right
154 var first/eax: (addr cell) <- lookup *first-ah
155 var first-type/ecx: (addr int) <- get first, type
156 compare *first-type, 2/symbol
157 break-if-!=
158 var sym-data-ah/eax: (addr handle stream byte) <- get first, text-data
159 var sym-data/eax: (addr stream byte) <- lookup *sym-data-ah
160 var set?/eax: boolean <- stream-data-equal? sym-data, "set"
161 compare set?, 0/false
162 break-if-=
163
164 trace-text trace, "eval", "set"
165 trace-text trace, "eval", "evaluating second arg"
166 var rest/eax: (addr cell) <- lookup *rest-ah
167 var first-arg-ah/ecx: (addr handle cell) <- get rest, left
168 {
169 var first-arg/eax: (addr cell) <- lookup *first-arg-ah
170 var first-arg-type/eax: (addr int) <- get first-arg, type
171 compare *first-arg-type, 2/symbol
172 break-if-=
173 error trace, "first arg to set must be a symbol"
174 trace-higher trace
175 return
176 }
177 rest-ah <- get rest, right
178 rest <- lookup *rest-ah
179 var second-arg-ah/edx: (addr handle cell) <- get rest, left
180 debug-print "P", 4/fg, 0/bg
181 increment call-number
182 evaluate second-arg-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
183 debug-print "Q", 4/fg, 0/bg
184 trace-text trace, "eval", "saving global binding"
185 var first-arg/eax: (addr cell) <- lookup *first-arg-ah
186 var first-arg-data-ah/eax: (addr handle stream byte) <- get first-arg, text-data
187 var first-arg-data/eax: (addr stream byte) <- lookup *first-arg-data-ah
188 var tmp-string: (handle array byte)
189 var tmp-ah/edx: (addr handle array byte) <- address tmp-string
190 rewind-stream first-arg-data
191 stream-to-array first-arg-data, tmp-ah
192 var first-arg-data-string/eax: (addr array byte) <- lookup *tmp-ah
193 var out2/edi: (addr handle cell) <- copy out
194 append-global globals, first-arg-data-string, *out2
195 trace-higher trace
196 return
197 }
198 $evaluate:if: {
199
200 var expr/esi: (addr cell) <- copy in-addr
201
202 var first-ah/ecx: (addr handle cell) <- get in-addr, left
203 var rest-ah/edx: (addr handle cell) <- get in-addr, right
204 var first/eax: (addr cell) <- lookup *first-ah
205 var first-type/ecx: (addr int) <- get first, type
206 compare *first-type, 2/symbol
207 break-if-!=
208 var sym-data-ah/eax: (addr handle stream byte) <- get first, text-data
209 var sym-data/eax: (addr stream byte) <- lookup *sym-data-ah
210 var if?/eax: boolean <- stream-data-equal? sym-data, "if"
211 compare if?, 0/false
212 break-if-=
213
214 trace-text trace, "eval", "if"
215 trace-text trace, "eval", "evaluating first arg"
216 var rest/eax: (addr cell) <- lookup *rest-ah
217 var first-arg-ah/ecx: (addr handle cell) <- get rest, left
218 var guard-h: (handle cell)
219 var guard-ah/esi: (addr handle cell) <- address guard-h
220 debug-print "R", 4/fg, 0/bg
221 increment call-number
222 evaluate first-arg-ah, guard-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
223 debug-print "S", 4/fg, 0/bg
224 rest-ah <- get rest, right
225 rest <- lookup *rest-ah
226 var branch-ah/edi: (addr handle cell) <- get rest, left
227 var guard-a/eax: (addr cell) <- lookup *guard-ah
228 var skip-to-third-arg?/eax: boolean <- nil? guard-a
229 compare skip-to-third-arg?, 0/false
230 {
231 break-if-=
232 trace-text trace, "eval", "skipping to third arg"
233 var rest/eax: (addr cell) <- lookup *rest-ah
234 rest-ah <- get rest, right
235 rest <- lookup *rest-ah
236 branch-ah <- get rest, left
237 }
238 debug-print "T", 4/fg, 0/bg
239 increment call-number
240 evaluate branch-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
241 debug-print "U", 4/fg, 0/bg
242 trace-higher trace
243 return
244 }
245 trace-text trace, "eval", "function call"
246 trace-text trace, "eval", "evaluating list elements"
247 trace-lower trace
248 var evaluated-list-storage: (handle cell)
249 var evaluated-list-ah/esi: (addr handle cell) <- address evaluated-list-storage
250 var curr-out-ah/edx: (addr handle cell) <- copy evaluated-list-ah
251 var curr/ecx: (addr cell) <- copy in-addr
252 $evaluate-list:loop: {
253 allocate-pair curr-out-ah
254 var nil?/eax: boolean <- nil? curr
255 compare nil?, 0/false
256 break-if-!=
257
258 var curr-out/eax: (addr cell) <- lookup *curr-out-ah
259 var left-out-ah/edi: (addr handle cell) <- get curr-out, left
260 var left-ah/esi: (addr handle cell) <- get curr, left
261 debug-print "A", 4/fg, 0/bg
262 increment call-number
263 evaluate left-ah, left-out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
264 debug-print "B", 4/fg, 0/bg
265
266 curr-out-ah <- get curr-out, right
267 var right-ah/eax: (addr handle cell) <- get curr, right
268 var right/eax: (addr cell) <- lookup *right-ah
269 curr <- copy right
270 loop
271 }
272 trace-higher trace
273 var evaluated-list/eax: (addr cell) <- lookup *evaluated-list-ah
274 var function-ah/ecx: (addr handle cell) <- get evaluated-list, left
275 var args-ah/edx: (addr handle cell) <- get evaluated-list, right
276 debug-print "C", 4/fg, 0/bg
277 apply function-ah, args-ah, out, globals, trace, screen-cell, keyboard-cell, call-number
278 debug-print "Y", 4/fg, 0/bg
279 trace-higher trace
280 +-- 11 lines: # trace "=> " out ---------------------------------------------------------------------------------------------------------------------------------------------------------
291 debug-print "Z", 4/fg, 0/bg
292 }
293
294 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 {
295 var f-ah/eax: (addr handle cell) <- copy _f-ah
296 var _f/eax: (addr cell) <- lookup *f-ah
297 var f/esi: (addr cell) <- copy _f
298
299 {
300 var f-type/eax: (addr int) <- get f, type
301 compare *f-type, 4/primitive-function
302 break-if-!=
303 apply-primitive f, args-ah, out, globals, trace
304 return
305 }
306
307 +-- 14 lines: # trace "apply anonymous function " f " in environment " env --------------------------------------------------------------------------------------------------------------
321 trace-lower trace
322 {
323 var f-type/ecx: (addr int) <- get f, type
324 compare *f-type, 0/pair
325 break-if-!=
326 var first-ah/eax: (addr handle cell) <- get f, left
327 var first/eax: (addr cell) <- lookup *first-ah
328 var fn?/eax: boolean <- fn? first
329 compare fn?, 0/false
330 break-if-=
331 var rest-ah/esi: (addr handle cell) <- get f, right
332 var rest/eax: (addr cell) <- lookup *rest-ah
333 var callee-env-ah/edx: (addr handle cell) <- get rest, left
334 rest-ah <- get rest, right
335 rest <- lookup *rest-ah
336 var params-ah/ecx: (addr handle cell) <- get rest, left
337 var body-ah/eax: (addr handle cell) <- get rest, right
338 debug-print "D", 7/fg, 0/bg
339 apply-function params-ah, args-ah, body-ah, out, *callee-env-ah, globals, trace, screen-cell, keyboard-cell, call-number
340 debug-print "Y", 7/fg, 0/bg
341 trace-higher trace
342 return
343 }
344 error trace, "unknown function"
345 }
346
347 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 {
348
349 var new-env-storage: (handle cell)
350 var new-env-ah/esi: (addr handle cell) <- address new-env-storage
351 push-bindings params-ah, args-ah, env-h, new-env-ah, trace
352
353 var body-ah/ecx: (addr handle cell) <- copy _body-ah
354 $apply-function:body: {
355 var body/eax: (addr cell) <- lookup *body-ah
356
357 {
358 var body-nil?/eax: boolean <- nil? body
359 compare body-nil?, 0/false
360 break-if-!= $apply-function:body
361 }
362
363 {
364 var curr-ah/eax: (addr handle cell) <- get body, left
365 debug-print "E", 7/fg, 0/bg
366 increment call-number
367 evaluate curr-ah, out, *new-env-ah, globals, trace, screen-cell, keyboard-cell, call-number
368 debug-print "X", 7/fg, 0/bg
369 }
370
371 body-ah <- get body, right
372 loop
373 }
374
375 }
376
377
378
379
380
381
382
383
384
385
386
387
388 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) {
389 var params-ah/edx: (addr handle cell) <- copy _params-ah
390 var args-ah/ebx: (addr handle cell) <- copy _args-ah
391 var _params/eax: (addr cell) <- lookup *params-ah
392 var params/esi: (addr cell) <- copy _params
393 {
394 var params-nil?/eax: boolean <- nil? params
395 compare params-nil?, 0/false
396 break-if-=
397
398 trace-text trace, "eval", "done with push-bindings"
399 copy-handle old-env-h, env-ah
400 return
401 }
402
403 +-- 16 lines: # trace "pushing bindings from " params " to " args -----------------------------------------------------------------------------------------------------------------------
419 trace-lower trace
420 var params-type/eax: (addr int) <- get params, type
421 compare *params-type, 2/symbol
422 {
423 break-if-!=
424 trace-text trace, "eval", "symbol; binding to all remaining args"
425
426 var new-binding-storage: (handle cell)
427 var new-binding-ah/eax: (addr handle cell) <- address new-binding-storage
428 new-pair new-binding-ah, *params-ah, *args-ah
429
430 new-pair env-ah, *new-binding-ah, old-env-h
431 trace-higher trace
432 return
433 }
434 compare *params-type, 0/pair
435 {
436 break-if-=
437 error trace, "cannot bind a non-symbol"
438 trace-higher trace
439 return
440 }
441 var _args/eax: (addr cell) <- lookup *args-ah
442 var args/edi: (addr cell) <- copy _args
443
444 var args-type/eax: (addr int) <- get args, type
445 compare *args-type, 0/pair
446 {
447 break-if-=
448 error trace, "args not in a proper list"
449 trace-higher trace
450 return
451 }
452 var intermediate-env-storage: (handle cell)
453 var intermediate-env-ah/edx: (addr handle cell) <- address intermediate-env-storage
454 var first-param-ah/eax: (addr handle cell) <- get params, left
455 var first-arg-ah/ecx: (addr handle cell) <- get args, left
456 push-bindings first-param-ah, first-arg-ah, old-env-h, intermediate-env-ah, trace
457 var remaining-params-ah/eax: (addr handle cell) <- get params, right
458 var remaining-args-ah/ecx: (addr handle cell) <- get args, right
459 push-bindings remaining-params-ah, remaining-args-ah, *intermediate-env-ah, env-ah, trace
460 trace-higher trace
461 }
462
463 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) {
464
465 {
466 compare trace, 0
467 break-if-=
468 var stream-storage: (stream byte 0x800)
469 var stream/ecx: (addr stream byte) <- address stream-storage
470 write stream, "look up "
471 var sym2/eax: (addr cell) <- copy sym
472 var sym-data-ah/eax: (addr handle stream byte) <- get sym2, text-data
473 var sym-data/eax: (addr stream byte) <- lookup *sym-data-ah
474 rewind-stream sym-data
475 write-stream stream, sym-data
476 write stream, " in "
477 var env-ah/eax: (addr handle cell) <- address env-h
478 print-cell env-ah, stream, 0/no-trace
479 trace trace, "eval", stream
480 }
481 trace-lower trace
482 var _env/eax: (addr cell) <- lookup env-h
483 var env/ebx: (addr cell) <- copy _env
484
485 {
486 var env-type/ecx: (addr int) <- get env, type
487 compare *env-type, 0/pair
488 break-if-=
489 error trace, "eval found a non-list environment"
490 trace-higher trace
491 return
492 }
493
494 {
495 var env-nil?/eax: boolean <- nil? env
496 compare env-nil?, 0/false
497 break-if-=
498 debug-print "b", 7/fg, 0/bg
499 lookup-symbol-in-globals sym, out, globals, trace, screen-cell, keyboard-cell
500 debug-print "x", 7/fg, 0/bg
501 trace-higher trace
502 +-- 15 lines: # trace "=> " out " (global)" ---------------------------------------------------------------------------------------------------------------------------------------------
517 debug-print "y", 7/fg, 0/bg
518 return
519 }
520
521 var env-head-storage: (handle cell)
522 var env-head-ah/eax: (addr handle cell) <- address env-head-storage
523 car env, env-head-ah, 0/no-trace
524 var _env-head/eax: (addr cell) <- lookup *env-head-ah
525 var env-head/ecx: (addr cell) <- copy _env-head
526
527 {
528 var env-head-type/eax: (addr int) <- get env-head, type
529 compare *env-head-type, 0/pair
530 break-if-=
531 error trace, "environment is not a list of (key . value) pairs"
532 trace-higher trace
533 return
534 }
535
536 var curr-key-storage: (handle cell)
537 var curr-key-ah/eax: (addr handle cell) <- address curr-key-storage
538 car env-head, curr-key-ah, trace
539 var curr-key/eax: (addr cell) <- lookup *curr-key-ah
540
541 {
542 var curr-key-type/eax: (addr int) <- get curr-key, type
543 compare *curr-key-type, 2/symbol
544 break-if-=
545 error trace, "environment contains a binding for a non-symbol"
546 trace-higher trace
547 return
548 }
549
550 var match?/eax: boolean <- cell-isomorphic? curr-key, sym, trace
551 compare match?, 0/false
552 {
553 break-if-=
554 cdr env-head, out, 0/no-trace
555 +-- 15 lines: # trace "=> " out " (match)" ----------------------------------------------------------------------------------------------------------------------------------------------
570 trace-higher trace
571 return
572 }
573
574 var env-tail-storage: (handle cell)
575 var env-tail-ah/eax: (addr handle cell) <- address env-tail-storage
576 cdr env, env-tail-ah, trace
577 lookup-symbol sym, out, *env-tail-ah, globals, trace, screen-cell, keyboard-cell
578 trace-higher trace
579 +-- 15 lines: # trace "=> " out " (recurse)" --------------------------------------------------------------------------------------------------------------------------------------------
594 }
595
596 fn test-lookup-symbol-in-env {
597
598 var val-storage: (handle cell)
599 var val-ah/ecx: (addr handle cell) <- address val-storage
600 new-integer val-ah, 3
601 var key-storage: (handle cell)
602 var key-ah/edx: (addr handle cell) <- address key-storage
603 new-symbol key-ah, "a"
604 var env-storage: (handle cell)
605 var env-ah/ebx: (addr handle cell) <- address env-storage
606 new-pair env-ah, *key-ah, *val-ah
607
608 var nil-storage: (handle cell)
609 var nil-ah/ecx: (addr handle cell) <- address nil-storage
610 allocate-pair nil-ah
611 new-pair env-ah, *env-ah, *nil-ah
612
613 var tmp-storage: (handle cell)
614 var tmp-ah/edx: (addr handle cell) <- address tmp-storage
615 new-symbol tmp-ah, "a"
616 var in/eax: (addr cell) <- lookup *tmp-ah
617 lookup-symbol in, tmp-ah, *env-ah, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard
618 var result/eax: (addr cell) <- lookup *tmp-ah
619 var result-type/edx: (addr int) <- get result, type
620 check-ints-equal *result-type, 1/number, "F - test-lookup-symbol-in-env/0"
621 var result-value-addr/eax: (addr float) <- get result, number-data
622 var result-value/eax: int <- convert *result-value-addr
623 check-ints-equal result-value, 3, "F - test-lookup-symbol-in-env/1"
624 }
625
626 fn test-lookup-symbol-in-globals {
627 var globals-storage: global-table
628 var globals/edi: (addr global-table) <- address globals-storage
629 initialize-globals globals
630
631 var nil-storage: (handle cell)
632 var nil-ah/ecx: (addr handle cell) <- address nil-storage
633 allocate-pair nil-ah
634
635 var tmp-storage: (handle cell)
636 var tmp-ah/ebx: (addr handle cell) <- address tmp-storage
637 new-symbol tmp-ah, "+"
638 var in/eax: (addr cell) <- lookup *tmp-ah
639 lookup-symbol in, tmp-ah, *nil-ah, globals, 0/no-trace, 0/no-screen, 0/no-keyboard
640 var result/eax: (addr cell) <- lookup *tmp-ah
641 var result-type/edx: (addr int) <- get result, type
642 check-ints-equal *result-type, 4/primitive-function, "F - test-lookup-symbol-in-globals/0"
643 var result-value/eax: (addr int) <- get result, index-data
644 check-ints-equal *result-value, 2/add, "F - test-lookup-symbol-in-globals/1"
645 }
646
647 fn car _in: (addr cell), out: (addr handle cell), trace: (addr trace) {
648 trace-text trace, "eval", "car"
649 trace-lower trace
650 var in/eax: (addr cell) <- copy _in
651
652 {
653 var in-type/ecx: (addr int) <- get in, type
654 compare *in-type, 0/pair
655 break-if-=
656 error trace, "car on a non-list"
657 trace-higher trace
658 return
659 }
660
661 {
662 var in-nil?/eax: boolean <- nil? in
663 compare in-nil?, 0/false
664 break-if-=
665 error trace, "car on nil"
666 trace-higher trace
667 return
668 }
669 var in-left/eax: (addr handle cell) <- get in, left
670 copy-object in-left, out
671 trace-higher trace
672 return
673 }
674
675 fn cdr _in: (addr cell), out: (addr handle cell), trace: (addr trace) {
676 trace-text trace, "eval", "cdr"
677 trace-lower trace
678 var in/eax: (addr cell) <- copy _in
679
680 {
681 var in-type/ecx: (addr int) <- get in, type
682 compare *in-type, 0/pair
683 break-if-=
684 error trace, "car on a non-list"
685 trace-higher trace
686 return
687 }
688
689 {
690 var in-nil?/eax: boolean <- nil? in
691 compare in-nil?, 0/false
692 break-if-=
693 error trace, "car on nil"
694 trace-higher trace
695 return
696 }
697 var in-right/eax: (addr handle cell) <- get in, right
698 copy-object in-right, out
699 trace-higher trace
700 return
701 }
702
703 fn cell-isomorphic? _a: (addr cell), _b: (addr cell), trace: (addr trace) -> _/eax: boolean {
704 trace-text trace, "eval", "cell-isomorphic?"
705 trace-lower trace
706 var a/esi: (addr cell) <- copy _a
707 var b/edi: (addr cell) <- copy _b
708
709 var a-type-addr/eax: (addr int) <- get a, type
710 var b-type-addr/ecx: (addr int) <- get b, type
711 var b-type/ecx: int <- copy *b-type-addr
712 compare b-type, *a-type-addr
713 {
714 break-if-=
715 trace-higher trace
716 trace-text trace, "eval", "=> false (type)"
717 return 0/false
718 }
719
720
721 compare b-type, 1/number
722 {
723 break-if-!=
724 var a-val-addr/eax: (addr float) <- get a, number-data
725 var b-val-addr/ecx: (addr float) <- get b, number-data
726 var a-val/xmm0: float <- copy *a-val-addr
727 compare a-val, *b-val-addr
728 {
729 break-if-=
730 trace-higher trace
731 trace-text trace, "eval", "=> false (numbers)"
732 return 0/false
733 }
734 trace-higher trace
735 trace-text trace, "eval", "=> true (numbers)"
736 return 1/true
737 }
738 compare b-type, 2/symbol
739 {
740 break-if-!=
741 var b-val-ah/eax: (addr handle stream byte) <- get b, text-data
742 var _b-val/eax: (addr stream byte) <- lookup *b-val-ah
743 var b-val/ecx: (addr stream byte) <- copy _b-val
744 var a-val-ah/eax: (addr handle stream byte) <- get a, text-data
745 var a-val/eax: (addr stream byte) <- lookup *a-val-ah
746 var tmp-array: (handle array byte)
747 var tmp-ah/edx: (addr handle array byte) <- address tmp-array
748 rewind-stream a-val
749 stream-to-array a-val, tmp-ah
750 var tmp/eax: (addr array byte) <- lookup *tmp-ah
751 var match?/eax: boolean <- stream-data-equal? b-val, tmp
752 trace-higher trace
753 {
754 compare match?, 0/false
755 break-if-=
756 trace-text trace, "eval", "=> true (symbols)"
757 }
758 {
759 compare match?, 0/false
760 break-if-!=
761 trace-text trace, "eval", "=> false (symbols)"
762 }
763 return match?
764 }
765
766 {
767
768 var _b-nil?/eax: boolean <- nil? b
769 var b-nil?/ecx: boolean <- copy _b-nil?
770 var a-nil?/eax: boolean <- nil? a
771
772 {
773 compare a-nil?, 0/false
774 break-if-=
775 compare b-nil?, 0/false
776 break-if-=
777 trace-higher trace
778 trace-text trace, "eval", "=> true (nils)"
779 return 1/true
780 }
781
782 {
783 compare a-nil?, 0/false
784 break-if-=
785 trace-higher trace
786 trace-text trace, "eval", "=> false (b != nil)"
787 return 0/false
788 }
789
790 {
791 compare b-nil?, 0/false
792 break-if-=
793 trace-higher trace
794 trace-text trace, "eval", "=> false (a != nil)"
795 return 0/false
796 }
797 }
798
799 var a-tmp-storage: (handle cell)
800 var a-tmp-ah/edx: (addr handle cell) <- address a-tmp-storage
801 var b-tmp-storage: (handle cell)
802 var b-tmp-ah/ebx: (addr handle cell) <- address b-tmp-storage
803
804 car a, a-tmp-ah, trace
805 car b, b-tmp-ah, trace
806 {
807 var _a-tmp/eax: (addr cell) <- lookup *a-tmp-ah
808 var a-tmp/ecx: (addr cell) <- copy _a-tmp
809 var b-tmp/eax: (addr cell) <- lookup *b-tmp-ah
810 var result/eax: boolean <- cell-isomorphic? a-tmp, b-tmp, trace
811 compare result, 0/false
812 break-if-!=
813 trace-higher trace
814 trace-text trace, "eval", "=> false (car mismatch)"
815 return 0/false
816 }
817
818 cdr a, a-tmp-ah, trace
819 cdr b, b-tmp-ah, trace
820 var _a-tmp/eax: (addr cell) <- lookup *a-tmp-ah
821 var a-tmp/ecx: (addr cell) <- copy _a-tmp
822 var b-tmp/eax: (addr cell) <- lookup *b-tmp-ah
823 var result/eax: boolean <- cell-isomorphic? a-tmp, b-tmp, trace
824 trace-higher trace
825 return result
826 }
827
828 fn fn? _x: (addr cell) -> _/eax: boolean {
829 var x/esi: (addr cell) <- copy _x
830 var type/eax: (addr int) <- get x, type
831 compare *type, 2/symbol
832 {
833 break-if-=
834 return 0/false
835 }
836 var contents-ah/eax: (addr handle stream byte) <- get x, text-data
837 var contents/eax: (addr stream byte) <- lookup *contents-ah
838 var result/eax: boolean <- stream-data-equal? contents, "fn"
839 return result
840 }
841
842 fn test-evaluate-is-well-behaved {
843 var t-storage: trace
844 var t/esi: (addr trace) <- address t-storage
845 initialize-trace t, 0x10, 0/visible
846
847 var env-storage: (handle cell)
848 var env-ah/ecx: (addr handle cell) <- address env-storage
849 allocate-pair env-ah
850
851 var tmp-storage: (handle cell)
852 var tmp-ah/edx: (addr handle cell) <- address tmp-storage
853 new-symbol tmp-ah, "a"
854 evaluate tmp-ah, tmp-ah, *env-ah, 0/no-globals, t, 0/no-screen, 0/no-keyboard, 0/call-number
855
856 check-trace-contains t, "error", "unbound symbol: a", "F - test-evaluate-is-well-behaved"
857 }
858
859 fn test-evaluate-number {
860
861 var env-storage: (handle cell)
862 var env-ah/ecx: (addr handle cell) <- address env-storage
863 allocate-pair env-ah
864
865 var tmp-storage: (handle cell)
866 var tmp-ah/edx: (addr handle cell) <- address tmp-storage
867 new-integer tmp-ah, 3
868 evaluate tmp-ah, tmp-ah, *env-ah, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
869
870 var result/eax: (addr cell) <- lookup *tmp-ah
871 var result-type/edx: (addr int) <- get result, type
872 check-ints-equal *result-type, 1/number, "F - test-evaluate-number/0"
873 var result-value-addr/eax: (addr float) <- get result, number-data
874 var result-value/eax: int <- convert *result-value-addr
875 check-ints-equal result-value, 3, "F - test-evaluate-number/1"
876 }
877
878 fn test-evaluate-symbol {
879
880 var val-storage: (handle cell)
881 var val-ah/ecx: (addr handle cell) <- address val-storage
882 new-integer val-ah, 3
883 var key-storage: (handle cell)
884 var key-ah/edx: (addr handle cell) <- address key-storage
885 new-symbol key-ah, "a"
886 var env-storage: (handle cell)
887 var env-ah/ebx: (addr handle cell) <- address env-storage
888 new-pair env-ah, *key-ah, *val-ah
889
890 var nil-storage: (handle cell)
891 var nil-ah/ecx: (addr handle cell) <- address nil-storage
892 allocate-pair nil-ah
893 new-pair env-ah, *env-ah, *nil-ah
894
895 var tmp-storage: (handle cell)
896 var tmp-ah/edx: (addr handle cell) <- address tmp-storage
897 new-symbol tmp-ah, "a"
898 evaluate tmp-ah, tmp-ah, *env-ah, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
899 var result/eax: (addr cell) <- lookup *tmp-ah
900 var result-type/edx: (addr int) <- get result, type
901 check-ints-equal *result-type, 1/number, "F - test-evaluate-symbol/0"
902 var result-value-addr/eax: (addr float) <- get result, number-data
903 var result-value/eax: int <- convert *result-value-addr
904 check-ints-equal result-value, 3, "F - test-evaluate-symbol/1"
905 }
906
907 fn test-evaluate-primitive-function {
908 var globals-storage: global-table
909 var globals/edi: (addr global-table) <- address globals-storage
910 initialize-globals globals
911 var nil-storage: (handle cell)
912 var nil-ah/ecx: (addr handle cell) <- address nil-storage
913 allocate-pair nil-ah
914 var add-storage: (handle cell)
915 var add-ah/ebx: (addr handle cell) <- address add-storage
916 new-symbol add-ah, "+"
917
918 var tmp-storage: (handle cell)
919 var tmp-ah/esi: (addr handle cell) <- address tmp-storage
920 evaluate add-ah, tmp-ah, *nil-ah, globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
921
922 var result/eax: (addr cell) <- lookup *tmp-ah
923 var result-type/edx: (addr int) <- get result, type
924 check-ints-equal *result-type, 4/primitive-function, "F - test-evaluate-primitive-function/0"
925 var result-value/eax: (addr int) <- get result, index-data
926 check-ints-equal *result-value, 2/add, "F - test-evaluate-primitive-function/1"
927 }
928
929 fn test-evaluate-primitive-function-call {
930 var t-storage: trace
931 var t/edi: (addr trace) <- address t-storage
932 initialize-trace t, 0x100, 0/visible
933
934 var nil-storage: (handle cell)
935 var nil-ah/ecx: (addr handle cell) <- address nil-storage
936 allocate-pair nil-ah
937 var one-storage: (handle cell)
938 var one-ah/edx: (addr handle cell) <- address one-storage
939 new-integer one-ah, 1
940 var add-storage: (handle cell)
941 var add-ah/ebx: (addr handle cell) <- address add-storage
942 new-symbol add-ah, "+"
943
944 var tmp-storage: (handle cell)
945 var tmp-ah/esi: (addr handle cell) <- address tmp-storage
946 new-pair tmp-ah, *one-ah, *nil-ah
947 new-pair tmp-ah, *one-ah, *tmp-ah
948 new-pair tmp-ah, *add-ah, *tmp-ah
949
950
951 var globals-storage: global-table
952 var globals/edx: (addr global-table) <- address globals-storage
953 initialize-globals globals
954
955 evaluate tmp-ah, tmp-ah, *nil-ah, globals, t, 0/no-screen, 0/no-keyboard, 0/call-number
956
957
958 var result/eax: (addr cell) <- lookup *tmp-ah
959 var result-type/edx: (addr int) <- get result, type
960 check-ints-equal *result-type, 1/number, "F - test-evaluate-primitive-function-call/0"
961 var result-value-addr/eax: (addr float) <- get result, number-data
962 var result-value/eax: int <- convert *result-value-addr
963 check-ints-equal result-value, 2, "F - test-evaluate-primitive-function-call/1"
964 }