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