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