https://github.com/akkartik/mu/blob/main/baremetal/shell/eval.mu
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 fn evaluate _in: (addr line), end: (addr word), out: (addr value-stack) {
41 clear-value-stack out
42 var line/eax: (addr line) <- copy _in
43 var curr-ah/eax: (addr handle word) <- get line, data
44 var curr/eax: (addr word) <- lookup *curr-ah
45 evaluate-sub curr, end, out, 1/top-level
46 }
47
48 fn evaluate-sub _curr: (addr word), end: (addr word), out: (addr value-stack), top-level?: boolean {
49 var curr/ecx: (addr word) <- copy _curr
50 var curr-stream-storage: (stream byte 0x10)
51 var curr-stream/edi: (addr stream byte) <- address curr-stream-storage
52 $evaluate-sub:loop: {
53
54 compare curr, 0
55 break-if-=
56
57 emit-word curr, curr-stream
58
59
60
61
62
63
64
65
66
67
68 $evaluate-sub:process-word: {
69
70 {
71 var is-add?/eax: boolean <- stream-data-equal? curr-stream, "+"
72 compare is-add?, 0/false
73 break-if-=
74 var _b/xmm0: float <- pop-number-from-value-stack out
75 var b/xmm1: float <- copy _b
76 var a/xmm0: float <- pop-number-from-value-stack out
77 a <- add b
78 push-number-to-value-stack out, a
79 break $evaluate-sub:process-word
80 }
81 {
82 var is-sub?/eax: boolean <- stream-data-equal? curr-stream, "-"
83 compare is-sub?, 0/false
84 break-if-=
85 var _b/xmm0: float <- pop-number-from-value-stack out
86 var b/xmm1: float <- copy _b
87 var a/xmm0: float <- pop-number-from-value-stack out
88 a <- subtract b
89 push-number-to-value-stack out, a
90 break $evaluate-sub:process-word
91 }
92 {
93 var is-mul?/eax: boolean <- stream-data-equal? curr-stream, "*"
94 compare is-mul?, 0/false
95 break-if-=
96 var _b/xmm0: float <- pop-number-from-value-stack out
97 var b/xmm1: float <- copy _b
98 var a/xmm0: float <- pop-number-from-value-stack out
99 a <- multiply b
100 push-number-to-value-stack out, a
101 break $evaluate-sub:process-word
102 }
103 {
104 var is-div?/eax: boolean <- stream-data-equal? curr-stream, "/"
105 compare is-div?, 0/false
106 break-if-=
107 var _b/xmm0: float <- pop-number-from-value-stack out
108 var b/xmm1: float <- copy _b
109 var a/xmm0: float <- pop-number-from-value-stack out
110 a <- divide b
111 push-number-to-value-stack out, a
112 break $evaluate-sub:process-word
113 }
114 {
115 var is-sqrt?/eax: boolean <- stream-data-equal? curr-stream, "sqrt"
116 compare is-sqrt?, 0/false
117 break-if-=
118 var a/xmm0: float <- pop-number-from-value-stack out
119 a <- square-root a
120 push-number-to-value-stack out, a
121 break $evaluate-sub:process-word
122 }
123 {
124 var is-lesser?/eax: boolean <- stream-data-equal? curr-stream, "<"
125 compare is-lesser?, 0/false
126 break-if-=
127 var _b/xmm0: float <- pop-number-from-value-stack out
128 var b/xmm1: float <- copy _b
129 var a/xmm0: float <- pop-number-from-value-stack out
130 compare a, b
131 {
132 break-if-float<
133 push-boolean-to-value-stack out, 0/false
134 break $evaluate-sub:process-word
135 }
136 push-boolean-to-value-stack out, 1/true
137 break $evaluate-sub:process-word
138 }
139 {
140 var is-greater?/eax: boolean <- stream-data-equal? curr-stream, ">"
141 compare is-greater?, 0/false
142 break-if-=
143 var _b/xmm0: float <- pop-number-from-value-stack out
144 var b/xmm1: float <- copy _b
145 var a/xmm0: float <- pop-number-from-value-stack out
146 compare a, b
147 {
148 break-if-float>
149 push-boolean-to-value-stack out, 0/false
150 break $evaluate-sub:process-word
151 }
152 push-boolean-to-value-stack out, 1/true
153 break $evaluate-sub:process-word
154 }
155 {
156 var is-equal?/eax: boolean <- stream-data-equal? curr-stream, "=="
157 compare is-equal?, 0/false
158 break-if-=
159 var _b/xmm0: float <- pop-number-from-value-stack out
160 var b/xmm1: float <- copy _b
161 var a/xmm0: float <- pop-number-from-value-stack out
162 compare a, b
163 {
164 break-if-=
165 push-boolean-to-value-stack out, 0/false
166 break $evaluate-sub:process-word
167 }
168 push-boolean-to-value-stack out, 1/true
169 break $evaluate-sub:process-word
170 }
171
172 {
173 var is-conditional?/eax: boolean <- stream-data-equal? curr-stream, "->"
174 compare is-conditional?, 0/false
175 break-if-=
176 var a/eax: boolean <- pop-boolean-from-value-stack out
177 compare a, 0/false
178 {
179 break-if-!=
180
181 var next-word: (handle word)
182 var next-word-ah/eax: (addr handle word) <- address next-word
183 skip-word curr, end, next-word-ah
184 var _curr/eax: (addr word) <- lookup *next-word-ah
185 curr <- copy _curr
186 }
187 break $evaluate-sub:process-word
188 }
189 {
190 var is-group-start?/eax: boolean <- stream-data-equal? curr-stream, "{"
191 compare is-group-start?, 0/false
192 break-if-=
193
194 compare top-level?, 0/false
195 break-if-= $evaluate-sub:process-word
196 compare curr, end
197 break-if-!= $evaluate-sub:process-word
198 clear-value-stack out
199 break $evaluate-sub:process-word
200 }
201 {
202 var is-group-end?/eax: boolean <- stream-data-equal? curr-stream, "}"
203 compare is-group-end?, 0/false
204 break-if-=
205
206 compare top-level?, 0/false
207 break-if-= $evaluate-sub:process-word
208 compare curr, end
209 break-if-!= $evaluate-sub:process-word
210 clear-value-stack out
211 break $evaluate-sub:process-word
212 }
213 {
214 var is-break?/eax: boolean <- stream-data-equal? curr-stream, "break"
215 compare is-break?, 0/false
216 break-if-=
217
218 var next-word: (handle word)
219 var next-word-ah/eax: (addr handle word) <- address next-word
220 skip-rest-of-group curr, end, next-word-ah
221 var _curr/eax: (addr word) <- lookup *next-word-ah
222 curr <- copy _curr
223 loop $evaluate-sub:loop
224 }
225 {
226 var is-loop?/eax: boolean <- stream-data-equal? curr-stream, "loop"
227 compare is-loop?, 0/false
228 break-if-=
229
230 var open-word: (handle word)
231 var open-word-ah/edx: (addr handle word) <- address open-word
232 scan-to-start-of-group curr, end, open-word-ah
233
234 var close-word: (handle word)
235 var close-word-ah/ebx: (addr handle word) <- address close-word
236 skip-rest-of-group curr, end, close-word-ah
237 var _curr/eax: (addr word) <- lookup *close-word-ah
238 curr <- copy _curr
239
240
241 var open/eax: (addr word) <- lookup *open-word-ah
242 evaluate-sub open, curr, out, 0/nested
243 loop $evaluate-sub:loop
244 }
245
246 {
247 var is-dup?/eax: boolean <- stream-data-equal? curr-stream, "dup"
248 compare is-dup?, 0/false
249 break-if-=
250
251 var out2/esi: (addr value-stack) <- copy out
252 var top-addr/ecx: (addr int) <- get out2, top
253 compare *top-addr, 0
254 break-if-<=
255 var data-ah/eax: (addr handle array value) <- get out2, data
256 var data/eax: (addr array value) <- lookup *data-ah
257 var top/ecx: int <- copy *top-addr
258 top <- decrement
259 var offset/edx: (offset value) <- compute-offset data, top
260 var src-val/edx: (addr value) <- index data, offset
261
262 top <- increment
263 var offset/ebx: (offset value) <- compute-offset data, top
264 var target-val/ebx: (addr value) <- index data, offset
265 copy-object src-val, target-val
266
267 var top-addr/ecx: (addr int) <- get out2, top
268 increment *top-addr
269 break $evaluate-sub:process-word
270 }
271 {
272 var is-swap?/eax: boolean <- stream-data-equal? curr-stream, "swap"
273 compare is-swap?, 0/false
274 break-if-=
275
276 var out2/esi: (addr value-stack) <- copy out
277 var top-addr/ecx: (addr int) <- get out2, top
278 compare *top-addr, 0
279 break-if-<=
280 var data-ah/eax: (addr handle array value) <- get out2, data
281 var data/eax: (addr array value) <- lookup *data-ah
282 var top/ecx: int <- copy *top-addr
283 top <- decrement
284 var offset/edx: (offset value) <- compute-offset data, top
285 var top-val/edx: (addr value) <- index data, offset
286
287 top <- decrement
288 var offset/ebx: (offset value) <- compute-offset data, top
289 var pen-top-val/ebx: (addr value) <- index data, offset
290
291 var tmp: value
292 var tmp-a/eax: (addr value) <- address tmp
293 copy-object top-val, tmp-a
294 copy-object pen-top-val, top-val
295 copy-object tmp-a, pen-top-val
296 break $evaluate-sub:process-word
297 }
298
299 {
300 rewind-stream curr-stream
301 var start/eax: byte <- stream-first curr-stream
302 compare start, 0x22/double-quote
303 break-if-!=
304 var end/eax: byte <- stream-final curr-stream
305 compare end, 0x22/double-quote
306 break-if-!=
307 var h: (handle array byte)
308 var s/eax: (addr handle array byte) <- address h
309 unquote-stream-to-array curr-stream, s
310 push-string-to-value-stack out, *s
311 break $evaluate-sub:process-word
312 }
313
314 {
315 rewind-stream curr-stream
316 var start/eax: byte <- stream-first curr-stream
317 compare start, 0x5b/open-bracket
318 break-if-!=
319 var end/eax: byte <- stream-final curr-stream
320 compare end, 0x5d/close-bracket
321 break-if-!=
322
323 var h: (handle array value)
324 var input-ah/eax: (addr handle array byte) <- address h
325 unquote-stream-to-array curr-stream, input-ah
326
327
328 var input/eax: (addr array byte) <- lookup *input-ah
329 var h2: (handle array int)
330 var int-array-ah/esi: (addr handle array int) <- address h2
331 parse-array-of-decimal-ints input, int-array-ah
332 var _int-array/eax: (addr array int) <- lookup *int-array-ah
333 var int-array/esi: (addr array int) <- copy _int-array
334 var len/ebx: int <- length int-array
335
336 var h3: (handle array value)
337 var value-array-ah/eax: (addr handle array value) <- address h3
338 populate value-array-ah, len
339 push-array-to-value-stack out, *value-array-ah
340
341 var _value-array/eax: (addr array value) <- lookup *value-array-ah
342 var value-array/edi: (addr array value) <- copy _value-array
343 var i/eax: int <- copy 0
344 {
345 compare i, len
346 break-if->=
347 var src-addr/ecx: (addr int) <- index int-array, i
348 var src/ecx: int <- copy *src-addr
349 var src-f/xmm0: float <- convert src
350 var dest-offset/edx: (offset value) <- compute-offset value-array, i
351 var dest-val/edx: (addr value) <- index value-array, dest-offset
352 var dest/edx: (addr float) <- get dest-val, number-data
353 copy-to *dest, src-f
354 i <- increment
355 loop
356 }
357 break $evaluate-sub:process-word
358 }
359
360 {
361 var n/eax: int <- parse-decimal-int-from-stream curr-stream
362 var n-f/xmm0: float <- convert n
363 push-number-to-value-stack out, n-f
364 }
365 }
366
367 compare curr, end
368 break-if-=
369
370 var next-word-ah/edx: (addr handle word) <- get curr, next
371 var _curr/eax: (addr word) <- lookup *next-word-ah
372 curr <- copy _curr
373
374 loop
375 }
376 }
377
378 fn skip-word _curr: (addr word), end: (addr word), out: (addr handle word) {
379 var curr/eax: (addr word) <- copy _curr
380 var bracket-count/ecx: int <- copy 0
381 var result-ah/esi: (addr handle word) <- get curr, next
382 {
383 var result-val/eax: (addr word) <- lookup *result-ah
384 compare result-val, end
385 break-if-=
386 {
387 var open?/eax: boolean <- word-equal? result-val, "{"
388 compare open?, 0/false
389 break-if-=
390 bracket-count <- increment
391 }
392 {
393 var close?/eax: boolean <- word-equal? result-val, "}"
394 compare close?, 0/false
395 break-if-=
396 bracket-count <- decrement
397 compare bracket-count, 0
398 {
399 break-if->=
400 abort "'->' cannot be final word in a {} group"
401 }
402 }
403 compare bracket-count, 0
404 break-if-=
405 result-ah <- get result-val, next
406 loop
407 }
408 copy-object result-ah, out
409 }
410
411 fn skip-rest-of-group _curr: (addr word), end: (addr word), out: (addr handle word) {
412 var curr/eax: (addr word) <- copy _curr
413 var bracket-count/ecx: int <- copy 0
414 var result-ah/esi: (addr handle word) <- get curr, next
415 $skip-rest-of-group:loop: {
416 var result-val/eax: (addr word) <- lookup *result-ah
417 compare result-val, end
418 break-if-=
419 {
420 var open?/eax: boolean <- word-equal? result-val, "{"
421 compare open?, 0/false
422 break-if-=
423 bracket-count <- increment
424 }
425 {
426 var close?/eax: boolean <- word-equal? result-val, "}"
427 compare close?, 0/false
428 break-if-=
429 compare bracket-count, 0
430 break-if-= $skip-rest-of-group:loop
431 bracket-count <- decrement
432 }
433 result-ah <- get result-val, next
434 loop
435 }
436 copy-object result-ah, out
437 }
438
439 fn scan-to-start-of-group _curr: (addr word), end: (addr word), out: (addr handle word) {
440 var curr/eax: (addr word) <- copy _curr
441 var bracket-count/ecx: int <- copy 0
442 var result-ah/esi: (addr handle word) <- get curr, prev
443 $scan-to-start-of-group:loop: {
444 var result-val/eax: (addr word) <- lookup *result-ah
445 compare result-val, end
446 break-if-=
447 {
448 var open?/eax: boolean <- word-equal? result-val, "{"
449 compare open?, 0/false
450 break-if-=
451 compare bracket-count, 0
452 break-if-= $scan-to-start-of-group:loop
453 bracket-count <- increment
454 }
455 {
456 var close?/eax: boolean <- word-equal? result-val, "}"
457 compare close?, 0/false
458 break-if-=
459 bracket-count <- decrement
460 }
461 result-ah <- get result-val, prev
462 loop
463 }
464 copy-object result-ah, out
465 }
466
467 fn test-eval-arithmetic {
468
469 var in-storage: line
470 var in/esi: (addr line) <- address in-storage
471 parse-line "1 1 +", in
472
473 var w-ah/eax: (addr handle word) <- get in, data
474 var end-h: (handle word)
475 var end-ah/ecx: (addr handle word) <- address end-h
476 final-word w-ah, end-ah
477 var end/eax: (addr word) <- lookup *end-ah
478
479 var out-storage: value-stack
480 var out/edi: (addr value-stack) <- address out-storage
481 initialize-value-stack out, 8
482
483 evaluate in, end, out
484
485 var len/eax: int <- value-stack-length out
486 check-ints-equal len, 1, "F - test-eval-arithmetic stack size"
487 var n/xmm0: float <- pop-number-from-value-stack out
488 var n2/eax: int <- convert n
489 check-ints-equal n2, 2, "F - test-eval-arithmetic result"
490 }
491
492 fn test-eval-string {
493
494 var in-storage: line
495 var in/esi: (addr line) <- address in-storage
496 parse-line "\"abc\"", in
497
498 var w-ah/eax: (addr handle word) <- get in, data
499 var end-h: (handle word)
500 var end-ah/ecx: (addr handle word) <- address end-h
501 final-word w-ah, end-ah
502 var end/eax: (addr word) <- lookup *end-ah
503
504 var out-storage: value-stack
505 var out/edi: (addr value-stack) <- address out-storage
506 initialize-value-stack out, 8
507
508 evaluate in, end, out
509
510 var len/eax: int <- value-stack-length out
511 check-ints-equal len, 1, "F - test-eval-string stack size"
512 var out-data-ah/eax: (addr handle array value) <- get out, data
513 var out-data/eax: (addr array value) <- lookup *out-data-ah
514 var v/eax: (addr value) <- index out-data, 0
515 var type/ecx: (addr int) <- get v, type
516 check-ints-equal *type, 1/text, "F - test-eval-string type"
517 var text-ah/eax: (addr handle array byte) <- get v, text-data
518 var text/eax: (addr array byte) <- lookup *text-ah
519 check-strings-equal text, "abc", "F - test-eval-string result"
520 }
521
522 fn test-eval-compare-lesser {
523
524 var in-storage: line
525 var in/esi: (addr line) <- address in-storage
526 parse-line "1 2 <", in
527
528 var w-ah/eax: (addr handle word) <- get in, data
529 var end-h: (handle word)
530 var end-ah/ecx: (addr handle word) <- address end-h
531 final-word w-ah, end-ah
532 var end/eax: (addr word) <- lookup *end-ah
533
534 var out-storage: value-stack
535 var out/edi: (addr value-stack) <- address out-storage
536 initialize-value-stack out, 8
537
538 evaluate in, end, out
539
540 var len/eax: int <- value-stack-length out
541 check-ints-equal len, 1, "F - test-eval-compare-lesser stack size"
542 var result/eax: boolean <- pop-boolean-from-value-stack out
543 check result, "F - test-eval-compare-lesser result"
544 }
545
546 fn test-eval-compare-greater {
547
548 var in-storage: line
549 var in/esi: (addr line) <- address in-storage
550 parse-line "2 1 >", in
551
552 var w-ah/eax: (addr handle word) <- get in, data
553 var end-h: (handle word)
554 var end-ah/ecx: (addr handle word) <- address end-h
555 final-word w-ah, end-ah
556 var end/eax: (addr word) <- lookup *end-ah
557
558 var out-storage: value-stack
559 var out/edi: (addr value-stack) <- address out-storage
560 initialize-value-stack out, 8
561
562 evaluate in, end, out
563
564 var len/eax: int <- value-stack-length out
565 check-ints-equal len, 1, "F - test-eval-compare-greater stack size"
566 var result/eax: boolean <- pop-boolean-from-value-stack out
567 check result, "F - test-eval-compare-greater result"
568 }
569
570 fn test-eval-compare-equal-fails {
571
572 var in-storage: line
573 var in/esi: (addr line) <- address in-storage
574 parse-line "1 2 ==", in
575
576 var w-ah/eax: (addr handle word) <- get in, data
577 var end-h: (handle word)
578 var end-ah/ecx: (addr handle word) <- address end-h
579 final-word w-ah, end-ah
580 var end/eax: (addr word) <- lookup *end-ah
581
582 var out-storage: value-stack
583 var out/edi: (addr value-stack) <- address out-storage
584 initialize-value-stack out, 8
585
586 evaluate in, end, out
587
588 var len/eax: int <- value-stack-length out
589 check-ints-equal len, 1, "F - test-eval-compare-equal-fails stack size"
590 var result/eax: boolean <- pop-boolean-from-value-stack out
591 check-not result, "F - test-eval-compare-equal-fails result"
592 }
593
594 fn test-eval-compare-equal {
595
596 var in-storage: line
597 var in/esi: (addr line) <- address in-storage
598 parse-line "2 2 ==", in
599
600 var w-ah/eax: (addr handle word) <- get in, data
601 var end-h: (handle word)
602 var end-ah/ecx: (addr handle word) <- address end-h
603 final-word w-ah, end-ah
604 var end/eax: (addr word) <- lookup *end-ah
605
606 var out-storage: value-stack
607 var out/edi: (addr value-stack) <- address out-storage
608 initialize-value-stack out, 8
609
610 evaluate in, end, out
611
612 var len/eax: int <- value-stack-length out
613 check-ints-equal len, 1, "F - test-eval-compare-equal stack size"
614 var result/eax: boolean <- pop-boolean-from-value-stack out
615 check result, "F - test-eval-compare-equal result"
616 }
617
618 fn test-eval-conditional {
619
620 var in-storage: line
621 var in/esi: (addr line) <- address in-storage
622 parse-line "1 2 < -> 3", in
623
624 var w-ah/eax: (addr handle word) <- get in, data
625 var end-h: (handle word)
626 var end-ah/ecx: (addr handle word) <- address end-h
627 final-word w-ah, end-ah
628 var end/eax: (addr word) <- lookup *end-ah
629
630 var out-storage: value-stack
631 var out/edi: (addr value-stack) <- address out-storage
632 initialize-value-stack out, 8
633
634 evaluate in, end, out
635
636 var len/eax: int <- value-stack-length out
637 check-ints-equal len, 1, "F - test-eval-conditional stack size"
638 var n/xmm0: float <- pop-number-from-value-stack out
639 var n2/eax: int <- convert n
640 check-ints-equal n2, 3, "F - test-eval-conditional result"
641 }
642
643
644 fn test-eval-conditional-skipped {
645
646 var in-storage: line
647 var in/esi: (addr line) <- address in-storage
648 parse-line "1 2 > -> 3", in
649
650 var w-ah/eax: (addr handle word) <- get in, data
651 var end-h: (handle word)
652 var end-ah/ecx: (addr handle word) <- address end-h
653 final-word w-ah, end-ah
654 var end/eax: (addr word) <- lookup *end-ah
655
656 var out-storage: value-stack
657 var out/edi: (addr value-stack) <- address out-storage
658 initialize-value-stack out, 8
659
660 evaluate in, end, out
661
662 var len/eax: int <- value-stack-length out
663 check-ints-equal len, 0, "F - test-eval-conditional-skipped stack size"
664 }
665
666
667 fn test-eval-group {
668
669 var in-storage: line
670 var in/esi: (addr line) <- address in-storage
671 parse-line "{ 1 } 1 +", in
672
673 var w-ah/eax: (addr handle word) <- get in, data
674 var end-h: (handle word)
675 var end-ah/ecx: (addr handle word) <- address end-h
676 final-word w-ah, end-ah
677 var end/eax: (addr word) <- lookup *end-ah
678
679 var out-storage: value-stack
680 var out/edi: (addr value-stack) <- address out-storage
681 initialize-value-stack out, 8
682
683 evaluate in, end, out
684
685 var len/eax: int <- value-stack-length out
686 check-ints-equal len, 1, "F - test-eval-group stack size"
687 var n/xmm0: float <- pop-number-from-value-stack out
688 var n2/eax: int <- convert n
689 check-ints-equal n2, 2, "F - test-eval-group result"
690 }
691
692 fn test-eval-group-open-at-end {
693
694 var in-storage: line
695 var in/esi: (addr line) <- address in-storage
696 parse-line "1 1 + {", in
697
698 var w-ah/eax: (addr handle word) <- get in, data
699 var end-h: (handle word)
700 var end-ah/ecx: (addr handle word) <- address end-h
701 final-word w-ah, end-ah
702 var end/eax: (addr word) <- lookup *end-ah
703
704 var out-storage: value-stack
705 var out/edi: (addr value-stack) <- address out-storage
706 initialize-value-stack out, 8
707
708 evaluate in, end, out
709
710 var len/eax: int <- value-stack-length out
711 check-ints-equal len, 0, "F - test-eval-group-open-at-end stack size"
712 }
713
714 fn test-eval-group-close-at-end {
715
716 var in-storage: line
717 var in/esi: (addr line) <- address in-storage
718 parse-line "{ 1 1 + }", in
719
720 var w-ah/eax: (addr handle word) <- get in, data
721 var end-h: (handle word)
722 var end-ah/ecx: (addr handle word) <- address end-h
723 final-word w-ah, end-ah
724 var end/eax: (addr word) <- lookup *end-ah
725
726 var out-storage: value-stack
727 var out/edi: (addr value-stack) <- address out-storage
728 initialize-value-stack out, 8
729
730 evaluate in, end, out
731
732 var len/eax: int <- value-stack-length out
733 check-ints-equal len, 0, "F - test-eval-group-close-at-end stack size"
734 }
735
736 fn test-eval-conditional-skips-group {
737
738 var in-storage: line
739 var in/esi: (addr line) <- address in-storage
740 parse-line "1 2 > -> { 3 } 9", in
741
742 var w-ah/eax: (addr handle word) <- get in, data
743 var end-h: (handle word)
744 var end-ah/ecx: (addr handle word) <- address end-h
745 final-word w-ah, end-ah
746 var end/eax: (addr word) <- lookup *end-ah
747
748 var out-storage: value-stack
749 var out/edi: (addr value-stack) <- address out-storage
750 initialize-value-stack out, 8
751
752 evaluate in, end, out
753
754 var len/eax: int <- value-stack-length out
755 check-ints-equal len, 1, "F - test-eval-conditional-skips-group stack size"
756 }
757
758 fn test-eval-conditional-skips-nested-group {
759
760 var in-storage: line
761 var in/esi: (addr line) <- address in-storage
762 parse-line "1 2 > -> { { 3 } 4 } 9", in
763
764 var w-ah/eax: (addr handle word) <- get in, data
765 var end-h: (handle word)
766 var end-ah/ecx: (addr handle word) <- address end-h
767 final-word w-ah, end-ah
768 var end/eax: (addr word) <- lookup *end-ah
769
770 var out-storage: value-stack
771 var out/edi: (addr value-stack) <- address out-storage
772 initialize-value-stack out, 8
773
774 evaluate in, end, out
775
776 var len/eax: int <- value-stack-length out
777 check-ints-equal len, 1, "F - test-eval-conditional-skips-nested-group stack size"
778 }
779
780
781
782
783
784 fn test-eval-break {
785
786 var in-storage: line
787 var in/esi: (addr line) <- address in-storage
788 parse-line "3 { 4 break 5 } +", in
789
790 var w-ah/eax: (addr handle word) <- get in, data
791 var end-h: (handle word)
792 var end-ah/ecx: (addr handle word) <- address end-h
793 final-word w-ah, end-ah
794 var end/eax: (addr word) <- lookup *end-ah
795
796 var out-storage: value-stack
797 var out/edi: (addr value-stack) <- address out-storage
798 initialize-value-stack out, 8
799
800 evaluate in, end, out
801
802 var len/eax: int <- value-stack-length out
803 check-ints-equal len, 1, "F - test-eval-break stack size"
804 var n/xmm0: float <- pop-number-from-value-stack out
805 var n2/eax: int <- convert n
806 check-ints-equal n2, 7, "F - test-eval-break result"
807 }
808
809 fn test-eval-break-nested {
810
811 var in-storage: line
812 var in/esi: (addr line) <- address in-storage
813 parse-line "3 { 4 break { 5 } 6 } +", in
814
815 var w-ah/eax: (addr handle word) <- get in, data
816 var end-h: (handle word)
817 var end-ah/ecx: (addr handle word) <- address end-h
818 final-word w-ah, end-ah
819 var end/eax: (addr word) <- lookup *end-ah
820
821 var out-storage: value-stack
822 var out/edi: (addr value-stack) <- address out-storage
823 initialize-value-stack out, 8
824
825 evaluate in, end, out
826
827 var len/eax: int <- value-stack-length out
828 check-ints-equal len, 1, "F - test-eval-break-nested stack size"
829 var n/xmm0: float <- pop-number-from-value-stack out
830 var n2/eax: int <- convert n
831 check-ints-equal n2, 7, "F - test-eval-break-nested result"
832 }
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851 fn test-eval-loop {
852
853 var in-storage: line
854 var in/esi: (addr line) <- address in-storage
855 parse-line "1 2 4 3 { < -> break loop } 9", in
856
857 var w-ah/eax: (addr handle word) <- get in, data
858 var end-h: (handle word)
859 var end-ah/ecx: (addr handle word) <- address end-h
860 final-word w-ah, end-ah
861 var end/eax: (addr word) <- lookup *end-ah
862
863 var out-storage: value-stack
864 var out/edi: (addr value-stack) <- address out-storage
865 initialize-value-stack out, 8
866
867 evaluate in, end, out
868
869
870 var len/eax: int <- value-stack-length out
871 check-ints-equal len, 1, "F - test-eval-loop stack size"
872 }
873
874 fn test-eval-loop-2 {
875
876 var in-storage: line
877 var in/esi: (addr line) <- address in-storage
878 parse-line "1 2 4 3 { 4 == -> break loop } 9", in
879
880 var w-ah/eax: (addr handle word) <- get in, data
881 var end-h: (handle word)
882 var end-ah/ecx: (addr handle word) <- address end-h
883 final-word w-ah, end-ah
884 var end/eax: (addr word) <- lookup *end-ah
885
886 var out-storage: value-stack
887 var out/edi: (addr value-stack) <- address out-storage
888 initialize-value-stack out, 8
889
890 evaluate in, end, out
891
892
893
894 var len/eax: int <- value-stack-length out
895
896 check-ints-equal len, 3, "F - test-eval-loop-2 stack size"
897 }
898
899 fn test-eval-loop-conditional {
900
901 var in-storage: line
902 var in/esi: (addr line) <- address in-storage
903 parse-line "1 2 3 { 3 == -> loop } 9", in
904
905 var w-ah/eax: (addr handle word) <- get in, data
906 var end-h: (handle word)
907 var end-ah/ecx: (addr handle word) <- address end-h
908 final-word w-ah, end-ah
909 var end/eax: (addr word) <- lookup *end-ah
910
911 var out-storage: value-stack
912 var out/edi: (addr value-stack) <- address out-storage
913 initialize-value-stack out, 8
914
915 evaluate in, end, out
916
917
918
919 var len/eax: int <- value-stack-length out
920
921 check-ints-equal len, 2, "F - test-eval-loop-2-conditional stack size"
922 }
923
924 fn test-eval-loop-with-words-after-in-group {
925
926 var in-storage: line
927 var in/esi: (addr line) <- address in-storage
928 parse-line "1 2 3 { 3 == -> loop 37 } 9", in
929
930 var w-ah/eax: (addr handle word) <- get in, data
931 var end-h: (handle word)
932 var end-ah/ecx: (addr handle word) <- address end-h
933 final-word w-ah, end-ah
934 var end/eax: (addr word) <- lookup *end-ah
935
936 var out-storage: value-stack
937 var out/edi: (addr value-stack) <- address out-storage
938 initialize-value-stack out, 8
939
940 evaluate in, end, out
941
942
943
944 var len/eax: int <- value-stack-length out
945
946 check-ints-equal len, 3, "F - test-eval-loop-with-words-after-in-group stack size"
947 }