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