From 2c56af2d8f791902f5ff59754c0277eddeb27a3e Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Wed, 11 Nov 2020 23:43:04 -0800 Subject: 7227 --- html/apps/tile/rpn.mu.html | 1469 ++++++++++++++++++++++++++------------------ 1 file changed, 875 insertions(+), 594 deletions(-) (limited to 'html/apps/tile/rpn.mu.html') diff --git a/html/apps/tile/rpn.mu.html b/html/apps/tile/rpn.mu.html index 54af3e40..c67a5d75 100644 --- a/html/apps/tile/rpn.mu.html +++ b/html/apps/tile/rpn.mu.html @@ -71,603 +71,884 @@ if ('onhashchange' in window) { 11 break-if-= 12 # update curr-stream 13 emit-word curr, curr-stream - 14 #? print-stream-to-real-screen curr-stream - 15 #? print-string-to-real-screen "\n" - 16 $evaluate:process-word: { - 17 # if curr-stream is an operator, perform it - 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 #? print-string 0, "is len\n" - 56 # pop target-val from out - 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 #? print-string 0, "stack has stuff\n" - 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 # check target-val is a string or array - 69 var target-type-addr/eax: (addr int) <- get target-val, type - 70 compare *target-type-addr, 1 # string - 71 { - 72 break-if-!= - 73 # compute length - 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 # save result into target-val - 78 var type-addr/eax: (addr int) <- get target-val, type - 79 copy-to *type-addr, 0 # int - 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 # array of ints - 88 { - 89 break-if-!= - 90 # compute length - 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 # save result into target-val - 95 var type-addr/eax: (addr int) <- get target-val, type - 96 copy-to *type-addr, 0 # int - 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 # pop target-val from out -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 # check target-val is a string -121 var target-type-addr/eax: (addr int) <- get target-val, type -122 compare *target-type-addr, 1 # string -123 break-if-!= -124 # open target-val as a filename and save the handle in target-val -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 # write? = false -129 # save result into target-val -130 var type-addr/eax: (addr int) <- get target-val, type -131 copy-to *type-addr, 3 # file -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 # pop target-val from out -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 # check target-val is a file -153 var target-type-addr/eax: (addr int) <- get target-val, type -154 compare *target-type-addr, 3 # file -155 break-if-!= -156 # read a line from the file and save in target-val -157 # read target-val as a filename and save the handle in target-val -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 # save result into target-val -166 var type-addr/eax: (addr int) <- get target-val, type -167 copy-to *type-addr, 1 # string -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 # pop target-val from out -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 # check target-val is a file -189 var target-type-addr/eax: (addr int) <- get target-val, type -190 compare *target-type-addr, 3 # file -191 break-if-!= -192 # slurp all contents from file and save in target-val -193 # read target-val as a filename and save the handle in target-val -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 # save result into target-val -202 var type-addr/eax: (addr int) <- get target-val, type -203 copy-to *type-addr, 1 # string -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 # pop target-val from out -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 # check target-val is a file -225 var target-type-addr/eax: (addr int) <- get target-val, type -226 compare *target-type-addr, 3 # file -227 break-if-!= -228 # read all lines from file and save as an array of strings in target-val -229 # read target-val as a filename and save the handle in target-val -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 #? enable-screen-type-mode -239 #? print-string 0, tmp -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 # save result into target-val -248 var type-addr/eax: (addr int) <- get target-val, type -249 copy-to *type-addr, 2 # array -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 # if curr-stream defines a binding, save top of stack to bindings -259 { -260 var done?/eax: boolean <- stream-empty? curr-stream -261 compare done?, 0 # false -262 break-if-!= -263 var new-byte/eax: byte <- read-byte curr-stream -264 compare new-byte, 0x3d # '=' -265 break-if-!= -266 # pop target-val from out -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 # create binding from curr-stream to target-val -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 # if curr-stream is a known function name, call it appropriately -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 # HACKS: we're trying to avoid turning this into Forth + 14 #? print-string-to-real-screen "eval: " + 15 #? print-stream-to-real-screen curr-stream + 16 #? print-string-to-real-screen "\n" + 17 $evaluate:process-word: { + 18 ### if curr-stream is an operator, perform it + 19 ## numbers + 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 ## strings/arrays + 54 { + 55 var is-len?/eax: boolean <- stream-data-equal? curr-stream, "len" + 56 compare is-len?, 0 + 57 break-if-= + 58 #? print-string 0, "is len\n" + 59 # pop target-val from out + 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 #? print-string 0, "stack has stuff\n" + 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 # check target-val is a string or array + 72 var target-type-addr/eax: (addr int) <- get target-val, type + 73 compare *target-type-addr, 1 # string + 74 { + 75 break-if-!= + 76 # compute length + 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 # save result into target-val + 81 var type-addr/eax: (addr int) <- get target-val, type + 82 copy-to *type-addr, 0 # int + 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 # array of ints + 91 { + 92 break-if-!= + 93 # compute length + 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 # save result into target-val + 98 var type-addr/eax: (addr int) <- get target-val, type + 99 copy-to *type-addr, 0 # int +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 ## files +109 { +110 var is-open?/eax: boolean <- stream-data-equal? curr-stream, "open" +111 compare is-open?, 0 +112 break-if-= +113 # pop target-val from out +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 # check target-val is a string +125 var target-type-addr/eax: (addr int) <- get target-val, type +126 compare *target-type-addr, 1 # string +127 break-if-!= +128 # open target-val as a filename and save the handle in target-val +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 # write? = false +133 # save result into target-val +134 var type-addr/eax: (addr int) <- get target-val, type +135 copy-to *type-addr, 3 # file +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 # pop target-val from out +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 # check target-val is a file +159 var target-type-addr/eax: (addr int) <- get target-val, type +160 compare *target-type-addr, 3 # file +161 break-if-!= +162 # read a line from the file and save in target-val +163 # read target-val as a filename and save the handle in target-val +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 # save result into target-val +172 var type-addr/eax: (addr int) <- get target-val, type +173 copy-to *type-addr, 1 # string +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 # pop target-val from out +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 # check target-val is a file +195 var target-type-addr/eax: (addr int) <- get target-val, type +196 compare *target-type-addr, 3 # file +197 break-if-!= +198 # slurp all contents from file and save in target-val +199 # read target-val as a filename and save the handle in target-val +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 # save result into target-val +208 var type-addr/eax: (addr int) <- get target-val, type +209 copy-to *type-addr, 1 # string +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 # pop target-val from out +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 # check target-val is a file +231 var target-type-addr/eax: (addr int) <- get target-val, type +232 compare *target-type-addr, 3 # file +233 break-if-!= +234 # read all lines from file and save as an array of strings in target-val +235 # read target-val as a filename and save the handle in target-val +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 #? enable-screen-type-mode +245 #? print-string 0, tmp +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 # save result into target-val +254 var type-addr/eax: (addr int) <- get target-val, type +255 copy-to *type-addr, 2 # array +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 ## screens +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 # pop width and height from out +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 # define a new screen with those dimensions +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 # push screen to stack +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 # screen +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-dup?/eax: boolean <- stream-data-equal? curr-stream, "dup" -299 compare is-dup?, 0 +298 var is-print?/eax: boolean <- stream-data-equal? curr-stream, "print" +299 compare is-print?, 0 300 break-if-= -301 # read src-val from out -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 # push a copy of it -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 # commit -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 # read top-val from out -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 # read next val from out -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 # swap -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 # END HACKS -350 # if it's a name, push its value -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 # unfortunate leak -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 # if the word starts with a quote and ends with a quote, turn it into a string -368 { -369 var start/eax: byte <- stream-first curr-stream -370 compare start, 0x22 # double-quote -371 break-if-!= -372 var end/eax: byte <- stream-final curr-stream -373 compare end, 0x22 # double-quote -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 # leak -378 push-string-to-value-stack out, *s -379 break $evaluate:process-word -380 } -381 # if the word starts with a '[' and ends with a ']', turn it into an array -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 # wastefully create a new input string to strip quotes -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 # leak -393 # wastefully parse input into int-array -394 # TODO: support parsing arrays of other types -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 # leak -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 # push value-array of same size as int-array -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 # copy int-array into value-array -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 # otherwise assume it's a literal int and push it -426 { -427 var n/eax: int <- parse-decimal-int-from-stream curr-stream -428 push-int-to-value-stack out, n -429 } -430 } -431 # termination check -432 compare curr, end -433 break-if-= -434 # update -435 var next-word-ah/edx: (addr handle word) <- get curr, next -436 curr <- lookup *next-word-ah -437 # -438 loop -439 } -440 # process next line if necessary -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 # false -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 # create bindings for args -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 # obtain body -502 var body-ah/eax: (addr handle line) <- get callee, body -503 var body/eax: (addr line) <- lookup *body-ah -504 # perform call -505 var stack-storage: value-stack -506 var stack/edi: (addr value-stack) <- address stack-storage -507 initialize-value-stack stack, 0x10 -508 #? print-string-to-real-screen "about to enter recursive eval\n" -509 evaluate functions, table, body, 0, stack -510 #? print-string-to-real-screen "exited recursive eval\n" -511 # pop target-val from out -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 # stitch target-val into caller-stack -522 push-value-stack caller-stack, target-val -523 } -524 -525 # pop args from the caller-stack and bind them to successive args -526 # implies: function args are stored in reverse order -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 # create binding -538 word-to-string curr-arg, curr-key -539 { -540 # pop target-val from caller-stack -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 # create binding from curr-key to target-val -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 # Copy of 'simplify' that just tracks the maximum stack depth needed -562 # Doesn't actually need to simulate the stack, since every word has a predictable effect. -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 # handle operators -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 # otherwise it's an int (do we need error-checking?) -592 curr-depth <- increment -593 # update max depth if necessary +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 # pop string from out +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 # select target screen from top of out (but don't pop it) +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 # screen +325 break-if-!= +326 # print string to target screen +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 # pop args +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 # select screen from top of out (but don't pop it) +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 # screen +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 # pop args +372 var _d/eax: int <- pop-int-from-value-stack out2 +373 var d/ecx: int <- copy _d +374 # select screen from top of out (but don't pop it) +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 # screen +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 # pop args +415 var _d/eax: int <- pop-int-from-value-stack out2 +416 var d/ecx: int <- copy _d +417 # select screen from top of out (but don't pop it) +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 # screen +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 # pop args +460 var _d/eax: int <- pop-int-from-value-stack out2 +461 var d/ecx: int <- copy _d +462 # select screen from top of out (but don't pop it) +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 # screen +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 # second one to undo the print above +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 # pop args +504 var _d/eax: int <- pop-int-from-value-stack out2 +505 var d/ecx: int <- copy _d +506 # select screen from top of out (but don't pop it) +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 # screen +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 # no increment; the print took care of it +534 move-cursor target, row, *c +535 d <- decrement +536 loop +537 } +538 break $evaluate:process-word +539 } +540 ## HACKS: we're trying to avoid turning this into Forth +541 { +542 var is-dup?/eax: boolean <- stream-data-equal? curr-stream, "dup" +543 compare is-dup?, 0 +544 break-if-= +545 # read src-val from out +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 # push a copy of it +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 # commit +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 # read top-val from out +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 # read next val from out +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 # swap +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 ### if curr-stream defines a binding, save top of stack to bindings 594 { -595 compare curr-depth, result -596 break-if-<= -597 result <- copy curr-depth -598 } -599 } -600 # if curr-word == final-word break -601 compare curr-word, final-word -602 break-if-= -603 # curr-word = curr-word->next -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 } +595 var done?/eax: boolean <- stream-empty? curr-stream +596 compare done?, 0 # false +597 break-if-!= +598 var new-byte/eax: byte <- read-byte curr-stream +599 compare new-byte, 0x3d # '=' +600 break-if-!= +601 # pop target-val from out +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 # create binding from curr-stream to target-val +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 ### if curr-stream is a known function name, call it appropriately +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 ### if it's a name, push its value +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 # unfortunate leak +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 ### if the word starts with a quote and ends with a quote, turn it into a string +649 { +650 var start/eax: byte <- stream-first curr-stream +651 compare start, 0x22 # double-quote +652 break-if-!= +653 var end/eax: byte <- stream-final curr-stream +654 compare end, 0x22 # double-quote +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 # leak +659 push-string-to-value-stack out, *s +660 break $evaluate:process-word +661 } +662 ### if the word starts with a '[' and ends with a ']', turn it into an array +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 # wastefully create a new input string to strip quotes +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 # leak +674 # wastefully parse input into int-array +675 # TODO: support parsing arrays of other types +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 # leak +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 # push value-array of same size as int-array +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 # copy int-array into value-array +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 ### otherwise assume it's a literal number and push it +707 { +708 var n/eax: int <- parse-decimal-int-from-stream curr-stream +709 push-int-to-value-stack out, n +710 } +711 } +712 # termination check +713 compare curr, end +714 break-if-= +715 # update +716 var next-word-ah/edx: (addr handle word) <- get curr, next +717 curr <- lookup *next-word-ah +718 # +719 loop +720 } +721 # process next line if necessary +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 # false +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 # create bindings for args +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 # obtain body +783 var body-ah/eax: (addr handle line) <- get callee, body +784 var body/eax: (addr line) <- lookup *body-ah +785 # perform call +786 var stack-storage: value-stack +787 var stack/edi: (addr value-stack) <- address stack-storage +788 initialize-value-stack stack, 0x10 +789 #? print-string-to-real-screen "about to enter recursive eval\n" +790 evaluate functions, table, body, 0, stack +791 #? print-string-to-real-screen "exited recursive eval\n" +792 # pop target-val from out +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 # stitch target-val into caller-stack +803 push-value-stack caller-stack, target-val +804 } +805 +806 # pop args from the caller-stack and bind them to successive args +807 # implies: function args are stored in reverse order +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 # create binding +819 word-to-string curr-arg, curr-key +820 { +821 # pop target-val from caller-stack +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 # create binding from curr-key to target-val +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 # Copy of 'simplify' that just tracks the maximum stack depth needed +843 # Doesn't actually need to simulate the stack, since every word has a predictable effect. +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 # handle operators +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 # otherwise it's an int (do we need error-checking?) +873 curr-depth <- increment +874 # update max depth if necessary +875 { +876 compare curr-depth, result +877 break-if-<= +878 result <- copy curr-depth +879 } +880 } +881 # if curr-word == final-word break +882 compare curr-word, final-word +883 break-if-= +884 # curr-word = curr-word->next +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 } -- cgit 1.4.1-2-gfad0