diff options
Diffstat (limited to 'linux/tile/rpn.mu')
-rw-r--r-- | linux/tile/rpn.mu | 911 |
1 files changed, 911 insertions, 0 deletions
diff --git a/linux/tile/rpn.mu b/linux/tile/rpn.mu new file mode 100644 index 00000000..bf81308b --- /dev/null +++ b/linux/tile/rpn.mu @@ -0,0 +1,911 @@ +fn evaluate functions: (addr handle function), bindings: (addr table), scratch: (addr line), end: (addr word), out: (addr value-stack) { + var line/eax: (addr line) <- copy scratch + var word-ah/eax: (addr handle word) <- get line, data + var curr/eax: (addr word) <- lookup *word-ah + var curr-stream-storage: (stream byte 0x10) + var curr-stream/edi: (addr stream byte) <- address curr-stream-storage + clear-value-stack out + $evaluate:loop: { + # precondition (should never hit) + compare curr, 0 + break-if-= + # update curr-stream + emit-word curr, curr-stream +#? print-string-to-real-screen "eval: " +#? print-stream-to-real-screen curr-stream +#? print-string-to-real-screen "\n" + $evaluate:process-word: { + ### if curr-stream is an operator, perform it + ## numbers + { + var is-add?/eax: boolean <- stream-data-equal? curr-stream, "+" + compare is-add?, 0 + break-if-= + var _b/xmm0: float <- pop-number-from-value-stack out + var b/xmm1: float <- copy _b + var a/xmm0: float <- pop-number-from-value-stack out + a <- add b + push-number-to-value-stack out, a + break $evaluate:process-word + } + { + var is-sub?/eax: boolean <- stream-data-equal? curr-stream, "-" + compare is-sub?, 0 + break-if-= + var _b/xmm0: float <- pop-number-from-value-stack out + var b/xmm1: float <- copy _b + var a/xmm0: float <- pop-number-from-value-stack out + a <- subtract b + push-number-to-value-stack out, a + break $evaluate:process-word + } + { + var is-mul?/eax: boolean <- stream-data-equal? curr-stream, "*" + compare is-mul?, 0 + break-if-= + var _b/xmm0: float <- pop-number-from-value-stack out + var b/xmm1: float <- copy _b + var a/xmm0: float <- pop-number-from-value-stack out + a <- multiply b + push-number-to-value-stack out, a + break $evaluate:process-word + } + { + var is-div?/eax: boolean <- stream-data-equal? curr-stream, "/" + compare is-div?, 0 + break-if-= + var _b/xmm0: float <- pop-number-from-value-stack out + var b/xmm1: float <- copy _b + var a/xmm0: float <- pop-number-from-value-stack out + a <- divide b + push-number-to-value-stack out, a + break $evaluate:process-word + } + { + var is-sqrt?/eax: boolean <- stream-data-equal? curr-stream, "sqrt" + compare is-sqrt?, 0 + break-if-= + var a/xmm0: float <- pop-number-from-value-stack out + a <- square-root a + push-number-to-value-stack out, a + break $evaluate:process-word + } + ## strings/arrays + { + var is-len?/eax: boolean <- stream-data-equal? curr-stream, "len" + compare is-len?, 0 + break-if-= +#? print-string 0, "is len\n" + # pop target-val from out + var out2/esi: (addr value-stack) <- copy out + var top-addr/ecx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= +#? print-string 0, "stack has stuff\n" + var data-ah/eax: (addr handle array value) <- get out2, data + var data/eax: (addr array value) <- lookup *data-ah + var top/edx: int <- copy *top-addr + top <- decrement + var dest-offset/edx: (offset value) <- compute-offset data, top + var target-val/edx: (addr value) <- index data, dest-offset + # check target-val is a string or array + var target-type-addr/eax: (addr int) <- get target-val, type + compare *target-type-addr, 1/string + { + break-if-!= + # compute length + var src-ah/eax: (addr handle array byte) <- get target-val, text-data + var src/eax: (addr array byte) <- lookup *src-ah + var result/ebx: int <- length src + var result-f/xmm0: float <- convert result + # save result into target-val + var type-addr/eax: (addr int) <- get target-val, type + copy-to *type-addr, 0/int + var target-string-ah/eax: (addr handle array byte) <- get target-val, text-data + clear-object target-string-ah + var target/eax: (addr float) <- get target-val, number-data + copy-to *target, result-f + break $evaluate:process-word + } + compare *target-type-addr, 2/array + { + break-if-!= + # compute length + var src-ah/eax: (addr handle array value) <- get target-val, array-data + var src/eax: (addr array value) <- lookup *src-ah + var result/ebx: int <- length src + var result-f/xmm0: float <- convert result + # save result into target-val + var type-addr/eax: (addr int) <- get target-val, type + copy-to *type-addr, 0/int + var target-array-ah/eax: (addr handle array value) <- get target-val, array-data + clear-object target-array-ah + var target/eax: (addr float) <- get target-val, number-data + copy-to *target, result-f + break $evaluate:process-word + } + } + ## files + { + var is-open?/eax: boolean <- stream-data-equal? curr-stream, "open" + compare is-open?, 0 + break-if-= + # pop target-val from out + var out2/esi: (addr value-stack) <- copy out + var top-addr/ecx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= + var data-ah/eax: (addr handle array value) <- get out2, data + var data/eax: (addr array value) <- lookup *data-ah + var top/edx: int <- copy *top-addr + top <- decrement + var dest-offset/edx: (offset value) <- compute-offset data, top + var target-val/edx: (addr value) <- index data, dest-offset + # check target-val is a string + var target-type-addr/eax: (addr int) <- get target-val, type + compare *target-type-addr, 1/string + break-if-!= + # open target-val as a filename and save the handle in target-val + var src-ah/eax: (addr handle array byte) <- get target-val, text-data + var src/eax: (addr array byte) <- lookup *src-ah + var result-ah/ecx: (addr handle buffered-file) <- get target-val, file-data + open src, 0, result-ah # write? = false + # save result into target-val + var type-addr/eax: (addr int) <- get target-val, type + copy-to *type-addr, 3/file + var target-string-ah/eax: (addr handle array byte) <- get target-val, text-data + var filename-ah/ecx: (addr handle array byte) <- get target-val, filename + copy-object target-string-ah, filename-ah + clear-object target-string-ah + break $evaluate:process-word + } + { + var is-read?/eax: boolean <- stream-data-equal? curr-stream, "read" + compare is-read?, 0 + break-if-= + # pop target-val from out + var out2/esi: (addr value-stack) <- copy out + var top-addr/ecx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= + var data-ah/eax: (addr handle array value) <- get out2, data + var data/eax: (addr array value) <- lookup *data-ah + var top/edx: int <- copy *top-addr + top <- decrement + var dest-offset/edx: (offset value) <- compute-offset data, top + var target-val/edx: (addr value) <- index data, dest-offset + # check target-val is a file + var target-type-addr/eax: (addr int) <- get target-val, type + compare *target-type-addr, 3/file + break-if-!= + # read a line from the file and save in target-val + # read target-val as a filename and save the handle in target-val + var file-ah/eax: (addr handle buffered-file) <- get target-val, file-data + var file/eax: (addr buffered-file) <- lookup *file-ah + var s: (stream byte 0x100) + var s-addr/ecx: (addr stream byte) <- address s + read-line-buffered file, s-addr + var target/eax: (addr handle array byte) <- get target-val, text-data + stream-to-array s-addr, target + # save result into target-val + var type-addr/eax: (addr int) <- get target-val, type + copy-to *type-addr, 1/string + var target-file-ah/eax: (addr handle buffered-file) <- get target-val, file-data + clear-object target-file-ah + break $evaluate:process-word + } + { + var is-slurp?/eax: boolean <- stream-data-equal? curr-stream, "slurp" + compare is-slurp?, 0 + break-if-= + # pop target-val from out + var out2/esi: (addr value-stack) <- copy out + var top-addr/ecx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= + var data-ah/eax: (addr handle array value) <- get out2, data + var data/eax: (addr array value) <- lookup *data-ah + var top/edx: int <- copy *top-addr + top <- decrement + var dest-offset/edx: (offset value) <- compute-offset data, top + var target-val/edx: (addr value) <- index data, dest-offset + # check target-val is a file + var target-type-addr/eax: (addr int) <- get target-val, type + compare *target-type-addr, 3/file + break-if-!= + # slurp all contents from file and save in target-val + # read target-val as a filename and save the handle in target-val + var file-ah/eax: (addr handle buffered-file) <- get target-val, file-data + var file/eax: (addr buffered-file) <- lookup *file-ah + var s: (stream byte 0x100) + var s-addr/ecx: (addr stream byte) <- address s + slurp file, s-addr + var target/eax: (addr handle array byte) <- get target-val, text-data + stream-to-array s-addr, target + # save result into target-val + var type-addr/eax: (addr int) <- get target-val, type + copy-to *type-addr, 1/string + var target-file-ah/eax: (addr handle buffered-file) <- get target-val, file-data + clear-object target-file-ah + break $evaluate:process-word + } + { + var is-lines?/eax: boolean <- stream-data-equal? curr-stream, "lines" + compare is-lines?, 0 + break-if-= + # pop target-val from out + var out2/esi: (addr value-stack) <- copy out + var top-addr/ecx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= + var data-ah/eax: (addr handle array value) <- get out2, data + var data/eax: (addr array value) <- lookup *data-ah + var top/edx: int <- copy *top-addr + top <- decrement + var dest-offset/edx: (offset value) <- compute-offset data, top + var target-val/edx: (addr value) <- index data, dest-offset + # check target-val is a file + var target-type-addr/eax: (addr int) <- get target-val, type + compare *target-type-addr, 3/file + break-if-!= + # read all lines from file and save as an array of strings in target-val + # read target-val as a filename and save the handle in target-val + var file-ah/eax: (addr handle buffered-file) <- get target-val, file-data + var file/eax: (addr buffered-file) <- lookup *file-ah + var s: (stream byte 0x100) + var s-addr/ecx: (addr stream byte) <- address s + slurp file, s-addr + var tmp-ah/eax: (addr handle array byte) <- get target-val, text-data + stream-to-array s-addr, tmp-ah + var tmp/eax: (addr array byte) <- lookup *tmp-ah +#? enable-screen-type-mode +#? print-string 0, tmp + var h: (handle array (handle array byte)) + { + var ah/edx: (addr handle array (handle array byte)) <- address h + split-string tmp, 0xa, ah + } + var target/eax: (addr handle array value) <- get target-val, array-data + save-lines h, target + # save result into target-val + var type-addr/eax: (addr int) <- get target-val, type + copy-to *type-addr, 2/array + var target-file-ah/eax: (addr handle buffered-file) <- get target-val, file-data + var empty-file: (handle buffered-file) + copy-handle empty-file, target-file-ah + var target-text-ah/eax: (addr handle array byte) <- get target-val, text-data + var empty-text: (handle array byte) + copy-handle empty-text, target-text-ah + break $evaluate:process-word + } + ## screens + { + var is-fake-screen?/eax: boolean <- stream-data-equal? curr-stream, "fake-screen" + compare is-fake-screen?, 0 + break-if-= + var out2/esi: (addr value-stack) <- copy out + var top-addr/ecx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= + # pop width and height from out + var nrows-f/xmm0: float <- pop-number-from-value-stack out2 + var nrows/edx: int <- convert nrows-f + var ncols-f/xmm0: float <- pop-number-from-value-stack out2 + var ncols/ebx: int <- convert ncols-f + # define a new screen with those dimensions + var screen-h: (handle screen) + var screen-ah/eax: (addr handle screen) <- address screen-h + allocate screen-ah + var screen/eax: (addr screen) <- lookup screen-h + initialize-screen screen, nrows, ncols + # push screen to stack + var data-ah/eax: (addr handle array value) <- get out2, data + var data/eax: (addr array value) <- lookup *data-ah + var top/edx: int <- copy *top-addr + increment *top-addr + var dest-offset/edx: (offset value) <- compute-offset data, top + var target-val/edx: (addr value) <- index data, dest-offset + var type/eax: (addr int) <- get target-val, type + copy-to *type, 4/screen + var dest/eax: (addr handle screen) <- get target-val, screen-data + copy-handle screen-h, dest + break $evaluate:process-word + } + { + var is-print?/eax: boolean <- stream-data-equal? curr-stream, "print" + compare is-print?, 0 + break-if-= + var out2/esi: (addr value-stack) <- copy out + var top-addr/ecx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= + # pop string from out + var top-addr/ecx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= + decrement *top-addr + var data-ah/eax: (addr handle array value) <- get out2, data + var _data/eax: (addr array value) <- lookup *data-ah + var data/edi: (addr array value) <- copy _data + var top/eax: int <- copy *top-addr + var dest-offset/edx: (offset value) <- compute-offset data, top + var s/esi: (addr value) <- index data, dest-offset + # select target screen from top of out (but don't pop it) + compare *top-addr, 0 + break-if-<= + var top/eax: int <- copy *top-addr + top <- decrement + var dest-offset/edx: (offset value) <- compute-offset data, top + var target-val/edx: (addr value) <- index data, dest-offset + var type/eax: (addr int) <- get target-val, type + compare *type, 4/screen + break-if-!= + # print string to target screen + var dest-ah/eax: (addr handle screen) <- get target-val, screen-data + var dest/eax: (addr screen) <- lookup *dest-ah + var r/ecx: (addr int) <- get dest, cursor-row + var c/edx: (addr int) <- get dest, cursor-col + render-value-at dest, *r, *c, s, 0 + break $evaluate:process-word + } + { + var is-move?/eax: boolean <- stream-data-equal? curr-stream, "move" + compare is-move?, 0 + break-if-= + var out2/esi: (addr value-stack) <- copy out + # pop args + var r-f/xmm0: float <- pop-number-from-value-stack out2 + var r/ecx: int <- convert r-f + var c-f/xmm0: float <- pop-number-from-value-stack out2 + var c/edx: int <- convert c-f + # select screen from top of out (but don't pop it) + var top-addr/ebx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= + var data-ah/eax: (addr handle array value) <- get out2, data + var _data/eax: (addr array value) <- lookup *data-ah + var data/edi: (addr array value) <- copy _data + var top/eax: int <- copy *top-addr + top <- decrement + var target-offset/eax: (offset value) <- compute-offset data, top + var target-val/ebx: (addr value) <- index data, target-offset + var type/eax: (addr int) <- get target-val, type + compare *type, 4/screen + break-if-!= + var target-ah/eax: (addr handle screen) <- get target-val, screen-data + var target/eax: (addr screen) <- lookup *target-ah + move-cursor target, r, c + break $evaluate:process-word + } + { + var is-up?/eax: boolean <- stream-data-equal? curr-stream, "up" + compare is-up?, 0 + break-if-= + var out2/esi: (addr value-stack) <- copy out + var top-addr/ebx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= + # pop args + var d-f/xmm0: float <- pop-number-from-value-stack out2 + var d/ecx: int <- convert d-f + # select screen from top of out (but don't pop it) + compare *top-addr, 0 + break-if-<= + var data-ah/eax: (addr handle array value) <- get out2, data + var _data/eax: (addr array value) <- lookup *data-ah + var data/edi: (addr array value) <- copy _data + var top/eax: int <- copy *top-addr + top <- decrement + var target-offset/eax: (offset value) <- compute-offset data, top + var target-val/ebx: (addr value) <- index data, target-offset + var type/eax: (addr int) <- get target-val, type + compare *type, 4/screen + break-if-!= + var target-ah/eax: (addr handle screen) <- get target-val, screen-data + var _target/eax: (addr screen) <- lookup *target-ah + var target/edi: (addr screen) <- copy _target + var r/edx: (addr int) <- get target, cursor-row + var c/eax: (addr int) <- get target, cursor-col + var col/eax: int <- copy *c + { + compare d, 0 + break-if-<= + compare *r, 1 + break-if-<= + print-string target "│" + decrement *r + move-cursor target, *r, col + d <- decrement + loop + } + break $evaluate:process-word + } + { + var is-down?/eax: boolean <- stream-data-equal? curr-stream, "down" + compare is-down?, 0 + break-if-= + var out2/esi: (addr value-stack) <- copy out + var top-addr/ebx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= + # pop args + var d-f/xmm0: float <- pop-number-from-value-stack out2 + var d/ecx: int <- convert d-f + # select screen from top of out (but don't pop it) + compare *top-addr, 0 + break-if-<= + var data-ah/eax: (addr handle array value) <- get out2, data + var _data/eax: (addr array value) <- lookup *data-ah + var data/edi: (addr array value) <- copy _data + var top/eax: int <- copy *top-addr + top <- decrement + var target-offset/eax: (offset value) <- compute-offset data, top + var target-val/ebx: (addr value) <- index data, target-offset + var type/eax: (addr int) <- get target-val, type + compare *type, 4/screen + break-if-!= + var target-ah/eax: (addr handle screen) <- get target-val, screen-data + var _target/eax: (addr screen) <- lookup *target-ah + var target/edi: (addr screen) <- copy _target + var bound-a/ebx: (addr int) <- get target, num-rows + var bound/ebx: int <- copy *bound-a + var r/edx: (addr int) <- get target, cursor-row + var c/eax: (addr int) <- get target, cursor-col + var col/eax: int <- copy *c + { + compare d, 0 + break-if-<= + compare *r, bound + break-if->= + print-string target "│" + increment *r + move-cursor target, *r, col + d <- decrement + loop + } + break $evaluate:process-word + } + { + var is-left?/eax: boolean <- stream-data-equal? curr-stream, "left" + compare is-left?, 0 + break-if-= + var out2/esi: (addr value-stack) <- copy out + var top-addr/ebx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= + # pop args + var d-f/xmm0: float <- pop-number-from-value-stack out2 + var d/ecx: int <- convert d-f + # select screen from top of out (but don't pop it) + compare *top-addr, 0 + break-if-<= + var data-ah/eax: (addr handle array value) <- get out2, data + var _data/eax: (addr array value) <- lookup *data-ah + var data/edi: (addr array value) <- copy _data + var top/eax: int <- copy *top-addr + top <- decrement + var target-offset/eax: (offset value) <- compute-offset data, top + var target-val/ebx: (addr value) <- index data, target-offset + var type/eax: (addr int) <- get target-val, type + compare *type, 4/screen + break-if-!= + var target-ah/eax: (addr handle screen) <- get target-val, screen-data + var _target/eax: (addr screen) <- lookup *target-ah + var target/edi: (addr screen) <- copy _target + var c/edx: (addr int) <- get target, cursor-col + var r/eax: (addr int) <- get target, cursor-row + var row/eax: int <- copy *r + { + compare d, 0 + break-if-<= + compare *c, 1 + break-if-<= + print-string target "─" + decrement *c + decrement *c # second one to undo the print above + move-cursor target, row, *c + d <- decrement + loop + } + break $evaluate:process-word + } + { + var is-right?/eax: boolean <- stream-data-equal? curr-stream, "right" + compare is-right?, 0 + break-if-= + var out2/esi: (addr value-stack) <- copy out + var top-addr/ebx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= + # pop args + var _d/xmm0: float <- pop-number-from-value-stack out2 + var d/ecx: int <- convert _d + # select screen from top of out (but don't pop it) + compare *top-addr, 0 + break-if-<= + var data-ah/eax: (addr handle array value) <- get out2, data + var _data/eax: (addr array value) <- lookup *data-ah + var data/edi: (addr array value) <- copy _data + var top/eax: int <- copy *top-addr + top <- decrement + var target-offset/eax: (offset value) <- compute-offset data, top + var target-val/ebx: (addr value) <- index data, target-offset + var type/eax: (addr int) <- get target-val, type + compare *type, 4/screen + break-if-!= + var target-ah/eax: (addr handle screen) <- get target-val, screen-data + var _target/eax: (addr screen) <- lookup *target-ah + var target/edi: (addr screen) <- copy _target + var bound-a/ebx: (addr int) <- get target, num-rows + var bound/ebx: int <- copy *bound-a + var c/edx: (addr int) <- get target, cursor-col + var r/eax: (addr int) <- get target, cursor-row + var row/eax: int <- copy *r + { + compare d, 0 + break-if-<= + compare *c, bound + break-if->= + print-string target "─" + # no increment; the print took care of it + move-cursor target, row, *c + d <- decrement + loop + } + break $evaluate:process-word + } + ## HACKS: we're trying to avoid turning this into Forth + { + var is-dup?/eax: boolean <- stream-data-equal? curr-stream, "dup" + compare is-dup?, 0 + break-if-= + # read src-val from out + var out2/esi: (addr value-stack) <- copy out + var top-addr/ecx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= + var data-ah/eax: (addr handle array value) <- get out2, data + var data/eax: (addr array value) <- lookup *data-ah + var top/ecx: int <- copy *top-addr + top <- decrement + var offset/edx: (offset value) <- compute-offset data, top + var src-val/edx: (addr value) <- index data, offset + # push a copy of it + top <- increment + var offset/ebx: (offset value) <- compute-offset data, top + var target-val/ebx: (addr value) <- index data, offset + copy-object src-val, target-val + # commit + var top-addr/ecx: (addr int) <- get out2, top + increment *top-addr + break $evaluate:process-word + } + { + var is-swap?/eax: boolean <- stream-data-equal? curr-stream, "swap" + compare is-swap?, 0 + break-if-= + # read top-val from out + var out2/esi: (addr value-stack) <- copy out + var top-addr/ecx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= + var data-ah/eax: (addr handle array value) <- get out2, data + var data/eax: (addr array value) <- lookup *data-ah + var top/ecx: int <- copy *top-addr + top <- decrement + var offset/edx: (offset value) <- compute-offset data, top + var top-val/edx: (addr value) <- index data, offset + # read next val from out + top <- decrement + var offset/ebx: (offset value) <- compute-offset data, top + var pen-top-val/ebx: (addr value) <- index data, offset + # swap + var tmp: value + var tmp-a/eax: (addr value) <- address tmp + copy-object top-val, tmp-a + copy-object pen-top-val, top-val + copy-object tmp-a, pen-top-val + break $evaluate:process-word + } + ### if curr-stream defines a binding, save top of stack to bindings + { + var done?/eax: boolean <- stream-empty? curr-stream + compare done?, 0/false + break-if-!= + var new-byte/eax: byte <- read-byte curr-stream + compare new-byte, 0x3d/= + break-if-!= + # pop target-val from out + var out2/esi: (addr value-stack) <- copy out + var top-addr/ecx: (addr int) <- get out2, top + compare *top-addr, 0 + break-if-<= + var data-ah/eax: (addr handle array value) <- get out2, data + var data/eax: (addr array value) <- lookup *data-ah + var top/edx: int <- copy *top-addr + top <- decrement + var dest-offset/edx: (offset value) <- compute-offset data, top + var target-val/edx: (addr value) <- index data, dest-offset + # create binding from curr-stream to target-val + var key-h: (handle array byte) + var key/ecx: (addr handle array byte) <- address key-h + stream-to-array curr-stream, key + bind-in-table bindings, key, target-val + break $evaluate:process-word + } + rewind-stream curr-stream + ### if curr-stream is a known function name, call it appropriately + { + var callee-h: (handle function) + var callee-ah/eax: (addr handle function) <- address callee-h + find-function functions, curr-stream, callee-ah + var callee/eax: (addr function) <- lookup *callee-ah + compare callee, 0 + break-if-= + perform-call callee, out, functions + break $evaluate:process-word + } + ### if it's a name, push its value + { + compare bindings, 0 + break-if-= + var tmp: (handle array byte) + var curr-string-ah/edx: (addr handle array byte) <- address tmp + stream-to-array curr-stream, curr-string-ah # unfortunate leak + var curr-string/eax: (addr array byte) <- lookup *curr-string-ah + var val-storage: (handle value) + var val-ah/edi: (addr handle value) <- address val-storage + lookup-binding bindings, curr-string, val-ah + var val/eax: (addr value) <- lookup *val-ah + compare val, 0 + break-if-= + push-value-stack out, val + break $evaluate:process-word + } + ### if the word starts with a quote and ends with a quote, turn it into a string + { + var start/eax: byte <- stream-first curr-stream + compare start, 0x22/double-quote + break-if-!= + var end/eax: byte <- stream-final curr-stream + compare end, 0x22/double-quote + break-if-!= + var h: (handle array byte) + var s/eax: (addr handle array byte) <- address h + unquote-stream-to-array curr-stream, s # leak + push-string-to-value-stack out, *s + break $evaluate:process-word + } + ### if the word starts with a '[' and ends with a ']', turn it into an array + { + var start/eax: byte <- stream-first curr-stream + compare start, 0x5b/[ + break-if-!= + var end/eax: byte <- stream-final curr-stream + compare end, 0x5d/] + break-if-!= + # wastefully create a new input string to strip quotes + var h: (handle array value) + var input-ah/eax: (addr handle array byte) <- address h + unquote-stream-to-array curr-stream, input-ah # leak + # wastefully parse input into int-array + # TODO: support parsing arrays of other types + var input/eax: (addr array byte) <- lookup *input-ah + var h2: (handle array int) + var int-array-ah/esi: (addr handle array int) <- address h2 + parse-array-of-decimal-ints input, int-array-ah # leak + var _int-array/eax: (addr array int) <- lookup *int-array-ah + var int-array/esi: (addr array int) <- copy _int-array + var len/ebx: int <- length int-array + # push value-array of same size as int-array + var h3: (handle array value) + var value-array-ah/eax: (addr handle array value) <- address h3 + populate value-array-ah, len + push-array-to-value-stack out, *value-array-ah + # copy int-array into value-array + var _value-array/eax: (addr array value) <- lookup *value-array-ah + var value-array/edi: (addr array value) <- copy _value-array + var i/eax: int <- copy 0 + { + compare i, len + break-if->= + var src-addr/ecx: (addr int) <- index int-array, i + var src/ecx: int <- copy *src-addr + var src-f/xmm0: float <- convert src + var dest-offset/edx: (offset value) <- compute-offset value-array, i + var dest-val/edx: (addr value) <- index value-array, dest-offset + var dest/edx: (addr float) <- get dest-val, number-data + copy-to *dest, src-f + i <- increment + loop + } + break $evaluate:process-word + } + ### otherwise assume it's a literal number and push it + { + var n/eax: int <- parse-decimal-int-from-stream curr-stream + var n-f/xmm0: float <- convert n + push-number-to-value-stack out, n-f + } + } + # termination check + compare curr, end + break-if-= + # update + var next-word-ah/edx: (addr handle word) <- get curr, next + curr <- lookup *next-word-ah + # + loop + } + # process next line if necessary + var line/eax: (addr line) <- copy scratch + var next-line-ah/eax: (addr handle line) <- get line, next + var next-line/eax: (addr line) <- lookup *next-line-ah + compare next-line, 0 + break-if-= + evaluate functions, bindings, next-line, end, out +} + +fn test-evaluate { + var line-storage: line + var line/esi: (addr line) <- address line-storage + var first-word-ah/eax: (addr handle word) <- get line-storage, data + allocate-word-with first-word-ah, "3" + append-word-with *first-word-ah, "=a" + var next-line-ah/eax: (addr handle line) <- get line-storage, next + allocate next-line-ah + var next-line/eax: (addr line) <- lookup *next-line-ah + var first-word-ah/eax: (addr handle word) <- get next-line, data + allocate-word-with first-word-ah, "a" + var functions-storage: (handle function) + var functions/ecx: (addr handle function) <- address functions-storage + var table-storage: table + var table/ebx: (addr table) <- address table-storage + initialize-table table, 0x10 + var stack-storage: value-stack + var stack/edi: (addr value-stack) <- address stack-storage + initialize-value-stack stack, 0x10 + evaluate functions, table, line, 0, stack + var x-f/xmm0: float <- pop-number-from-value-stack stack + var x/eax: int <- convert x-f + check-ints-equal x, 3, "F - test-evaluate" +} + +fn find-function first: (addr handle function), name: (addr stream byte), out: (addr handle function) { + var curr/esi: (addr handle function) <- copy first + $find-function:loop: { + var _f/eax: (addr function) <- lookup *curr + var f/ecx: (addr function) <- copy _f + compare f, 0 + break-if-= + var curr-name-ah/eax: (addr handle array byte) <- get f, name + var curr-name/eax: (addr array byte) <- lookup *curr-name-ah + var done?/eax: boolean <- stream-data-equal? name, curr-name + compare done?, 0/false + { + break-if-= + copy-handle *curr, out + break $find-function:loop + } + curr <- get f, next + loop + } +} + +fn perform-call _callee: (addr function), caller-stack: (addr value-stack), functions: (addr handle function) { + var callee/ecx: (addr function) <- copy _callee + # create bindings for args + var table-storage: table + var table/esi: (addr table) <- address table-storage + initialize-table table, 0x10 + bind-args callee, caller-stack, table + # obtain body + var body-ah/eax: (addr handle line) <- get callee, body + var body/eax: (addr line) <- lookup *body-ah + # perform call + var stack-storage: value-stack + var stack/edi: (addr value-stack) <- address stack-storage + initialize-value-stack stack, 0x10 +#? print-string-to-real-screen "about to enter recursive eval\n" + evaluate functions, table, body, 0, stack +#? print-string-to-real-screen "exited recursive eval\n" + # pop target-val from out + var top-addr/ecx: (addr int) <- get stack, top + compare *top-addr, 0 + break-if-<= + var data-ah/eax: (addr handle array value) <- get stack, data + var data/eax: (addr array value) <- lookup *data-ah + var top/edx: int <- copy *top-addr + top <- decrement + var dest-offset/edx: (offset value) <- compute-offset data, top + var target-val/edx: (addr value) <- index data, dest-offset + # stitch target-val into caller-stack + push-value-stack caller-stack, target-val +} + +# pop args from the caller-stack and bind them to successive args +# implies: function args are stored in reverse order +fn bind-args _callee: (addr function), _caller-stack: (addr value-stack), table: (addr table) { + var callee/ecx: (addr function) <- copy _callee + var curr-arg-ah/eax: (addr handle word) <- get callee, args + var curr-arg/eax: (addr word) <- lookup *curr-arg-ah + # + var curr-key-storage: (handle array byte) + var curr-key/edx: (addr handle array byte) <- address curr-key-storage + { + compare curr-arg, 0 + break-if-= + # create binding + word-to-string curr-arg, curr-key + { + # pop target-val from caller-stack + var caller-stack/esi: (addr value-stack) <- copy _caller-stack + var top-addr/ecx: (addr int) <- get caller-stack, top + compare *top-addr, 0 + break-if-<= + decrement *top-addr + var data-ah/eax: (addr handle array value) <- get caller-stack, data + var data/eax: (addr array value) <- lookup *data-ah + var top/ebx: int <- copy *top-addr + var dest-offset/ebx: (offset value) <- compute-offset data, top + var target-val/ebx: (addr value) <- index data, dest-offset + # create binding from curr-key to target-val + bind-in-table table, curr-key, target-val + } + # + var next-arg-ah/edx: (addr handle word) <- get curr-arg, next + curr-arg <- lookup *next-arg-ah + loop + } +} + +# Copy of 'simplify' that just tracks the maximum stack depth needed +# Doesn't actually need to simulate the stack, since every word has a predictable effect. +fn max-stack-depth first-word: (addr word), final-word: (addr word) -> _/edi: int { + var curr-word/eax: (addr word) <- copy first-word + var curr-depth/ecx: int <- copy 0 + var result/edi: int <- copy 0 + $max-stack-depth:loop: { + $max-stack-depth:process-word: { + # handle operators + { + var is-add?/eax: boolean <- word-equal? curr-word, "+" + compare is-add?, 0 + break-if-= + curr-depth <- decrement + break $max-stack-depth:process-word + } + { + var is-sub?/eax: boolean <- word-equal? curr-word, "-" + compare is-sub?, 0 + break-if-= + curr-depth <- decrement + break $max-stack-depth:process-word + } + { + var is-mul?/eax: boolean <- word-equal? curr-word, "*" + compare is-mul?, 0 + break-if-= + curr-depth <- decrement + break $max-stack-depth:process-word + } + # otherwise it's an int (do we need error-checking?) + curr-depth <- increment + # update max depth if necessary + { + compare curr-depth, result + break-if-<= + result <- copy curr-depth + } + } + # if curr-word == final-word break + compare curr-word, final-word + break-if-= + # curr-word = curr-word->next + var next-word-ah/edx: (addr handle word) <- get curr-word, next + curr-word <- lookup *next-word-ah + # + loop + } + return result +} |