From 3350c34a74844e21ea69077e01efff3bae64bdcd Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Tue, 23 Mar 2021 17:31:08 -0700 Subject: . --- html/apps/tile/rpn.mu.html | 975 --------------------------------------------- 1 file changed, 975 deletions(-) delete mode 100644 html/apps/tile/rpn.mu.html (limited to 'html/apps/tile/rpn.mu.html') diff --git a/html/apps/tile/rpn.mu.html b/html/apps/tile/rpn.mu.html deleted file mode 100644 index 55564796..00000000 --- a/html/apps/tile/rpn.mu.html +++ /dev/null @@ -1,975 +0,0 @@ - - - - -Mu - apps/tile/rpn.mu - - - - - - - - - - -https://github.com/akkartik/mu/blob/main/apps/tile/rpn.mu -
-  1 fn evaluate functions: (addr handle function), bindings: (addr table), scratch: (addr line), end: (addr word), out: (addr value-stack) {
-  2   var line/eax: (addr line) <- copy scratch
-  3   var word-ah/eax: (addr handle word) <- get line, data
-  4   var curr/eax: (addr word) <- lookup *word-ah
-  5   var curr-stream-storage: (stream byte 0x10)
-  6   var curr-stream/edi: (addr stream byte) <- address curr-stream-storage
-  7   clear-value-stack out
-  8   $evaluate:loop: {
-  9     # precondition (should never hit)
- 10     compare curr, 0
- 11     break-if-=
- 12     # update curr-stream
- 13     emit-word curr, curr-stream
- 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/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-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/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-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/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-number-to-value-stack out, a
- 51         break $evaluate:process-word
- 52       }
- 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 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