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 $evaluate:process-word: {
17
18 {
19 var is-add?/eax: boolean <- stream-data-equal? curr-stream, "+"
20 compare is-add?, 0
21 break-if-=
22 var _b/eax: int <- pop-int-from-value-stack out
23 var b/edx: int <- copy _b
24 var a/eax: int <- pop-int-from-value-stack out
25 a <- add b
26 push-int-to-value-stack out, a
27 break $evaluate:process-word
28 }
29 {
30 var is-sub?/eax: boolean <- stream-data-equal? curr-stream, "-"
31 compare is-sub?, 0
32 break-if-=
33 var _b/eax: int <- pop-int-from-value-stack out
34 var b/edx: int <- copy _b
35 var a/eax: int <- pop-int-from-value-stack out
36 a <- subtract b
37 push-int-to-value-stack out, a
38 break $evaluate:process-word
39 }
40 {
41 var is-mul?/eax: boolean <- stream-data-equal? curr-stream, "*"
42 compare is-mul?, 0
43 break-if-=
44 var _b/eax: int <- pop-int-from-value-stack out
45 var b/edx: int <- copy _b
46 var a/eax: int <- pop-int-from-value-stack out
47 a <- multiply b
48 push-int-to-value-stack out, a
49 break $evaluate:process-word
50 }
51 {
52 var is-len?/eax: boolean <- stream-data-equal? curr-stream, "len"
53 compare is-len?, 0
54 break-if-=
55
56
57 var out2/esi: (addr value-stack) <- copy out
58 var top-addr/ecx: (addr int) <- get out2, top
59 compare *top-addr, 0
60 break-if-<=
61
62 var data-ah/eax: (addr handle array value) <- get out2, data
63 var data/eax: (addr array value) <- lookup *data-ah
64 var top/edx: int <- copy *top-addr
65 top <- decrement
66 var dest-offset/edx: (offset value) <- compute-offset data, top
67 var target-val/edx: (addr value) <- index data, dest-offset
68
69 var target-type-addr/eax: (addr int) <- get target-val, type
70 compare *target-type-addr, 1
71 {
72 break-if-!=
73
74 var src-ah/eax: (addr handle array byte) <- get target-val, text-data
75 var src/eax: (addr array byte) <- lookup *src-ah
76 var result/ebx: int <- length src
77
78 var type-addr/eax: (addr int) <- get target-val, type
79 copy-to *type-addr, 0
80 var target-string-ah/eax: (addr handle array byte) <- get target-val, text-data
81 var empty: (handle array byte)
82 copy-handle empty, target-string-ah
83 var target/eax: (addr int) <- get target-val, int-data
84 copy-to *target, result
85 break $evaluate:process-word
86 }
87 compare *target-type-addr, 2
88 {
89 break-if-!=
90
91 var src-ah/eax: (addr handle array value) <- get target-val, array-data
92 var src/eax: (addr array value) <- lookup *src-ah
93 var result/ebx: int <- length src
94
95 var type-addr/eax: (addr int) <- get target-val, type
96 copy-to *type-addr, 0
97 var target-array-ah/eax: (addr handle array value) <- get target-val, array-data
98 var empty: (handle array value)
99 copy-handle empty, target-array-ah
100 var target/eax: (addr int) <- get target-val, int-data
101 copy-to *target, result
102 break $evaluate:process-word
103 }
104 }
105 {
106 var is-open?/eax: boolean <- stream-data-equal? curr-stream, "open"
107 compare is-open?, 0
108 break-if-=
109
110 var out2/esi: (addr value-stack) <- copy out
111 var top-addr/ecx: (addr int) <- get out2, top
112 compare *top-addr, 0
113 break-if-<=
114 var data-ah/eax: (addr handle array value) <- get out2, data
115 var data/eax: (addr array value) <- lookup *data-ah
116 var top/edx: int <- copy *top-addr
117 top <- decrement
118 var dest-offset/edx: (offset value) <- compute-offset data, top
119 var target-val/edx: (addr value) <- index data, dest-offset
120
121 var target-type-addr/eax: (addr int) <- get target-val, type
122 compare *target-type-addr, 1
123 break-if-!=
124
125 var src-ah/eax: (addr handle array byte) <- get target-val, text-data
126 var src/eax: (addr array byte) <- lookup *src-ah
127 var result-ah/ecx: (addr handle buffered-file) <- get target-val, file-data
128 open src, 0, result-ah
129
130 var type-addr/eax: (addr int) <- get target-val, type
131 copy-to *type-addr, 3
132 var target-string-ah/eax: (addr handle array byte) <- get target-val, text-data
133 var empty: (handle array byte)
134 copy-handle empty, target-string-ah
135 break $evaluate:process-word
136 }
137 {
138 var is-read?/eax: boolean <- stream-data-equal? curr-stream, "read"
139 compare is-read?, 0
140 break-if-=
141
142 var out2/esi: (addr value-stack) <- copy out
143 var top-addr/ecx: (addr int) <- get out2, top
144 compare *top-addr, 0
145 break-if-<=
146 var data-ah/eax: (addr handle array value) <- get out2, data
147 var data/eax: (addr array value) <- lookup *data-ah
148 var top/edx: int <- copy *top-addr
149 top <- decrement
150 var dest-offset/edx: (offset value) <- compute-offset data, top
151 var target-val/edx: (addr value) <- index data, dest-offset
152
153 var target-type-addr/eax: (addr int) <- get target-val, type
154 compare *target-type-addr, 3
155 break-if-!=
156
157
158 var file-ah/eax: (addr handle buffered-file) <- get target-val, file-data
159 var file/eax: (addr buffered-file) <- lookup *file-ah
160 var s: (stream byte 0x100)
161 var s-addr/ecx: (addr stream byte) <- address s
162 read-line-buffered file, s-addr
163 var target/eax: (addr handle array byte) <- get target-val, text-data
164 stream-to-array s-addr, target
165
166 var type-addr/eax: (addr int) <- get target-val, type
167 copy-to *type-addr, 1
168 var target-file-ah/eax: (addr handle buffered-file) <- get target-val, file-data
169 var empty: (handle buffered-file)
170 copy-handle empty, target-file-ah
171 break $evaluate:process-word
172 }
173 {
174 var is-slurp?/eax: boolean <- stream-data-equal? curr-stream, "slurp"
175 compare is-slurp?, 0
176 break-if-=
177
178 var out2/esi: (addr value-stack) <- copy out
179 var top-addr/ecx: (addr int) <- get out2, top
180 compare *top-addr, 0
181 break-if-<=
182 var data-ah/eax: (addr handle array value) <- get out2, data
183 var data/eax: (addr array value) <- lookup *data-ah
184 var top/edx: int <- copy *top-addr
185 top <- decrement
186 var dest-offset/edx: (offset value) <- compute-offset data, top
187 var target-val/edx: (addr value) <- index data, dest-offset
188
189 var target-type-addr/eax: (addr int) <- get target-val, type
190 compare *target-type-addr, 3
191 break-if-!=
192
193
194 var file-ah/eax: (addr handle buffered-file) <- get target-val, file-data
195 var file/eax: (addr buffered-file) <- lookup *file-ah
196 var s: (stream byte 0x100)
197 var s-addr/ecx: (addr stream byte) <- address s
198 slurp file, s-addr
199 var target/eax: (addr handle array byte) <- get target-val, text-data
200 stream-to-array s-addr, target
201
202 var type-addr/eax: (addr int) <- get target-val, type
203 copy-to *type-addr, 1
204 var target-file-ah/eax: (addr handle buffered-file) <- get target-val, file-data
205 var empty: (handle buffered-file)
206 copy-handle empty, target-file-ah
207 break $evaluate:process-word
208 }
209 {
210 var is-lines?/eax: boolean <- stream-data-equal? curr-stream, "lines"
211 compare is-lines?, 0
212 break-if-=
213
214 var out2/esi: (addr value-stack) <- copy out
215 var top-addr/ecx: (addr int) <- get out2, top
216 compare *top-addr, 0
217 break-if-<=
218 var data-ah/eax: (addr handle array value) <- get out2, data
219 var data/eax: (addr array value) <- lookup *data-ah
220 var top/edx: int <- copy *top-addr
221 top <- decrement
222 var dest-offset/edx: (offset value) <- compute-offset data, top
223 var target-val/edx: (addr value) <- index data, dest-offset
224
225 var target-type-addr/eax: (addr int) <- get target-val, type
226 compare *target-type-addr, 3
227 break-if-!=
228
229
230 var file-ah/eax: (addr handle buffered-file) <- get target-val, file-data
231 var file/eax: (addr buffered-file) <- lookup *file-ah
232 var s: (stream byte 0x100)
233 var s-addr/ecx: (addr stream byte) <- address s
234 slurp file, s-addr
235 var tmp-ah/eax: (addr handle array byte) <- get target-val, text-data
236 stream-to-array s-addr, tmp-ah
237 var tmp/eax: (addr array byte) <- lookup *tmp-ah
238
239
240 var h: (handle array (handle array byte))
241 {
242 var ah/edx: (addr handle array (handle array byte)) <- address h
243 split-string tmp, 0xa, ah
244 }
245 var target/eax: (addr handle array value) <- get target-val, array-data
246 save-lines h, target
247
248 var type-addr/eax: (addr int) <- get target-val, type
249 copy-to *type-addr, 2
250 var target-file-ah/eax: (addr handle buffered-file) <- get target-val, file-data
251 var empty-file: (handle buffered-file)
252 copy-handle empty-file, target-file-ah
253 var target-text-ah/eax: (addr handle array byte) <- get target-val, text-data
254 var empty-text: (handle array byte)
255 copy-handle empty-text, target-text-ah
256 break $evaluate:process-word
257 }
258
259 {
260 var done?/eax: boolean <- stream-empty? curr-stream
261 compare done?, 0
262 break-if-!=
263 var new-byte/eax: byte <- read-byte curr-stream
264 compare new-byte, 0x3d
265 break-if-!=
266
267 var out2/esi: (addr value-stack) <- copy out
268 var top-addr/ecx: (addr int) <- get out2, top
269 compare *top-addr, 0
270 break-if-<=
271 var data-ah/eax: (addr handle array value) <- get out2, data
272 var data/eax: (addr array value) <- lookup *data-ah
273 var top/edx: int <- copy *top-addr
274 top <- decrement
275 var dest-offset/edx: (offset value) <- compute-offset data, top
276 var target-val/edx: (addr value) <- index data, dest-offset
277
278 var key-h: (handle array byte)
279 var key/ecx: (addr handle array byte) <- address key-h
280 stream-to-array curr-stream, key
281 bind-in-table bindings, key, target-val
282 break $evaluate:process-word
283 }
284 rewind-stream curr-stream
285
286 {
287 var callee-h: (handle function)
288 var callee-ah/eax: (addr handle function) <- address callee-h
289 find-function functions, curr-stream, callee-ah
290 var callee/eax: (addr function) <- lookup *callee-ah
291 compare callee, 0
292 break-if-=
293 perform-call callee, out, functions
294 break $evaluate:process-word
295 }
296
297 {
298 var is-dup?/eax: boolean <- stream-data-equal? curr-stream, "dup"
299 compare is-dup?, 0
300 break-if-=
301
302 var out2/esi: (addr value-stack) <- copy out
303 var top-addr/ecx: (addr int) <- get out2, top
304 compare *top-addr, 0
305 break-if-<=
306 var data-ah/eax: (addr handle array value) <- get out2, data
307 var data/eax: (addr array value) <- lookup *data-ah
308 var top/ecx: int <- copy *top-addr
309 top <- decrement
310 var offset/edx: (offset value) <- compute-offset data, top
311 var src-val/edx: (addr value) <- index data, offset
312
313 top <- increment
314 var offset/ebx: (offset value) <- compute-offset data, top
315 var target-val/ebx: (addr value) <- index data, offset
316 copy-object src-val, target-val
317
318 var top-addr/ecx: (addr int) <- get out2, top
319 increment *top-addr
320 break $evaluate:process-word
321 }
322 {
323 var is-swap?/eax: boolean <- stream-data-equal? curr-stream, "swap"
324 compare is-swap?, 0
325 break-if-=
326
327 var out2/esi: (addr value-stack) <- copy out
328 var top-addr/ecx: (addr int) <- get out2, top
329 compare *top-addr, 0
330 break-if-<=
331 var data-ah/eax: (addr handle array value) <- get out2, data
332 var data/eax: (addr array value) <- lookup *data-ah
333 var top/ecx: int <- copy *top-addr
334 top <- decrement
335 var offset/edx: (offset value) <- compute-offset data, top
336 var top-val/edx: (addr value) <- index data, offset
337
338 top <- decrement
339 var offset/ebx: (offset value) <- compute-offset data, top
340 var pen-top-val/ebx: (addr value) <- index data, offset
341
342 var tmp: value
343 var tmp-a/eax: (addr value) <- address tmp
344 copy-object top-val, tmp-a
345 copy-object pen-top-val, top-val
346 copy-object tmp-a, pen-top-val
347 break $evaluate:process-word
348 }
349
350
351 {
352 compare bindings, 0
353 break-if-=
354 var tmp: (handle array byte)
355 var curr-string-ah/edx: (addr handle array byte) <- address tmp
356 stream-to-array curr-stream, curr-string-ah
357 var curr-string/eax: (addr array byte) <- lookup *curr-string-ah
358 var val-storage: (handle value)
359 var val-ah/edi: (addr handle value) <- address val-storage
360 lookup-binding bindings, curr-string, val-ah
361 var val/eax: (addr value) <- lookup *val-ah
362 compare val, 0
363 break-if-=
364 push-value-stack out, val
365 break $evaluate:process-word
366 }
367
368 {
369 var start/eax: byte <- stream-first curr-stream
370 compare start, 0x22
371 break-if-!=
372 var end/eax: byte <- stream-final curr-stream
373 compare end, 0x22
374 break-if-!=
375 var h: (handle array byte)
376 var s/eax: (addr handle array byte) <- address h
377 unquote-stream-to-array curr-stream, s
378 push-string-to-value-stack out, *s
379 break $evaluate:process-word
380 }
381
382 {
383 var start/eax: byte <- stream-first curr-stream
384 compare start, 0x5b
385 break-if-!=
386 var end/eax: byte <- stream-final curr-stream
387 compare end, 0x5d
388 break-if-!=
389
390 var h: (handle array value)
391 var input-ah/eax: (addr handle array byte) <- address h
392 unquote-stream-to-array curr-stream, input-ah
393
394
395 var input/eax: (addr array byte) <- lookup *input-ah
396 var h2: (handle array int)
397 var int-array-ah/esi: (addr handle array int) <- address h2
398 parse-array-of-decimal-ints input, int-array-ah
399 var _int-array/eax: (addr array int) <- lookup *int-array-ah
400 var int-array/esi: (addr array int) <- copy _int-array
401 var len/ebx: int <- length int-array
402
403 var h3: (handle array value)
404 var value-array-ah/eax: (addr handle array value) <- address h3
405 populate value-array-ah, len
406 push-array-to-value-stack out, *value-array-ah
407
408 var _value-array/eax: (addr array value) <- lookup *value-array-ah
409 var value-array/edi: (addr array value) <- copy _value-array
410 var i/eax: int <- copy 0
411 {
412 compare i, len
413 break-if->=
414 var src-addr/ecx: (addr int) <- index int-array, i
415 var src/ecx: int <- copy *src-addr
416 var dest-offset/edx: (offset value) <- compute-offset value-array, i
417 var dest-val/edx: (addr value) <- index value-array, dest-offset
418 var dest/edx: (addr int) <- get dest-val, int-data
419 copy-to *dest, src
420 i <- increment
421 loop
422 }
423 break $evaluate:process-word
424 }
425
426 {
427 var n/eax: int <- parse-decimal-int-from-stream curr-stream
428 push-int-to-value-stack out, n
429 }
430 }
431
432 compare curr, end
433 break-if-=
434
435 var next-word-ah/edx: (addr handle word) <- get curr, next
436 curr <- lookup *next-word-ah
437
438 loop
439 }
440
441 var line/eax: (addr line) <- copy scratch
442 var next-line-ah/eax: (addr handle line) <- get line, next
443 var next-line/eax: (addr line) <- lookup *next-line-ah
444 compare next-line, 0
445 break-if-=
446 evaluate functions, bindings, next-line, end, out
447 }
448
449 fn test-evaluate {
450 var line-storage: line
451 var line/esi: (addr line) <- address line-storage
452 var first-word-ah/eax: (addr handle word) <- get line-storage, data
453 allocate-word-with first-word-ah, "3"
454 append-word-with *first-word-ah, "=a"
455 var next-line-ah/eax: (addr handle line) <- get line-storage, next
456 allocate next-line-ah
457 var next-line/eax: (addr line) <- lookup *next-line-ah
458 var first-word-ah/eax: (addr handle word) <- get next-line, data
459 allocate-word-with first-word-ah, "a"
460 var functions-storage: (handle function)
461 var functions/ecx: (addr handle function) <- address functions-storage
462 var table-storage: table
463 var table/ebx: (addr table) <- address table-storage
464 initialize-table table, 0x10
465 var stack-storage: value-stack
466 var stack/edi: (addr value-stack) <- address stack-storage
467 initialize-value-stack stack, 0x10
468 evaluate functions, table, line, 0, stack
469 var x/eax: int <- pop-int-from-value-stack stack
470 check-ints-equal x, 3, "F - test-evaluate"
471 }
472
473 fn find-function first: (addr handle function), name: (addr stream byte), out: (addr handle function) {
474 var curr/esi: (addr handle function) <- copy first
475 $find-function:loop: {
476 var _f/eax: (addr function) <- lookup *curr
477 var f/ecx: (addr function) <- copy _f
478 compare f, 0
479 break-if-=
480 var curr-name-ah/eax: (addr handle array byte) <- get f, name
481 var curr-name/eax: (addr array byte) <- lookup *curr-name-ah
482 var done?/eax: boolean <- stream-data-equal? name, curr-name
483 compare done?, 0
484 {
485 break-if-=
486 copy-handle *curr, out
487 break $find-function:loop
488 }
489 curr <- get f, next
490 loop
491 }
492 }
493
494 fn perform-call _callee: (addr function), caller-stack: (addr value-stack), functions: (addr handle function) {
495 var callee/ecx: (addr function) <- copy _callee
496
497 var table-storage: table
498 var table/esi: (addr table) <- address table-storage
499 initialize-table table, 0x10
500 bind-args callee, caller-stack, table
501
502 var body-ah/eax: (addr handle line) <- get callee, body
503 var body/eax: (addr line) <- lookup *body-ah
504
505 var stack-storage: value-stack
506 var stack/edi: (addr value-stack) <- address stack-storage
507 initialize-value-stack stack, 0x10
508
509 evaluate functions, table, body, 0, stack
510
511
512 var top-addr/ecx: (addr int) <- get stack, top
513 compare *top-addr, 0
514 break-if-<=
515 var data-ah/eax: (addr handle array value) <- get stack, data
516 var data/eax: (addr array value) <- lookup *data-ah
517 var top/edx: int <- copy *top-addr
518 top <- decrement
519 var dest-offset/edx: (offset value) <- compute-offset data, top
520 var target-val/edx: (addr value) <- index data, dest-offset
521
522 push-value-stack caller-stack, target-val
523 }
524
525
526
527 fn bind-args _callee: (addr function), _caller-stack: (addr value-stack), table: (addr table) {
528 var callee/ecx: (addr function) <- copy _callee
529 var curr-arg-ah/eax: (addr handle word) <- get callee, args
530 var curr-arg/eax: (addr word) <- lookup *curr-arg-ah
531
532 var curr-key-storage: (handle array byte)
533 var curr-key/edx: (addr handle array byte) <- address curr-key-storage
534 {
535 compare curr-arg, 0
536 break-if-=
537
538 word-to-string curr-arg, curr-key
539 {
540
541 var caller-stack/esi: (addr value-stack) <- copy _caller-stack
542 var top-addr/ecx: (addr int) <- get caller-stack, top
543 compare *top-addr, 0
544 break-if-<=
545 decrement *top-addr
546 var data-ah/eax: (addr handle array value) <- get caller-stack, data
547 var data/eax: (addr array value) <- lookup *data-ah
548 var top/ebx: int <- copy *top-addr
549 var dest-offset/ebx: (offset value) <- compute-offset data, top
550 var target-val/ebx: (addr value) <- index data, dest-offset
551
552 bind-in-table table, curr-key, target-val
553 }
554
555 var next-arg-ah/edx: (addr handle word) <- get curr-arg, next
556 curr-arg <- lookup *next-arg-ah
557 loop
558 }
559 }
560
561
562
563 fn max-stack-depth first-word: (addr word), final-word: (addr word) -> _/edi: int {
564 var curr-word/eax: (addr word) <- copy first-word
565 var curr-depth/ecx: int <- copy 0
566 var result/edi: int <- copy 0
567 $max-stack-depth:loop: {
568 $max-stack-depth:process-word: {
569
570 {
571 var is-add?/eax: boolean <- word-equal? curr-word, "+"
572 compare is-add?, 0
573 break-if-=
574 curr-depth <- decrement
575 break $max-stack-depth:process-word
576 }
577 {
578 var is-sub?/eax: boolean <- word-equal? curr-word, "-"
579 compare is-sub?, 0
580 break-if-=
581 curr-depth <- decrement
582 break $max-stack-depth:process-word
583 }
584 {
585 var is-mul?/eax: boolean <- word-equal? curr-word, "*"
586 compare is-mul?, 0
587 break-if-=
588 curr-depth <- decrement
589 break $max-stack-depth:process-word
590 }
591
592 curr-depth <- increment
593
594 {
595 compare curr-depth, result
596 break-if-<=
597 result <- copy curr-depth
598 }
599 }
600
601 compare curr-word, final-word
602 break-if-=
603
604 var next-word-ah/edx: (addr handle word) <- get curr-word, next
605 curr-word <- lookup *next-word-ah
606
607 loop
608 }
609 return result
610 }