From 74ed21ab147a7ea6b6bcc37162c52405c80a3257 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sun, 14 Feb 2021 16:48:02 -0800 Subject: [PATCH] 7746 --- html/baremetal/shell/eval.mu.html | 906 ++++++++++---------- html/baremetal/shell/gap-buffer.mu.html | 522 +++++------ html/baremetal/shell/grapheme-stack.mu.html | 170 ++-- html/baremetal/shell/line.mu.html | 176 ++-- html/baremetal/shell/value-stack.mu.html | 276 +++--- html/baremetal/shell/value.mu.html | 192 ++--- html/baremetal/shell/word.mu.html | 824 +++++++++--------- tools/update_html | 5 +- 8 files changed, 1535 insertions(+), 1536 deletions(-) diff --git a/html/baremetal/shell/eval.mu.html b/html/baremetal/shell/eval.mu.html index 36b8d3f9..9e0d1e32 100644 --- a/html/baremetal/shell/eval.mu.html +++ b/html/baremetal/shell/eval.mu.html @@ -97,16 +97,16 @@ if ('onhashchange' in window) { 37 # If `loop` in middle executes, skip to previous containing `{` 38 # If no containing `}`, clear stack (error) 39 - 40 fn evaluate _in: (addr line), end: (addr word), out: (addr value-stack) { - 41 clear-value-stack out - 42 var line/eax: (addr line) <- copy _in - 43 var curr-ah/eax: (addr handle word) <- get line, data - 44 var curr/eax: (addr word) <- lookup *curr-ah - 45 evaluate-sub curr, end, out, 1/top-level + 40 fn evaluate _in: (addr line), end: (addr word), out: (addr value-stack) { + 41 clear-value-stack out + 42 var line/eax: (addr line) <- copy _in + 43 var curr-ah/eax: (addr handle word) <- get line, data + 44 var curr/eax: (addr word) <- lookup *curr-ah + 45 evaluate-sub curr, end, out, 1/top-level 46 } 47 - 48 fn evaluate-sub _curr: (addr word), end: (addr word), out: (addr value-stack), top-level?: boolean { - 49 var curr/ecx: (addr word) <- copy _curr + 48 fn evaluate-sub _curr: (addr word), end: (addr word), out: (addr value-stack), top-level?: boolean { + 49 var curr/ecx: (addr word) <- copy _curr 50 var curr-stream-storage: (stream byte 0x10) 51 var curr-stream/edi: (addr stream byte) <- address curr-stream-storage 52 $evaluate-sub:loop: { @@ -114,7 +114,7 @@ if ('onhashchange' in window) { 54 compare curr, 0 55 break-if-= 56 # pull next word in for parsing - 57 emit-word curr, curr-stream + 57 emit-word curr, curr-stream 58 #? { 59 #? clear-screen 0/screen 60 #? dump-stack out @@ -128,126 +128,126 @@ if ('onhashchange' in window) { 68 $evaluate-sub:process-word: { 69 ### if curr-stream is an operator, perform it 70 { - 71 var is-add?/eax: boolean <- stream-data-equal? curr-stream, "+" + 71 var is-add?/eax: boolean <- stream-data-equal? curr-stream, "+" 72 compare is-add?, 0/false 73 break-if-= - 74 var _b/xmm0: float <- pop-number-from-value-stack out + 74 var _b/xmm0: float <- pop-number-from-value-stack out 75 var b/xmm1: float <- copy _b - 76 var a/xmm0: float <- pop-number-from-value-stack out + 76 var a/xmm0: float <- pop-number-from-value-stack out 77 a <- add b - 78 push-number-to-value-stack out, a + 78 push-number-to-value-stack out, a 79 break $evaluate-sub:process-word 80 } 81 { - 82 var is-sub?/eax: boolean <- stream-data-equal? curr-stream, "-" + 82 var is-sub?/eax: boolean <- stream-data-equal? curr-stream, "-" 83 compare is-sub?, 0/false 84 break-if-= - 85 var _b/xmm0: float <- pop-number-from-value-stack out + 85 var _b/xmm0: float <- pop-number-from-value-stack out 86 var b/xmm1: float <- copy _b - 87 var a/xmm0: float <- pop-number-from-value-stack out + 87 var a/xmm0: float <- pop-number-from-value-stack out 88 a <- subtract b - 89 push-number-to-value-stack out, a + 89 push-number-to-value-stack out, a 90 break $evaluate-sub:process-word 91 } 92 { - 93 var is-mul?/eax: boolean <- stream-data-equal? curr-stream, "*" + 93 var is-mul?/eax: boolean <- stream-data-equal? curr-stream, "*" 94 compare is-mul?, 0/false 95 break-if-= - 96 var _b/xmm0: float <- pop-number-from-value-stack out + 96 var _b/xmm0: float <- pop-number-from-value-stack out 97 var b/xmm1: float <- copy _b - 98 var a/xmm0: float <- pop-number-from-value-stack out + 98 var a/xmm0: float <- pop-number-from-value-stack out 99 a <- multiply b -100 push-number-to-value-stack out, a +100 push-number-to-value-stack out, a 101 break $evaluate-sub:process-word 102 } 103 { -104 var is-div?/eax: boolean <- stream-data-equal? curr-stream, "/" +104 var is-div?/eax: boolean <- stream-data-equal? curr-stream, "/" 105 compare is-div?, 0/false 106 break-if-= -107 var _b/xmm0: float <- pop-number-from-value-stack out +107 var _b/xmm0: float <- pop-number-from-value-stack out 108 var b/xmm1: float <- copy _b -109 var a/xmm0: float <- pop-number-from-value-stack out +109 var a/xmm0: float <- pop-number-from-value-stack out 110 a <- divide b -111 push-number-to-value-stack out, a +111 push-number-to-value-stack out, a 112 break $evaluate-sub:process-word 113 } 114 { -115 var is-sqrt?/eax: boolean <- stream-data-equal? curr-stream, "sqrt" +115 var is-sqrt?/eax: boolean <- stream-data-equal? curr-stream, "sqrt" 116 compare is-sqrt?, 0/false 117 break-if-= -118 var a/xmm0: float <- pop-number-from-value-stack out +118 var a/xmm0: float <- pop-number-from-value-stack out 119 a <- square-root a -120 push-number-to-value-stack out, a +120 push-number-to-value-stack out, a 121 break $evaluate-sub:process-word 122 } 123 { -124 var is-lesser?/eax: boolean <- stream-data-equal? curr-stream, "<" +124 var is-lesser?/eax: boolean <- stream-data-equal? curr-stream, "<" 125 compare is-lesser?, 0/false 126 break-if-= -127 var _b/xmm0: float <- pop-number-from-value-stack out +127 var _b/xmm0: float <- pop-number-from-value-stack out 128 var b/xmm1: float <- copy _b -129 var a/xmm0: float <- pop-number-from-value-stack out +129 var a/xmm0: float <- pop-number-from-value-stack out 130 compare a, b 131 { 132 break-if-float< -133 push-boolean-to-value-stack out, 0/false +133 push-boolean-to-value-stack out, 0/false 134 break $evaluate-sub:process-word 135 } -136 push-boolean-to-value-stack out, 1/true +136 push-boolean-to-value-stack out, 1/true 137 break $evaluate-sub:process-word 138 } 139 { -140 var is-greater?/eax: boolean <- stream-data-equal? curr-stream, ">" +140 var is-greater?/eax: boolean <- stream-data-equal? curr-stream, ">" 141 compare is-greater?, 0/false 142 break-if-= -143 var _b/xmm0: float <- pop-number-from-value-stack out +143 var _b/xmm0: float <- pop-number-from-value-stack out 144 var b/xmm1: float <- copy _b -145 var a/xmm0: float <- pop-number-from-value-stack out +145 var a/xmm0: float <- pop-number-from-value-stack out 146 compare a, b 147 { 148 break-if-float> -149 push-boolean-to-value-stack out, 0/false +149 push-boolean-to-value-stack out, 0/false 150 break $evaluate-sub:process-word 151 } -152 push-boolean-to-value-stack out, 1/true +152 push-boolean-to-value-stack out, 1/true 153 break $evaluate-sub:process-word 154 } 155 { -156 var is-equal?/eax: boolean <- stream-data-equal? curr-stream, "==" # TODO support non-numbers +156 var is-equal?/eax: boolean <- stream-data-equal? curr-stream, "==" # TODO support non-numbers 157 compare is-equal?, 0/false 158 break-if-= -159 var _b/xmm0: float <- pop-number-from-value-stack out +159 var _b/xmm0: float <- pop-number-from-value-stack out 160 var b/xmm1: float <- copy _b -161 var a/xmm0: float <- pop-number-from-value-stack out +161 var a/xmm0: float <- pop-number-from-value-stack out 162 compare a, b 163 { 164 break-if-= -165 push-boolean-to-value-stack out, 0/false +165 push-boolean-to-value-stack out, 0/false 166 break $evaluate-sub:process-word 167 } -168 push-boolean-to-value-stack out, 1/true +168 push-boolean-to-value-stack out, 1/true 169 break $evaluate-sub:process-word 170 } 171 ## control flow 172 { -173 var is-conditional?/eax: boolean <- stream-data-equal? curr-stream, "->" +173 var is-conditional?/eax: boolean <- stream-data-equal? curr-stream, "->" 174 compare is-conditional?, 0/false 175 break-if-= -176 var a/eax: boolean <- pop-boolean-from-value-stack out +176 var a/eax: boolean <- pop-boolean-from-value-stack out 177 compare a, 0/false 178 { 179 break-if-!= 180 # if a is false, skip one word -181 var next-word: (handle word) -182 var next-word-ah/eax: (addr handle word) <- address next-word -183 skip-word curr, end, next-word-ah -184 var _curr/eax: (addr word) <- lookup *next-word-ah +181 var next-word: (handle word) +182 var next-word-ah/eax: (addr handle word) <- address next-word +183 skip-word curr, end, next-word-ah +184 var _curr/eax: (addr word) <- lookup *next-word-ah 185 curr <- copy _curr 186 } 187 break $evaluate-sub:process-word 188 } 189 { -190 var is-group-start?/eax: boolean <- stream-data-equal? curr-stream, "{" +190 var is-group-start?/eax: boolean <- stream-data-equal? curr-stream, "{" 191 compare is-group-start?, 0/false 192 break-if-= 193 # if top-level? and this is the final word, clear the stack @@ -255,11 +255,11 @@ if ('onhashchange' in window) { 195 break-if-= $evaluate-sub:process-word 196 compare curr, end 197 break-if-!= $evaluate-sub:process-word -198 clear-value-stack out +198 clear-value-stack out 199 break $evaluate-sub:process-word 200 } 201 { -202 var is-group-end?/eax: boolean <- stream-data-equal? curr-stream, "}" +202 var is-group-end?/eax: boolean <- stream-data-equal? curr-stream, "}" 203 compare is-group-end?, 0/false 204 break-if-= 205 # if top-level? and this is the final word, clear the stack @@ -267,89 +267,89 @@ if ('onhashchange' in window) { 207 break-if-= $evaluate-sub:process-word 208 compare curr, end 209 break-if-!= $evaluate-sub:process-word -210 clear-value-stack out +210 clear-value-stack out 211 break $evaluate-sub:process-word 212 } 213 { -214 var is-break?/eax: boolean <- stream-data-equal? curr-stream, "break" +214 var is-break?/eax: boolean <- stream-data-equal? curr-stream, "break" 215 compare is-break?, 0/false 216 break-if-= 217 # scan ahead to containing '}' -218 var next-word: (handle word) -219 var next-word-ah/eax: (addr handle word) <- address next-word -220 skip-rest-of-group curr, end, next-word-ah -221 var _curr/eax: (addr word) <- lookup *next-word-ah +218 var next-word: (handle word) +219 var next-word-ah/eax: (addr handle word) <- address next-word +220 skip-rest-of-group curr, end, next-word-ah +221 var _curr/eax: (addr word) <- lookup *next-word-ah 222 curr <- copy _curr 223 loop $evaluate-sub:loop 224 } 225 { -226 var is-loop?/eax: boolean <- stream-data-equal? curr-stream, "loop" +226 var is-loop?/eax: boolean <- stream-data-equal? curr-stream, "loop" 227 compare is-loop?, 0/false 228 break-if-= 229 # scan back to containing '{' -230 var open-word: (handle word) -231 var open-word-ah/edx: (addr handle word) <- address open-word -232 scan-to-start-of-group curr, end, open-word-ah +230 var open-word: (handle word) +231 var open-word-ah/edx: (addr handle word) <- address open-word +232 scan-to-start-of-group curr, end, open-word-ah 233 # scan ahead to the containing '}'; record that as next word to eval at -234 var close-word: (handle word) -235 var close-word-ah/ebx: (addr handle word) <- address close-word -236 skip-rest-of-group curr, end, close-word-ah -237 var _curr/eax: (addr word) <- lookup *close-word-ah +234 var close-word: (handle word) +235 var close-word-ah/ebx: (addr handle word) <- address close-word +236 skip-rest-of-group curr, end, close-word-ah +237 var _curr/eax: (addr word) <- lookup *close-word-ah 238 curr <- copy _curr 239 # now eval until getting there 240 # TODO: can 'curr' be after 'end' at this point? -241 var open/eax: (addr word) <- lookup *open-word-ah -242 evaluate-sub open, curr, out, 0/nested +241 var open/eax: (addr word) <- lookup *open-word-ah +242 evaluate-sub open, curr, out, 0/nested 243 loop $evaluate-sub:loop 244 } 245 ## TEMPORARY HACKS; we're trying to avoid turning this into Forth 246 { -247 var is-dup?/eax: boolean <- stream-data-equal? curr-stream, "dup" +247 var is-dup?/eax: boolean <- stream-data-equal? curr-stream, "dup" 248 compare is-dup?, 0/false 249 break-if-= 250 # read src-val from out -251 var out2/esi: (addr value-stack) <- copy out -252 var top-addr/ecx: (addr int) <- get out2, top +251 var out2/esi: (addr value-stack) <- copy out +252 var top-addr/ecx: (addr int) <- get out2, top 253 compare *top-addr, 0 254 break-if-<= -255 var data-ah/eax: (addr handle array value) <- get out2, data -256 var data/eax: (addr array value) <- lookup *data-ah -257 var top/ecx: int <- copy *top-addr -258 top <- decrement -259 var offset/edx: (offset value) <- compute-offset data, top -260 var src-val/edx: (addr value) <- index data, offset +255 var data-ah/eax: (addr handle array value) <- get out2, data +256 var data/eax: (addr array value) <- lookup *data-ah +257 var top/ecx: int <- copy *top-addr +258 top <- decrement +259 var offset/edx: (offset value) <- compute-offset data, top +260 var src-val/edx: (addr value) <- index data, offset 261 # push a copy of it -262 top <- increment -263 var offset/ebx: (offset value) <- compute-offset data, top -264 var target-val/ebx: (addr value) <- index data, offset +262 top <- increment +263 var offset/ebx: (offset value) <- compute-offset data, top +264 var target-val/ebx: (addr value) <- index data, offset 265 copy-object src-val, target-val 266 # commit -267 var top-addr/ecx: (addr int) <- get out2, top +267 var top-addr/ecx: (addr int) <- get out2, top 268 increment *top-addr 269 break $evaluate-sub:process-word 270 } 271 { -272 var is-swap?/eax: boolean <- stream-data-equal? curr-stream, "swap" +272 var is-swap?/eax: boolean <- stream-data-equal? curr-stream, "swap" 273 compare is-swap?, 0/false 274 break-if-= 275 # read top-val from out -276 var out2/esi: (addr value-stack) <- copy out -277 var top-addr/ecx: (addr int) <- get out2, top +276 var out2/esi: (addr value-stack) <- copy out +277 var top-addr/ecx: (addr int) <- get out2, top 278 compare *top-addr, 0 279 break-if-<= -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/ecx: int <- copy *top-addr -283 top <- decrement -284 var offset/edx: (offset value) <- compute-offset data, top -285 var top-val/edx: (addr value) <- index data, offset +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/ecx: int <- copy *top-addr +283 top <- decrement +284 var offset/edx: (offset value) <- compute-offset data, top +285 var top-val/edx: (addr value) <- index data, offset 286 # read next val from out -287 top <- decrement -288 var offset/ebx: (offset value) <- compute-offset data, top -289 var pen-top-val/ebx: (addr value) <- index data, offset +287 top <- decrement +288 var offset/ebx: (offset value) <- compute-offset data, top +289 var pen-top-val/ebx: (addr value) <- index data, offset 290 # swap -291 var tmp: value -292 var tmp-a/eax: (addr value) <- address tmp +291 var tmp: value +292 var tmp-a/eax: (addr value) <- address tmp 293 copy-object top-val, tmp-a 294 copy-object pen-top-val, top-val 295 copy-object tmp-a, pen-top-val @@ -357,49 +357,49 @@ if ('onhashchange' in window) { 297 } 298 ### if the word starts with a quote and ends with a quote, turn it into a string 299 { -300 rewind-stream curr-stream -301 var start/eax: byte <- stream-first curr-stream +300 rewind-stream curr-stream +301 var start/eax: byte <- stream-first curr-stream 302 compare start, 0x22/double-quote 303 break-if-!= -304 var end/eax: byte <- stream-final curr-stream +304 var end/eax: byte <- stream-final curr-stream 305 compare end, 0x22/double-quote 306 break-if-!= 307 var h: (handle array byte) 308 var s/eax: (addr handle array byte) <- address h -309 unquote-stream-to-array curr-stream, s # leak -310 push-string-to-value-stack out, *s +309 unquote-stream-to-array curr-stream, s # leak +310 push-string-to-value-stack out, *s 311 break $evaluate-sub:process-word 312 } 313 ### if the word starts with a '[' and ends with a ']', turn it into an array 314 { -315 rewind-stream curr-stream -316 var start/eax: byte <- stream-first curr-stream +315 rewind-stream curr-stream +316 var start/eax: byte <- stream-first curr-stream 317 compare start, 0x5b/open-bracket 318 break-if-!= -319 var end/eax: byte <- stream-final curr-stream +319 var end/eax: byte <- stream-final curr-stream 320 compare end, 0x5d/close-bracket 321 break-if-!= 322 # wastefully create a new input string to strip quotes -323 var h: (handle array value) +323 var h: (handle array value) 324 var input-ah/eax: (addr handle array byte) <- address h -325 unquote-stream-to-array curr-stream, input-ah # leak +325 unquote-stream-to-array curr-stream, input-ah # leak 326 # wastefully parse input into int-array 327 # TODO: support parsing arrays of other types -328 var input/eax: (addr array byte) <- lookup *input-ah +328 var input/eax: (addr array byte) <- lookup *input-ah 329 var h2: (handle array int) 330 var int-array-ah/esi: (addr handle array int) <- address h2 -331 parse-array-of-decimal-ints input, int-array-ah # leak -332 var _int-array/eax: (addr array int) <- lookup *int-array-ah +331 parse-array-of-decimal-ints input, int-array-ah # leak +332 var _int-array/eax: (addr array int) <- lookup *int-array-ah 333 var int-array/esi: (addr array int) <- copy _int-array 334 var len/ebx: int <- length int-array 335 # push value-array of same size as int-array -336 var h3: (handle array value) -337 var value-array-ah/eax: (addr handle array value) <- address h3 +336 var h3: (handle array value) +337 var value-array-ah/eax: (addr handle array value) <- address h3 338 populate value-array-ah, len -339 push-array-to-value-stack out, *value-array-ah +339 push-array-to-value-stack out, *value-array-ah 340 # copy int-array into value-array -341 var _value-array/eax: (addr array value) <- lookup *value-array-ah -342 var value-array/edi: (addr array value) <- copy _value-array +341 var _value-array/eax: (addr array value) <- lookup *value-array-ah +342 var value-array/edi: (addr array value) <- copy _value-array 343 var i/eax: int <- copy 0 344 { 345 compare i, len @@ -407,9 +407,9 @@ if ('onhashchange' in window) { 347 var src-addr/ecx: (addr int) <- index int-array, i 348 var src/ecx: int <- copy *src-addr 349 var src-f/xmm0: float <- convert src -350 var dest-offset/edx: (offset value) <- compute-offset value-array, i -351 var dest-val/edx: (addr value) <- index value-array, dest-offset -352 var dest/edx: (addr float) <- get dest-val, number-data +350 var dest-offset/edx: (offset value) <- compute-offset value-array, i +351 var dest-val/edx: (addr value) <- index value-array, dest-offset +352 var dest/edx: (addr float) <- get dest-val, number-data 353 copy-to *dest, src-f 354 i <- increment 355 loop @@ -418,94 +418,94 @@ if ('onhashchange' in window) { 358 } 359 ### otherwise assume it's a literal number and push it (can't parse floats yet) 360 { -361 var n/eax: int <- parse-decimal-int-from-stream curr-stream +361 var n/eax: int <- parse-decimal-int-from-stream curr-stream 362 var n-f/xmm0: float <- convert n -363 push-number-to-value-stack out, n-f +363 push-number-to-value-stack out, n-f 364 } 365 } 366 # termination check 367 compare curr, end 368 break-if-= 369 # update -370 var next-word-ah/edx: (addr handle word) <- get curr, next -371 var _curr/eax: (addr word) <- lookup *next-word-ah +370 var next-word-ah/edx: (addr handle word) <- get curr, next +371 var _curr/eax: (addr word) <- lookup *next-word-ah 372 curr <- copy _curr 373 # 374 loop 375 } 376 } 377 -378 fn skip-word _curr: (addr word), end: (addr word), out: (addr handle word) { -379 var curr/eax: (addr word) <- copy _curr +378 fn skip-word _curr: (addr word), end: (addr word), out: (addr handle word) { +379 var curr/eax: (addr word) <- copy _curr 380 var bracket-count/ecx: int <- copy 0 -381 var result-ah/esi: (addr handle word) <- get curr, next +381 var result-ah/esi: (addr handle word) <- get curr, next 382 { -383 var result-val/eax: (addr word) <- lookup *result-ah +383 var result-val/eax: (addr word) <- lookup *result-ah 384 compare result-val, end 385 break-if-= 386 { -387 var open?/eax: boolean <- word-equal? result-val, "{" +387 var open?/eax: boolean <- word-equal? result-val, "{" 388 compare open?, 0/false 389 break-if-= 390 bracket-count <- increment 391 } 392 { -393 var close?/eax: boolean <- word-equal? result-val, "}" +393 var close?/eax: boolean <- word-equal? result-val, "}" 394 compare close?, 0/false 395 break-if-= 396 bracket-count <- decrement 397 compare bracket-count, 0 398 { 399 break-if->= -400 abort "'->' cannot be final word in a {} group" # TODO: error-handling +400 abort "'->' cannot be final word in a {} group" # TODO: error-handling 401 } 402 } 403 compare bracket-count, 0 404 break-if-= -405 result-ah <- get result-val, next +405 result-ah <- get result-val, next 406 loop 407 } 408 copy-object result-ah, out 409 } 410 -411 fn skip-rest-of-group _curr: (addr word), end: (addr word), out: (addr handle word) { -412 var curr/eax: (addr word) <- copy _curr +411 fn skip-rest-of-group _curr: (addr word), end: (addr word), out: (addr handle word) { +412 var curr/eax: (addr word) <- copy _curr 413 var bracket-count/ecx: int <- copy 0 -414 var result-ah/esi: (addr handle word) <- get curr, next +414 var result-ah/esi: (addr handle word) <- get curr, next 415 $skip-rest-of-group:loop: { -416 var result-val/eax: (addr word) <- lookup *result-ah +416 var result-val/eax: (addr word) <- lookup *result-ah 417 compare result-val, end 418 break-if-= 419 { -420 var open?/eax: boolean <- word-equal? result-val, "{" +420 var open?/eax: boolean <- word-equal? result-val, "{" 421 compare open?, 0/false 422 break-if-= 423 bracket-count <- increment 424 } 425 { -426 var close?/eax: boolean <- word-equal? result-val, "}" +426 var close?/eax: boolean <- word-equal? result-val, "}" 427 compare close?, 0/false 428 break-if-= 429 compare bracket-count, 0 430 break-if-= $skip-rest-of-group:loop 431 bracket-count <- decrement 432 } -433 result-ah <- get result-val, next +433 result-ah <- get result-val, next 434 loop 435 } 436 copy-object result-ah, out 437 } 438 -439 fn scan-to-start-of-group _curr: (addr word), end: (addr word), out: (addr handle word) { -440 var curr/eax: (addr word) <- copy _curr +439 fn scan-to-start-of-group _curr: (addr word), end: (addr word), out: (addr handle word) { +440 var curr/eax: (addr word) <- copy _curr 441 var bracket-count/ecx: int <- copy 0 -442 var result-ah/esi: (addr handle word) <- get curr, prev +442 var result-ah/esi: (addr handle word) <- get curr, prev 443 $scan-to-start-of-group:loop: { -444 var result-val/eax: (addr word) <- lookup *result-ah +444 var result-val/eax: (addr word) <- lookup *result-ah 445 compare result-val, end 446 break-if-= 447 { -448 var open?/eax: boolean <- word-equal? result-val, "{" +448 var open?/eax: boolean <- word-equal? result-val, "{" 449 compare open?, 0/false 450 break-if-= 451 compare bracket-count, 0 @@ -513,382 +513,382 @@ if ('onhashchange' in window) { 453 bracket-count <- increment 454 } 455 { -456 var close?/eax: boolean <- word-equal? result-val, "}" +456 var close?/eax: boolean <- word-equal? result-val, "}" 457 compare close?, 0/false 458 break-if-= 459 bracket-count <- decrement 460 } -461 result-ah <- get result-val, prev +461 result-ah <- get result-val, prev 462 loop 463 } 464 copy-object result-ah, out 465 } 466 -467 fn test-eval-arithmetic { +467 fn test-eval-arithmetic { 468 # in -469 var in-storage: line -470 var in/esi: (addr line) <- address in-storage -471 parse-line "1 1 +", in +469 var in-storage: line +470 var in/esi: (addr line) <- address in-storage +471 parse-line "1 1 +", in 472 # end -473 var w-ah/eax: (addr handle word) <- get in, data -474 var end-h: (handle word) -475 var end-ah/ecx: (addr handle word) <- address end-h -476 final-word w-ah, end-ah -477 var end/eax: (addr word) <- lookup *end-ah +473 var w-ah/eax: (addr handle word) <- get in, data +474 var end-h: (handle word) +475 var end-ah/ecx: (addr handle word) <- address end-h +476 final-word w-ah, end-ah +477 var end/eax: (addr word) <- lookup *end-ah 478 # out -479 var out-storage: value-stack -480 var out/edi: (addr value-stack) <- address out-storage -481 initialize-value-stack out, 8 +479 var out-storage: value-stack +480 var out/edi: (addr value-stack) <- address out-storage +481 initialize-value-stack out, 8 482 # -483 evaluate in, end, out +483 evaluate in, end, out 484 # -485 var len/eax: int <- value-stack-length out -486 check-ints-equal len, 1, "F - test-eval-arithmetic stack size" -487 var n/xmm0: float <- pop-number-from-value-stack out +485 var len/eax: int <- value-stack-length out +486 check-ints-equal len, 1, "F - test-eval-arithmetic stack size" +487 var n/xmm0: float <- pop-number-from-value-stack out 488 var n2/eax: int <- convert n -489 check-ints-equal n2, 2, "F - test-eval-arithmetic result" +489 check-ints-equal n2, 2, "F - test-eval-arithmetic result" 490 } 491 -492 fn test-eval-string { +492 fn test-eval-string { 493 # in -494 var in-storage: line -495 var in/esi: (addr line) <- address in-storage -496 parse-line "\"abc\"", in # TODO support spaces within strings +494 var in-storage: line +495 var in/esi: (addr line) <- address in-storage +496 parse-line "\"abc\"", in # TODO support spaces within strings 497 # end -498 var w-ah/eax: (addr handle word) <- get in, data -499 var end-h: (handle word) -500 var end-ah/ecx: (addr handle word) <- address end-h -501 final-word w-ah, end-ah -502 var end/eax: (addr word) <- lookup *end-ah +498 var w-ah/eax: (addr handle word) <- get in, data +499 var end-h: (handle word) +500 var end-ah/ecx: (addr handle word) <- address end-h +501 final-word w-ah, end-ah +502 var end/eax: (addr word) <- lookup *end-ah 503 # out -504 var out-storage: value-stack -505 var out/edi: (addr value-stack) <- address out-storage -506 initialize-value-stack out, 8 +504 var out-storage: value-stack +505 var out/edi: (addr value-stack) <- address out-storage +506 initialize-value-stack out, 8 507 # -508 evaluate in, end, out +508 evaluate in, end, out 509 # -510 var len/eax: int <- value-stack-length out -511 check-ints-equal len, 1, "F - test-eval-string stack size" -512 var out-data-ah/eax: (addr handle array value) <- get out, data -513 var out-data/eax: (addr array value) <- lookup *out-data-ah -514 var v/eax: (addr value) <- index out-data, 0 -515 var type/ecx: (addr int) <- get v, type -516 check-ints-equal *type, 1/text, "F - test-eval-string type" -517 var text-ah/eax: (addr handle array byte) <- get v, text-data -518 var text/eax: (addr array byte) <- lookup *text-ah -519 check-strings-equal text, "abc", "F - test-eval-string result" +510 var len/eax: int <- value-stack-length out +511 check-ints-equal len, 1, "F - test-eval-string stack size" +512 var out-data-ah/eax: (addr handle array value) <- get out, data +513 var out-data/eax: (addr array value) <- lookup *out-data-ah +514 var v/eax: (addr value) <- index out-data, 0 +515 var type/ecx: (addr int) <- get v, type +516 check-ints-equal *type, 1/text, "F - test-eval-string type" +517 var text-ah/eax: (addr handle array byte) <- get v, text-data +518 var text/eax: (addr array byte) <- lookup *text-ah +519 check-strings-equal text, "abc", "F - test-eval-string result" 520 } 521 -522 fn test-eval-compare-lesser { +522 fn test-eval-compare-lesser { 523 # in -524 var in-storage: line -525 var in/esi: (addr line) <- address in-storage -526 parse-line "1 2 <", in +524 var in-storage: line +525 var in/esi: (addr line) <- address in-storage +526 parse-line "1 2 <", in 527 # end -528 var w-ah/eax: (addr handle word) <- get in, data -529 var end-h: (handle word) -530 var end-ah/ecx: (addr handle word) <- address end-h -531 final-word w-ah, end-ah -532 var end/eax: (addr word) <- lookup *end-ah +528 var w-ah/eax: (addr handle word) <- get in, data +529 var end-h: (handle word) +530 var end-ah/ecx: (addr handle word) <- address end-h +531 final-word w-ah, end-ah +532 var end/eax: (addr word) <- lookup *end-ah 533 # out -534 var out-storage: value-stack -535 var out/edi: (addr value-stack) <- address out-storage -536 initialize-value-stack out, 8 +534 var out-storage: value-stack +535 var out/edi: (addr value-stack) <- address out-storage +536 initialize-value-stack out, 8 537 # -538 evaluate in, end, out +538 evaluate in, end, out 539 # -540 var len/eax: int <- value-stack-length out -541 check-ints-equal len, 1, "F - test-eval-compare-lesser stack size" -542 var result/eax: boolean <- pop-boolean-from-value-stack out -543 check result, "F - test-eval-compare-lesser result" +540 var len/eax: int <- value-stack-length out +541 check-ints-equal len, 1, "F - test-eval-compare-lesser stack size" +542 var result/eax: boolean <- pop-boolean-from-value-stack out +543 check result, "F - test-eval-compare-lesser result" 544 } 545 -546 fn test-eval-compare-greater { +546 fn test-eval-compare-greater { 547 # in -548 var in-storage: line -549 var in/esi: (addr line) <- address in-storage -550 parse-line "2 1 >", in +548 var in-storage: line +549 var in/esi: (addr line) <- address in-storage +550 parse-line "2 1 >", in 551 # end -552 var w-ah/eax: (addr handle word) <- get in, data -553 var end-h: (handle word) -554 var end-ah/ecx: (addr handle word) <- address end-h -555 final-word w-ah, end-ah -556 var end/eax: (addr word) <- lookup *end-ah +552 var w-ah/eax: (addr handle word) <- get in, data +553 var end-h: (handle word) +554 var end-ah/ecx: (addr handle word) <- address end-h +555 final-word w-ah, end-ah +556 var end/eax: (addr word) <- lookup *end-ah 557 # out -558 var out-storage: value-stack -559 var out/edi: (addr value-stack) <- address out-storage -560 initialize-value-stack out, 8 +558 var out-storage: value-stack +559 var out/edi: (addr value-stack) <- address out-storage +560 initialize-value-stack out, 8 561 # -562 evaluate in, end, out +562 evaluate in, end, out 563 # -564 var len/eax: int <- value-stack-length out -565 check-ints-equal len, 1, "F - test-eval-compare-greater stack size" -566 var result/eax: boolean <- pop-boolean-from-value-stack out -567 check result, "F - test-eval-compare-greater result" +564 var len/eax: int <- value-stack-length out +565 check-ints-equal len, 1, "F - test-eval-compare-greater stack size" +566 var result/eax: boolean <- pop-boolean-from-value-stack out +567 check result, "F - test-eval-compare-greater result" 568 } 569 -570 fn test-eval-compare-equal-fails { +570 fn test-eval-compare-equal-fails { 571 # in -572 var in-storage: line -573 var in/esi: (addr line) <- address in-storage -574 parse-line "1 2 ==", in +572 var in-storage: line +573 var in/esi: (addr line) <- address in-storage +574 parse-line "1 2 ==", in 575 # end -576 var w-ah/eax: (addr handle word) <- get in, data -577 var end-h: (handle word) -578 var end-ah/ecx: (addr handle word) <- address end-h -579 final-word w-ah, end-ah -580 var end/eax: (addr word) <- lookup *end-ah +576 var w-ah/eax: (addr handle word) <- get in, data +577 var end-h: (handle word) +578 var end-ah/ecx: (addr handle word) <- address end-h +579 final-word w-ah, end-ah +580 var end/eax: (addr word) <- lookup *end-ah 581 # out -582 var out-storage: value-stack -583 var out/edi: (addr value-stack) <- address out-storage -584 initialize-value-stack out, 8 +582 var out-storage: value-stack +583 var out/edi: (addr value-stack) <- address out-storage +584 initialize-value-stack out, 8 585 # -586 evaluate in, end, out +586 evaluate in, end, out 587 # -588 var len/eax: int <- value-stack-length out -589 check-ints-equal len, 1, "F - test-eval-compare-equal-fails stack size" -590 var result/eax: boolean <- pop-boolean-from-value-stack out -591 check-not result, "F - test-eval-compare-equal-fails result" +588 var len/eax: int <- value-stack-length out +589 check-ints-equal len, 1, "F - test-eval-compare-equal-fails stack size" +590 var result/eax: boolean <- pop-boolean-from-value-stack out +591 check-not result, "F - test-eval-compare-equal-fails result" 592 } 593 -594 fn test-eval-compare-equal { +594 fn test-eval-compare-equal { 595 # in -596 var in-storage: line -597 var in/esi: (addr line) <- address in-storage -598 parse-line "2 2 ==", in +596 var in-storage: line +597 var in/esi: (addr line) <- address in-storage +598 parse-line "2 2 ==", in 599 # end -600 var w-ah/eax: (addr handle word) <- get in, data -601 var end-h: (handle word) -602 var end-ah/ecx: (addr handle word) <- address end-h -603 final-word w-ah, end-ah -604 var end/eax: (addr word) <- lookup *end-ah +600 var w-ah/eax: (addr handle word) <- get in, data +601 var end-h: (handle word) +602 var end-ah/ecx: (addr handle word) <- address end-h +603 final-word w-ah, end-ah +604 var end/eax: (addr word) <- lookup *end-ah 605 # out -606 var out-storage: value-stack -607 var out/edi: (addr value-stack) <- address out-storage -608 initialize-value-stack out, 8 +606 var out-storage: value-stack +607 var out/edi: (addr value-stack) <- address out-storage +608 initialize-value-stack out, 8 609 # -610 evaluate in, end, out +610 evaluate in, end, out 611 # -612 var len/eax: int <- value-stack-length out -613 check-ints-equal len, 1, "F - test-eval-compare-equal stack size" -614 var result/eax: boolean <- pop-boolean-from-value-stack out -615 check result, "F - test-eval-compare-equal result" +612 var len/eax: int <- value-stack-length out +613 check-ints-equal len, 1, "F - test-eval-compare-equal stack size" +614 var result/eax: boolean <- pop-boolean-from-value-stack out +615 check result, "F - test-eval-compare-equal result" 616 } 617 -618 fn test-eval-conditional { +618 fn test-eval-conditional { 619 # in -620 var in-storage: line -621 var in/esi: (addr line) <- address in-storage -622 parse-line "1 2 < -> 3", in +620 var in-storage: line +621 var in/esi: (addr line) <- address in-storage +622 parse-line "1 2 < -> 3", in 623 # end -624 var w-ah/eax: (addr handle word) <- get in, data -625 var end-h: (handle word) -626 var end-ah/ecx: (addr handle word) <- address end-h -627 final-word w-ah, end-ah -628 var end/eax: (addr word) <- lookup *end-ah +624 var w-ah/eax: (addr handle word) <- get in, data +625 var end-h: (handle word) +626 var end-ah/ecx: (addr handle word) <- address end-h +627 final-word w-ah, end-ah +628 var end/eax: (addr word) <- lookup *end-ah 629 # out -630 var out-storage: value-stack -631 var out/edi: (addr value-stack) <- address out-storage -632 initialize-value-stack out, 8 +630 var out-storage: value-stack +631 var out/edi: (addr value-stack) <- address out-storage +632 initialize-value-stack out, 8 633 # -634 evaluate in, end, out +634 evaluate in, end, out 635 # -636 var len/eax: int <- value-stack-length out -637 check-ints-equal len, 1, "F - test-eval-conditional stack size" -638 var n/xmm0: float <- pop-number-from-value-stack out +636 var len/eax: int <- value-stack-length out +637 check-ints-equal len, 1, "F - test-eval-conditional stack size" +638 var n/xmm0: float <- pop-number-from-value-stack out 639 var n2/eax: int <- convert n -640 check-ints-equal n2, 3, "F - test-eval-conditional result" +640 check-ints-equal n2, 3, "F - test-eval-conditional result" 641 } 642 643 # if top of stack is false, `->` skips one word -644 fn test-eval-conditional-skipped { +644 fn test-eval-conditional-skipped { 645 # in -646 var in-storage: line -647 var in/esi: (addr line) <- address in-storage -648 parse-line "1 2 > -> 3", in +646 var in-storage: line +647 var in/esi: (addr line) <- address in-storage +648 parse-line "1 2 > -> 3", in 649 # end -650 var w-ah/eax: (addr handle word) <- get in, data -651 var end-h: (handle word) -652 var end-ah/ecx: (addr handle word) <- address end-h -653 final-word w-ah, end-ah -654 var end/eax: (addr word) <- lookup *end-ah +650 var w-ah/eax: (addr handle word) <- get in, data +651 var end-h: (handle word) +652 var end-ah/ecx: (addr handle word) <- address end-h +653 final-word w-ah, end-ah +654 var end/eax: (addr word) <- lookup *end-ah 655 # out -656 var out-storage: value-stack -657 var out/edi: (addr value-stack) <- address out-storage -658 initialize-value-stack out, 8 +656 var out-storage: value-stack +657 var out/edi: (addr value-stack) <- address out-storage +658 initialize-value-stack out, 8 659 # -660 evaluate in, end, out +660 evaluate in, end, out 661 # -662 var len/eax: int <- value-stack-length out -663 check-ints-equal len, 0, "F - test-eval-conditional-skipped stack size" +662 var len/eax: int <- value-stack-length out +663 check-ints-equal len, 0, "F - test-eval-conditional-skipped stack size" 664 } 665 666 # curlies have no effect in isolation -667 fn test-eval-group { +667 fn test-eval-group { 668 # in -669 var in-storage: line -670 var in/esi: (addr line) <- address in-storage -671 parse-line "{ 1 } 1 +", in +669 var in-storage: line +670 var in/esi: (addr line) <- address in-storage +671 parse-line "{ 1 } 1 +", in 672 # end -673 var w-ah/eax: (addr handle word) <- get in, data -674 var end-h: (handle word) -675 var end-ah/ecx: (addr handle word) <- address end-h -676 final-word w-ah, end-ah -677 var end/eax: (addr word) <- lookup *end-ah +673 var w-ah/eax: (addr handle word) <- get in, data +674 var end-h: (handle word) +675 var end-ah/ecx: (addr handle word) <- address end-h +676 final-word w-ah, end-ah +677 var end/eax: (addr word) <- lookup *end-ah 678 # out -679 var out-storage: value-stack -680 var out/edi: (addr value-stack) <- address out-storage -681 initialize-value-stack out, 8 +679 var out-storage: value-stack +680 var out/edi: (addr value-stack) <- address out-storage +681 initialize-value-stack out, 8 682 # -683 evaluate in, end, out +683 evaluate in, end, out 684 # -685 var len/eax: int <- value-stack-length out -686 check-ints-equal len, 1, "F - test-eval-group stack size" -687 var n/xmm0: float <- pop-number-from-value-stack out +685 var len/eax: int <- value-stack-length out +686 check-ints-equal len, 1, "F - test-eval-group stack size" +687 var n/xmm0: float <- pop-number-from-value-stack out 688 var n2/eax: int <- convert n -689 check-ints-equal n2, 2, "F - test-eval-group result" +689 check-ints-equal n2, 2, "F - test-eval-group result" 690 } 691 -692 fn test-eval-group-open-at-end { +692 fn test-eval-group-open-at-end { 693 # in -694 var in-storage: line -695 var in/esi: (addr line) <- address in-storage -696 parse-line "1 1 + {", in +694 var in-storage: line +695 var in/esi: (addr line) <- address in-storage +696 parse-line "1 1 + {", in 697 # end -698 var w-ah/eax: (addr handle word) <- get in, data -699 var end-h: (handle word) -700 var end-ah/ecx: (addr handle word) <- address end-h -701 final-word w-ah, end-ah -702 var end/eax: (addr word) <- lookup *end-ah +698 var w-ah/eax: (addr handle word) <- get in, data +699 var end-h: (handle word) +700 var end-ah/ecx: (addr handle word) <- address end-h +701 final-word w-ah, end-ah +702 var end/eax: (addr word) <- lookup *end-ah 703 # out -704 var out-storage: value-stack -705 var out/edi: (addr value-stack) <- address out-storage -706 initialize-value-stack out, 8 +704 var out-storage: value-stack +705 var out/edi: (addr value-stack) <- address out-storage +706 initialize-value-stack out, 8 707 # -708 evaluate in, end, out +708 evaluate in, end, out 709 # -710 var len/eax: int <- value-stack-length out -711 check-ints-equal len, 0, "F - test-eval-group-open-at-end stack size" +710 var len/eax: int <- value-stack-length out +711 check-ints-equal len, 0, "F - test-eval-group-open-at-end stack size" 712 } 713 -714 fn test-eval-group-close-at-end { +714 fn test-eval-group-close-at-end { 715 # in -716 var in-storage: line -717 var in/esi: (addr line) <- address in-storage -718 parse-line "{ 1 1 + }", in +716 var in-storage: line +717 var in/esi: (addr line) <- address in-storage +718 parse-line "{ 1 1 + }", in 719 # end -720 var w-ah/eax: (addr handle word) <- get in, data -721 var end-h: (handle word) -722 var end-ah/ecx: (addr handle word) <- address end-h -723 final-word w-ah, end-ah -724 var end/eax: (addr word) <- lookup *end-ah +720 var w-ah/eax: (addr handle word) <- get in, data +721 var end-h: (handle word) +722 var end-ah/ecx: (addr handle word) <- address end-h +723 final-word w-ah, end-ah +724 var end/eax: (addr word) <- lookup *end-ah 725 # out -726 var out-storage: value-stack -727 var out/edi: (addr value-stack) <- address out-storage -728 initialize-value-stack out, 8 +726 var out-storage: value-stack +727 var out/edi: (addr value-stack) <- address out-storage +728 initialize-value-stack out, 8 729 # -730 evaluate in, end, out +730 evaluate in, end, out 731 # -732 var len/eax: int <- value-stack-length out -733 check-ints-equal len, 0, "F - test-eval-group-close-at-end stack size" +732 var len/eax: int <- value-stack-length out +733 check-ints-equal len, 0, "F - test-eval-group-close-at-end stack size" 734 } 735 -736 fn test-eval-conditional-skips-group { +736 fn test-eval-conditional-skips-group { 737 # in -738 var in-storage: line -739 var in/esi: (addr line) <- address in-storage -740 parse-line "1 2 > -> { 3 } 9", in +738 var in-storage: line +739 var in/esi: (addr line) <- address in-storage +740 parse-line "1 2 > -> { 3 } 9", in 741 # end -742 var w-ah/eax: (addr handle word) <- get in, data -743 var end-h: (handle word) -744 var end-ah/ecx: (addr handle word) <- address end-h -745 final-word w-ah, end-ah -746 var end/eax: (addr word) <- lookup *end-ah +742 var w-ah/eax: (addr handle word) <- get in, data +743 var end-h: (handle word) +744 var end-ah/ecx: (addr handle word) <- address end-h +745 final-word w-ah, end-ah +746 var end/eax: (addr word) <- lookup *end-ah 747 # out -748 var out-storage: value-stack -749 var out/edi: (addr value-stack) <- address out-storage -750 initialize-value-stack out, 8 +748 var out-storage: value-stack +749 var out/edi: (addr value-stack) <- address out-storage +750 initialize-value-stack out, 8 751 # -752 evaluate in, end, out +752 evaluate in, end, out 753 # out contains just the final sentinel '9' -754 var len/eax: int <- value-stack-length out -755 check-ints-equal len, 1, "F - test-eval-conditional-skips-group stack size" +754 var len/eax: int <- value-stack-length out +755 check-ints-equal len, 1, "F - test-eval-conditional-skips-group stack size" 756 } 757 -758 fn test-eval-conditional-skips-nested-group { +758 fn test-eval-conditional-skips-nested-group { 759 # in -760 var in-storage: line -761 var in/esi: (addr line) <- address in-storage -762 parse-line "1 2 > -> { { 3 } 4 } 9", in +760 var in-storage: line +761 var in/esi: (addr line) <- address in-storage +762 parse-line "1 2 > -> { { 3 } 4 } 9", in 763 # end -764 var w-ah/eax: (addr handle word) <- get in, data -765 var end-h: (handle word) -766 var end-ah/ecx: (addr handle word) <- address end-h -767 final-word w-ah, end-ah -768 var end/eax: (addr word) <- lookup *end-ah +764 var w-ah/eax: (addr handle word) <- get in, data +765 var end-h: (handle word) +766 var end-ah/ecx: (addr handle word) <- address end-h +767 final-word w-ah, end-ah +768 var end/eax: (addr word) <- lookup *end-ah 769 # out -770 var out-storage: value-stack -771 var out/edi: (addr value-stack) <- address out-storage -772 initialize-value-stack out, 8 +770 var out-storage: value-stack +771 var out/edi: (addr value-stack) <- address out-storage +772 initialize-value-stack out, 8 773 # -774 evaluate in, end, out +774 evaluate in, end, out 775 # out contains just the final sentinel '9' -776 var len/eax: int <- value-stack-length out -777 check-ints-equal len, 1, "F - test-eval-conditional-skips-nested-group stack size" +776 var len/eax: int <- value-stack-length out +777 check-ints-equal len, 1, "F - test-eval-conditional-skips-nested-group stack size" 778 } 779 780 # TODO: test error-handling on: 781 # 1 2 > -> } 782 783 # break skips to next containing `}` -784 fn test-eval-break { +784 fn test-eval-break { 785 # in -786 var in-storage: line -787 var in/esi: (addr line) <- address in-storage -788 parse-line "3 { 4 break 5 } +", in +786 var in-storage: line +787 var in/esi: (addr line) <- address in-storage +788 parse-line "3 { 4 break 5 } +", in 789 # end -790 var w-ah/eax: (addr handle word) <- get in, data -791 var end-h: (handle word) -792 var end-ah/ecx: (addr handle word) <- address end-h -793 final-word w-ah, end-ah -794 var end/eax: (addr word) <- lookup *end-ah +790 var w-ah/eax: (addr handle word) <- get in, data +791 var end-h: (handle word) +792 var end-ah/ecx: (addr handle word) <- address end-h +793 final-word w-ah, end-ah +794 var end/eax: (addr word) <- lookup *end-ah 795 # out -796 var out-storage: value-stack -797 var out/edi: (addr value-stack) <- address out-storage -798 initialize-value-stack out, 8 +796 var out-storage: value-stack +797 var out/edi: (addr value-stack) <- address out-storage +798 initialize-value-stack out, 8 799 # -800 evaluate in, end, out +800 evaluate in, end, out 801 # result is 3+4, not 4+5 -802 var len/eax: int <- value-stack-length out -803 check-ints-equal len, 1, "F - test-eval-break stack size" -804 var n/xmm0: float <- pop-number-from-value-stack out +802 var len/eax: int <- value-stack-length out +803 check-ints-equal len, 1, "F - test-eval-break stack size" +804 var n/xmm0: float <- pop-number-from-value-stack out 805 var n2/eax: int <- convert n -806 check-ints-equal n2, 7, "F - test-eval-break result" +806 check-ints-equal n2, 7, "F - test-eval-break result" 807 } 808 -809 fn test-eval-break-nested { +809 fn test-eval-break-nested { 810 # in -811 var in-storage: line -812 var in/esi: (addr line) <- address in-storage -813 parse-line "3 { 4 break { 5 } 6 } +", in +811 var in-storage: line +812 var in/esi: (addr line) <- address in-storage +813 parse-line "3 { 4 break { 5 } 6 } +", in 814 # end -815 var w-ah/eax: (addr handle word) <- get in, data -816 var end-h: (handle word) -817 var end-ah/ecx: (addr handle word) <- address end-h -818 final-word w-ah, end-ah -819 var end/eax: (addr word) <- lookup *end-ah +815 var w-ah/eax: (addr handle word) <- get in, data +816 var end-h: (handle word) +817 var end-ah/ecx: (addr handle word) <- address end-h +818 final-word w-ah, end-ah +819 var end/eax: (addr word) <- lookup *end-ah 820 # out -821 var out-storage: value-stack -822 var out/edi: (addr value-stack) <- address out-storage -823 initialize-value-stack out, 8 +821 var out-storage: value-stack +822 var out/edi: (addr value-stack) <- address out-storage +823 initialize-value-stack out, 8 824 # -825 evaluate in, end, out +825 evaluate in, end, out 826 # result is 3+4, skipping remaining numbers -827 var len/eax: int <- value-stack-length out -828 check-ints-equal len, 1, "F - test-eval-break-nested stack size" -829 var n/xmm0: float <- pop-number-from-value-stack out +827 var len/eax: int <- value-stack-length out +828 check-ints-equal len, 1, "F - test-eval-break-nested stack size" +829 var n/xmm0: float <- pop-number-from-value-stack out 830 var n2/eax: int <- convert n -831 check-ints-equal n2, 7, "F - test-eval-break-nested result" +831 check-ints-equal n2, 7, "F - test-eval-break-nested result" 832 } 833 834 #? 1 2 3 4 6 5 { < -> break loop } @@ -908,102 +908,102 @@ if ('onhashchange' in window) { 848 849 # loop skips to previous containing `{` and continues evaluating until control 850 # leaves the group -851 fn test-eval-loop { +851 fn test-eval-loop { 852 # in -853 var in-storage: line -854 var in/esi: (addr line) <- address in-storage -855 parse-line "1 2 4 3 { < -> break loop } 9", in +853 var in-storage: line +854 var in/esi: (addr line) <- address in-storage +855 parse-line "1 2 4 3 { < -> break loop } 9", in 856 # end -857 var w-ah/eax: (addr handle word) <- get in, data -858 var end-h: (handle word) -859 var end-ah/ecx: (addr handle word) <- address end-h -860 final-word w-ah, end-ah -861 var end/eax: (addr word) <- lookup *end-ah +857 var w-ah/eax: (addr handle word) <- get in, data +858 var end-h: (handle word) +859 var end-ah/ecx: (addr handle word) <- address end-h +860 final-word w-ah, end-ah +861 var end/eax: (addr word) <- lookup *end-ah 862 # out -863 var out-storage: value-stack -864 var out/edi: (addr value-stack) <- address out-storage -865 initialize-value-stack out, 8 +863 var out-storage: value-stack +864 var out/edi: (addr value-stack) <- address out-storage +865 initialize-value-stack out, 8 866 # -867 evaluate in, end, out +867 evaluate in, end, out 868 # evaluation order: 1 2 4 3 { < -> loop { < -> break 9 869 # stack contents: 9 -870 var len/eax: int <- value-stack-length out -871 check-ints-equal len, 1, "F - test-eval-loop stack size" +870 var len/eax: int <- value-stack-length out +871 check-ints-equal len, 1, "F - test-eval-loop stack size" 872 } 873 -874 fn test-eval-loop-2 { +874 fn test-eval-loop-2 { 875 # in -876 var in-storage: line -877 var in/esi: (addr line) <- address in-storage -878 parse-line "1 2 4 3 { 4 == -> break loop } 9", in +876 var in-storage: line +877 var in/esi: (addr line) <- address in-storage +878 parse-line "1 2 4 3 { 4 == -> break loop } 9", in 879 # end -880 var w-ah/eax: (addr handle word) <- get in, data -881 var end-h: (handle word) -882 var end-ah/ecx: (addr handle word) <- address end-h -883 final-word w-ah, end-ah -884 var end/eax: (addr word) <- lookup *end-ah +880 var w-ah/eax: (addr handle word) <- get in, data +881 var end-h: (handle word) +882 var end-ah/ecx: (addr handle word) <- address end-h +883 final-word w-ah, end-ah +884 var end/eax: (addr word) <- lookup *end-ah 885 # out -886 var out-storage: value-stack -887 var out/edi: (addr value-stack) <- address out-storage -888 initialize-value-stack out, 8 +886 var out-storage: value-stack +887 var out/edi: (addr value-stack) <- address out-storage +888 initialize-value-stack out, 8 889 # -890 evaluate in, end, out +890 evaluate in, end, out 891 # evaluation order: 1 2 4 3 { 4 == -> loop { 4 == -> break 9 892 # stack contents: 1 2 9 893 #? dump-stack out -894 var len/eax: int <- value-stack-length out +894 var len/eax: int <- value-stack-length out 895 #? draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, len, 0xc/red, 0/black -896 check-ints-equal len, 3, "F - test-eval-loop-2 stack size" +896 check-ints-equal len, 3, "F - test-eval-loop-2 stack size" 897 } 898 -899 fn test-eval-loop-conditional { +899 fn test-eval-loop-conditional { 900 # in -901 var in-storage: line -902 var in/esi: (addr line) <- address in-storage -903 parse-line "1 2 3 { 3 == -> loop } 9", in +901 var in-storage: line +902 var in/esi: (addr line) <- address in-storage +903 parse-line "1 2 3 { 3 == -> loop } 9", in 904 # end -905 var w-ah/eax: (addr handle word) <- get in, data -906 var end-h: (handle word) -907 var end-ah/ecx: (addr handle word) <- address end-h -908 final-word w-ah, end-ah -909 var end/eax: (addr word) <- lookup *end-ah +905 var w-ah/eax: (addr handle word) <- get in, data +906 var end-h: (handle word) +907 var end-ah/ecx: (addr handle word) <- address end-h +908 final-word w-ah, end-ah +909 var end/eax: (addr word) <- lookup *end-ah 910 # out -911 var out-storage: value-stack -912 var out/edi: (addr value-stack) <- address out-storage -913 initialize-value-stack out, 8 +911 var out-storage: value-stack +912 var out/edi: (addr value-stack) <- address out-storage +913 initialize-value-stack out, 8 914 # -915 evaluate in, end, out +915 evaluate in, end, out 916 # evaluation order: 1 2 3 { 3 == -> loop { 3 == -> 9 917 # stack contents: 1 9 918 #? dump-stack out -919 var len/eax: int <- value-stack-length out +919 var len/eax: int <- value-stack-length out 920 #? draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, len, 0xc/red, 0/black -921 check-ints-equal len, 2, "F - test-eval-loop-2-conditional stack size" +921 check-ints-equal len, 2, "F - test-eval-loop-2-conditional stack size" 922 } 923 -924 fn test-eval-loop-with-words-after-in-group { +924 fn test-eval-loop-with-words-after-in-group { 925 # in -926 var in-storage: line -927 var in/esi: (addr line) <- address in-storage -928 parse-line "1 2 3 { 3 == -> loop 37 } 9", in +926 var in-storage: line +927 var in/esi: (addr line) <- address in-storage +928 parse-line "1 2 3 { 3 == -> loop 37 } 9", in 929 # end -930 var w-ah/eax: (addr handle word) <- get in, data -931 var end-h: (handle word) -932 var end-ah/ecx: (addr handle word) <- address end-h -933 final-word w-ah, end-ah -934 var end/eax: (addr word) <- lookup *end-ah +930 var w-ah/eax: (addr handle word) <- get in, data +931 var end-h: (handle word) +932 var end-ah/ecx: (addr handle word) <- address end-h +933 final-word w-ah, end-ah +934 var end/eax: (addr word) <- lookup *end-ah 935 # out -936 var out-storage: value-stack -937 var out/edi: (addr value-stack) <- address out-storage -938 initialize-value-stack out, 8 +936 var out-storage: value-stack +937 var out/edi: (addr value-stack) <- address out-storage +938 initialize-value-stack out, 8 939 # -940 evaluate in, end, out +940 evaluate in, end, out 941 # evaluation order: 1 2 3 { 3 == -> loop { 3 == -> 37 } 9 942 # stack contents: 1 37 9 943 #? dump-stack out -944 var len/eax: int <- value-stack-length out +944 var len/eax: int <- value-stack-length out 945 #? draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, len, 0xc/red, 0/black -946 check-ints-equal len, 3, "F - test-eval-loop-with-words-after-in-group stack size" +946 check-ints-equal len, 3, "F - test-eval-loop-with-words-after-in-group stack size" 947 } diff --git a/html/baremetal/shell/gap-buffer.mu.html b/html/baremetal/shell/gap-buffer.mu.html index c970b830..9a84a565 100644 --- a/html/baremetal/shell/gap-buffer.mu.html +++ b/html/baremetal/shell/gap-buffer.mu.html @@ -60,76 +60,76 @@ if ('onhashchange' in window) { 1 # primitive for editing a single word 2 # parameter: max-word-size = 16 graphemes 3 - 4 type gap-buffer { - 5 left: grapheme-stack - 6 right: grapheme-stack + 4 type gap-buffer { + 5 left: grapheme-stack + 6 right: grapheme-stack 7 } 8 - 9 fn initialize-gap-buffer _self: (addr gap-buffer) { - 10 var self/esi: (addr gap-buffer) <- copy _self - 11 var left/eax: (addr grapheme-stack) <- get self, left - 12 initialize-grapheme-stack left, 0x10/max-word-size - 13 var right/eax: (addr grapheme-stack) <- get self, right - 14 initialize-grapheme-stack right, 0x10/max-word-size + 9 fn initialize-gap-buffer _self: (addr gap-buffer) { + 10 var self/esi: (addr gap-buffer) <- copy _self + 11 var left/eax: (addr grapheme-stack) <- get self, left + 12 initialize-grapheme-stack left, 0x10/max-word-size + 13 var right/eax: (addr grapheme-stack) <- get self, right + 14 initialize-grapheme-stack right, 0x10/max-word-size 15 } 16 17 # just for tests - 18 fn initialize-gap-buffer-with self: (addr gap-buffer), s: (addr array byte) { - 19 initialize-gap-buffer self + 18 fn initialize-gap-buffer-with self: (addr gap-buffer), s: (addr array byte) { + 19 initialize-gap-buffer self 20 var stream-storage: (stream byte 0x10/max-word-size) 21 var stream/ecx: (addr stream byte) <- address stream-storage - 22 write stream, s + 22 write stream, s 23 { - 24 var done?/eax: boolean <- stream-empty? stream + 24 var done?/eax: boolean <- stream-empty? stream 25 compare done?, 0/false 26 break-if-!= - 27 var g/eax: grapheme <- read-grapheme stream - 28 add-grapheme-at-gap self, g + 27 var g/eax: grapheme <- read-grapheme stream + 28 add-grapheme-at-gap self, g 29 loop 30 } 31 } 32 - 33 fn emit-gap-buffer _self: (addr gap-buffer), out: (addr stream byte) { - 34 var self/esi: (addr gap-buffer) <- copy _self - 35 clear-stream out - 36 var left/eax: (addr grapheme-stack) <- get self, left - 37 emit-stack-from-bottom left, out - 38 var right/eax: (addr grapheme-stack) <- get self, right - 39 emit-stack-from-top right, out + 33 fn emit-gap-buffer _self: (addr gap-buffer), out: (addr stream byte) { + 34 var self/esi: (addr gap-buffer) <- copy _self + 35 clear-stream out + 36 var left/eax: (addr grapheme-stack) <- get self, left + 37 emit-stack-from-bottom left, out + 38 var right/eax: (addr grapheme-stack) <- get self, right + 39 emit-stack-from-top right, out 40 } 41 42 # dump stack from bottom to top - 43 fn emit-stack-from-bottom _self: (addr grapheme-stack), out: (addr stream byte) { - 44 var self/esi: (addr grapheme-stack) <- copy _self - 45 var data-ah/edi: (addr handle array grapheme) <- get self, data - 46 var _data/eax: (addr array grapheme) <- lookup *data-ah + 43 fn emit-stack-from-bottom _self: (addr grapheme-stack), out: (addr stream byte) { + 44 var self/esi: (addr grapheme-stack) <- copy _self + 45 var data-ah/edi: (addr handle array grapheme) <- get self, data + 46 var _data/eax: (addr array grapheme) <- lookup *data-ah 47 var data/edi: (addr array grapheme) <- copy _data - 48 var top-addr/ecx: (addr int) <- get self, top + 48 var top-addr/ecx: (addr int) <- get self, top 49 var i/eax: int <- copy 0 50 { 51 compare i, *top-addr 52 break-if->= 53 var g/edx: (addr grapheme) <- index data, i - 54 write-grapheme out, *g + 54 write-grapheme out, *g 55 i <- increment 56 loop 57 } 58 } 59 60 # dump stack from top to bottom - 61 fn emit-stack-from-top _self: (addr grapheme-stack), out: (addr stream byte) { - 62 var self/esi: (addr grapheme-stack) <- copy _self - 63 var data-ah/edi: (addr handle array grapheme) <- get self, data - 64 var _data/eax: (addr array grapheme) <- lookup *data-ah + 61 fn emit-stack-from-top _self: (addr grapheme-stack), out: (addr stream byte) { + 62 var self/esi: (addr grapheme-stack) <- copy _self + 63 var data-ah/edi: (addr handle array grapheme) <- get self, data + 64 var _data/eax: (addr array grapheme) <- lookup *data-ah 65 var data/edi: (addr array grapheme) <- copy _data - 66 var top-addr/ecx: (addr int) <- get self, top + 66 var top-addr/ecx: (addr int) <- get self, top 67 var i/eax: int <- copy *top-addr 68 i <- decrement 69 { 70 compare i, 0 71 break-if-< 72 var g/edx: (addr grapheme) <- index data, i - 73 write-grapheme out, *g + 73 write-grapheme out, *g 74 i <- decrement 75 loop 76 } @@ -137,12 +137,12 @@ if ('onhashchange' in window) { 78 79 # We implicitly render everything editable in a single color, and assume the 80 # cursor is a single other color. - 81 fn render-gap-buffer screen: (addr screen), _gap: (addr gap-buffer), x: int, y: int, render-cursor?: boolean -> _/eax: int { - 82 var gap/esi: (addr gap-buffer) <- copy _gap - 83 var left/eax: (addr grapheme-stack) <- get gap, left - 84 var x2/eax: int <- render-stack-from-bottom screen, left, x, y - 85 var right/ecx: (addr grapheme-stack) <- get gap, right - 86 x2 <- render-stack-from-top screen, right, x2, y, render-cursor? + 81 fn render-gap-buffer screen: (addr screen), _gap: (addr gap-buffer), x: int, y: int, render-cursor?: boolean -> _/eax: int { + 82 var gap/esi: (addr gap-buffer) <- copy _gap + 83 var left/eax: (addr grapheme-stack) <- get gap, left + 84 var x2/eax: int <- render-stack-from-bottom screen, left, x, y + 85 var right/ecx: (addr grapheme-stack) <- get gap, right + 86 x2 <- render-stack-from-top screen, right, x2, y, render-cursor? 87 var x3/ebx: int <- copy x2 88 # decide whether we still need to print a cursor 89 var bg/edx: int <- copy 0 @@ -150,256 +150,256 @@ if ('onhashchange' in window) { 91 { 92 break-if-= 93 # if the right side is empty, grapheme stack didn't print the cursor - 94 var empty?/eax: boolean <- grapheme-stack-empty? right + 94 var empty?/eax: boolean <- grapheme-stack-empty? right 95 compare empty?, 0/false 96 break-if-= 97 bg <- copy 7/cursor 98 } 99 # print a grapheme either way so that cursor position doesn't affect printed width 100 var space/eax: grapheme <- copy 0x20 -101 draw-grapheme screen, space, x3, y, 3/fg=cyan, bg +101 draw-grapheme screen, space, x3, y, 3/fg=cyan, bg 102 x3 <- increment 103 return x3 104 } 105 -106 fn gap-buffer-length _gap: (addr gap-buffer) -> _/eax: int { -107 var gap/esi: (addr gap-buffer) <- copy _gap -108 var left/eax: (addr grapheme-stack) <- get gap, left -109 var tmp/eax: (addr int) <- get left, top +106 fn gap-buffer-length _gap: (addr gap-buffer) -> _/eax: int { +107 var gap/esi: (addr gap-buffer) <- copy _gap +108 var left/eax: (addr grapheme-stack) <- get gap, left +109 var tmp/eax: (addr int) <- get left, top 110 var left-length/ecx: int <- copy *tmp -111 var right/esi: (addr grapheme-stack) <- get gap, right -112 tmp <- get right, top +111 var right/esi: (addr grapheme-stack) <- get gap, right +112 tmp <- get right, top 113 var result/eax: int <- copy *tmp 114 result <- add left-length 115 return result 116 } 117 -118 fn add-grapheme-at-gap _self: (addr gap-buffer), g: grapheme { -119 var self/esi: (addr gap-buffer) <- copy _self -120 var left/eax: (addr grapheme-stack) <- get self, left -121 push-grapheme-stack left, g +118 fn add-grapheme-at-gap _self: (addr gap-buffer), g: grapheme { +119 var self/esi: (addr gap-buffer) <- copy _self +120 var left/eax: (addr grapheme-stack) <- get self, left +121 push-grapheme-stack left, g 122 } 123 -124 fn gap-to-start self: (addr gap-buffer) { +124 fn gap-to-start self: (addr gap-buffer) { 125 { -126 var curr/eax: grapheme <- gap-left self +126 var curr/eax: grapheme <- gap-left self 127 compare curr, -1 128 loop-if-!= 129 } 130 } 131 -132 fn gap-to-end self: (addr gap-buffer) { +132 fn gap-to-end self: (addr gap-buffer) { 133 { -134 var curr/eax: grapheme <- gap-right self +134 var curr/eax: grapheme <- gap-right self 135 compare curr, -1 136 loop-if-!= 137 } 138 } 139 -140 fn gap-at-start? _self: (addr gap-buffer) -> _/eax: boolean { -141 var self/esi: (addr gap-buffer) <- copy _self -142 var left/eax: (addr grapheme-stack) <- get self, left -143 var result/eax: boolean <- grapheme-stack-empty? left +140 fn gap-at-start? _self: (addr gap-buffer) -> _/eax: boolean { +141 var self/esi: (addr gap-buffer) <- copy _self +142 var left/eax: (addr grapheme-stack) <- get self, left +143 var result/eax: boolean <- grapheme-stack-empty? left 144 return result 145 } 146 -147 fn gap-at-end? _self: (addr gap-buffer) -> _/eax: boolean { -148 var self/esi: (addr gap-buffer) <- copy _self -149 var right/eax: (addr grapheme-stack) <- get self, right -150 var result/eax: boolean <- grapheme-stack-empty? right +147 fn gap-at-end? _self: (addr gap-buffer) -> _/eax: boolean { +148 var self/esi: (addr gap-buffer) <- copy _self +149 var right/eax: (addr grapheme-stack) <- get self, right +150 var result/eax: boolean <- grapheme-stack-empty? right 151 return result 152 } 153 -154 fn gap-right _self: (addr gap-buffer) -> _/eax: grapheme { -155 var self/esi: (addr gap-buffer) <- copy _self +154 fn gap-right _self: (addr gap-buffer) -> _/eax: grapheme { +155 var self/esi: (addr gap-buffer) <- copy _self 156 var g/eax: grapheme <- copy 0 -157 var right/ecx: (addr grapheme-stack) <- get self, right -158 g <- pop-grapheme-stack right +157 var right/ecx: (addr grapheme-stack) <- get self, right +158 g <- pop-grapheme-stack right 159 compare g, -1 160 { 161 break-if-= -162 var left/ecx: (addr grapheme-stack) <- get self, left -163 push-grapheme-stack left, g +162 var left/ecx: (addr grapheme-stack) <- get self, left +163 push-grapheme-stack left, g 164 } 165 return g 166 } 167 -168 fn gap-left _self: (addr gap-buffer) -> _/eax: grapheme { -169 var self/esi: (addr gap-buffer) <- copy _self +168 fn gap-left _self: (addr gap-buffer) -> _/eax: grapheme { +169 var self/esi: (addr gap-buffer) <- copy _self 170 var g/eax: grapheme <- copy 0 171 { -172 var left/ecx: (addr grapheme-stack) <- get self, left -173 g <- pop-grapheme-stack left +172 var left/ecx: (addr grapheme-stack) <- get self, left +173 g <- pop-grapheme-stack left 174 } 175 compare g, -1 176 { 177 break-if-= -178 var right/ecx: (addr grapheme-stack) <- get self, right -179 push-grapheme-stack right, g +178 var right/ecx: (addr grapheme-stack) <- get self, right +179 push-grapheme-stack right, g 180 } 181 return g 182 } 183 -184 fn index-of-gap _self: (addr gap-buffer) -> _/eax: int { -185 var self/eax: (addr gap-buffer) <- copy _self -186 var left/eax: (addr grapheme-stack) <- get self, left -187 var top-addr/eax: (addr int) <- get left, top +184 fn index-of-gap _self: (addr gap-buffer) -> _/eax: int { +185 var self/eax: (addr gap-buffer) <- copy _self +186 var left/eax: (addr grapheme-stack) <- get self, left +187 var top-addr/eax: (addr int) <- get left, top 188 var result/eax: int <- copy *top-addr 189 return result 190 } 191 -192 fn first-grapheme-in-gap-buffer _self: (addr gap-buffer) -> _/eax: grapheme { -193 var self/esi: (addr gap-buffer) <- copy _self +192 fn first-grapheme-in-gap-buffer _self: (addr gap-buffer) -> _/eax: grapheme { +193 var self/esi: (addr gap-buffer) <- copy _self 194 # try to read from left -195 var left/eax: (addr grapheme-stack) <- get self, left -196 var top-addr/ecx: (addr int) <- get left, top +195 var left/eax: (addr grapheme-stack) <- get self, left +196 var top-addr/ecx: (addr int) <- get left, top 197 compare *top-addr, 0 198 { 199 break-if-<= -200 var data-ah/eax: (addr handle array grapheme) <- get left, data -201 var data/eax: (addr array grapheme) <- lookup *data-ah +200 var data-ah/eax: (addr handle array grapheme) <- get left, data +201 var data/eax: (addr array grapheme) <- lookup *data-ah 202 var result-addr/eax: (addr grapheme) <- index data, 0 203 return *result-addr 204 } 205 # try to read from right -206 var right/eax: (addr grapheme-stack) <- get self, right -207 top-addr <- get right, top +206 var right/eax: (addr grapheme-stack) <- get self, right +207 top-addr <- get right, top 208 compare *top-addr, 0 209 { 210 break-if-<= -211 var data-ah/eax: (addr handle array grapheme) <- get right, data -212 var data/eax: (addr array grapheme) <- lookup *data-ah -213 var top/ecx: int <- copy *top-addr -214 top <- decrement -215 var result-addr/eax: (addr grapheme) <- index data, top +211 var data-ah/eax: (addr handle array grapheme) <- get right, data +212 var data/eax: (addr array grapheme) <- lookup *data-ah +213 var top/ecx: int <- copy *top-addr +214 top <- decrement +215 var result-addr/eax: (addr grapheme) <- index data, top 216 return *result-addr 217 } 218 # give up 219 return -1 220 } 221 -222 fn grapheme-before-cursor-in-gap-buffer _self: (addr gap-buffer) -> _/eax: grapheme { -223 var self/esi: (addr gap-buffer) <- copy _self +222 fn grapheme-before-cursor-in-gap-buffer _self: (addr gap-buffer) -> _/eax: grapheme { +223 var self/esi: (addr gap-buffer) <- copy _self 224 # try to read from left -225 var left/ecx: (addr grapheme-stack) <- get self, left -226 var top-addr/edx: (addr int) <- get left, top +225 var left/ecx: (addr grapheme-stack) <- get self, left +226 var top-addr/edx: (addr int) <- get left, top 227 compare *top-addr, 0 228 { 229 break-if-<= -230 var result/eax: grapheme <- pop-grapheme-stack left -231 push-grapheme-stack left, result +230 var result/eax: grapheme <- pop-grapheme-stack left +231 push-grapheme-stack left, result 232 return result 233 } 234 # give up 235 return -1 236 } 237 -238 fn delete-before-gap _self: (addr gap-buffer) { -239 var self/eax: (addr gap-buffer) <- copy _self -240 var left/eax: (addr grapheme-stack) <- get self, left -241 var dummy/eax: grapheme <- pop-grapheme-stack left +238 fn delete-before-gap _self: (addr gap-buffer) { +239 var self/eax: (addr gap-buffer) <- copy _self +240 var left/eax: (addr grapheme-stack) <- get self, left +241 var dummy/eax: grapheme <- pop-grapheme-stack left 242 } 243 -244 fn pop-after-gap _self: (addr gap-buffer) -> _/eax: grapheme { -245 var self/eax: (addr gap-buffer) <- copy _self -246 var right/eax: (addr grapheme-stack) <- get self, right -247 var result/eax: grapheme <- pop-grapheme-stack right +244 fn pop-after-gap _self: (addr gap-buffer) -> _/eax: grapheme { +245 var self/eax: (addr gap-buffer) <- copy _self +246 var right/eax: (addr grapheme-stack) <- get self, right +247 var result/eax: grapheme <- pop-grapheme-stack right 248 return result 249 } 250 -251 fn gap-buffer-equal? _self: (addr gap-buffer), s: (addr array byte) -> _/eax: boolean { -252 var self/esi: (addr gap-buffer) <- copy _self +251 fn gap-buffer-equal? _self: (addr gap-buffer), s: (addr array byte) -> _/eax: boolean { +252 var self/esi: (addr gap-buffer) <- copy _self 253 # complication: graphemes may be multiple bytes 254 # so don't rely on length 255 # instead turn the expected result into a stream and arrange to read from it in order 256 var stream-storage: (stream byte 0x10/max-word-size) 257 var expected-stream/ecx: (addr stream byte) <- address stream-storage -258 write expected-stream, s +258 write expected-stream, s 259 # compare left -260 var left/edx: (addr grapheme-stack) <- get self, left -261 var result/eax: boolean <- prefix-match? left, expected-stream +260 var left/edx: (addr grapheme-stack) <- get self, left +261 var result/eax: boolean <- prefix-match? left, expected-stream 262 compare result, 0/false 263 { 264 break-if-!= 265 return result 266 } 267 # compare right -268 var right/edx: (addr grapheme-stack) <- get self, right -269 result <- suffix-match? right, expected-stream +268 var right/edx: (addr grapheme-stack) <- get self, right +269 result <- suffix-match? right, expected-stream 270 compare result, 0/false 271 { 272 break-if-!= 273 return result 274 } 275 # ensure there's nothing left over -276 result <- stream-empty? expected-stream +276 result <- stream-empty? expected-stream 277 return result 278 } 279 -280 fn test-gap-buffer-equal-from-end { -281 var _g: gap-buffer -282 var g/esi: (addr gap-buffer) <- address _g -283 initialize-gap-buffer g +280 fn test-gap-buffer-equal-from-end { +281 var _g: gap-buffer +282 var g/esi: (addr gap-buffer) <- address _g +283 initialize-gap-buffer g 284 # 285 var c/eax: grapheme <- copy 0x61/a -286 add-grapheme-at-gap g, c -287 add-grapheme-at-gap g, c -288 add-grapheme-at-gap g, c +286 add-grapheme-at-gap g, c +287 add-grapheme-at-gap g, c +288 add-grapheme-at-gap g, c 289 # gap is at end (right is empty) -290 var result/eax: boolean <- gap-buffer-equal? g, "aaa" -291 check result, "F - test-gap-buffer-equal-from-end" +290 var result/eax: boolean <- gap-buffer-equal? g, "aaa" +291 check result, "F - test-gap-buffer-equal-from-end" 292 } 293 -294 fn test-gap-buffer-equal-from-middle { -295 var _g: gap-buffer -296 var g/esi: (addr gap-buffer) <- address _g -297 initialize-gap-buffer g +294 fn test-gap-buffer-equal-from-middle { +295 var _g: gap-buffer +296 var g/esi: (addr gap-buffer) <- address _g +297 initialize-gap-buffer g 298 # 299 var c/eax: grapheme <- copy 0x61/a -300 add-grapheme-at-gap g, c -301 add-grapheme-at-gap g, c -302 add-grapheme-at-gap g, c -303 var dummy/eax: grapheme <- gap-left g +300 add-grapheme-at-gap g, c +301 add-grapheme-at-gap g, c +302 add-grapheme-at-gap g, c +303 var dummy/eax: grapheme <- gap-left g 304 # gap is in the middle -305 var result/eax: boolean <- gap-buffer-equal? g, "aaa" -306 check result, "F - test-gap-buffer-equal-from-middle" +305 var result/eax: boolean <- gap-buffer-equal? g, "aaa" +306 check result, "F - test-gap-buffer-equal-from-middle" 307 } 308 -309 fn test-gap-buffer-equal-from-start { -310 var _g: gap-buffer -311 var g/esi: (addr gap-buffer) <- address _g -312 initialize-gap-buffer g +309 fn test-gap-buffer-equal-from-start { +310 var _g: gap-buffer +311 var g/esi: (addr gap-buffer) <- address _g +312 initialize-gap-buffer g 313 # 314 var c/eax: grapheme <- copy 0x61/a -315 add-grapheme-at-gap g, c -316 add-grapheme-at-gap g, c -317 add-grapheme-at-gap g, c -318 var dummy/eax: grapheme <- gap-left g -319 dummy <- gap-left g -320 dummy <- gap-left g +315 add-grapheme-at-gap g, c +316 add-grapheme-at-gap g, c +317 add-grapheme-at-gap g, c +318 var dummy/eax: grapheme <- gap-left g +319 dummy <- gap-left g +320 dummy <- gap-left g 321 # gap is at the start -322 var result/eax: boolean <- gap-buffer-equal? g, "aaa" -323 check result, "F - test-gap-buffer-equal-from-start" +322 var result/eax: boolean <- gap-buffer-equal? g, "aaa" +323 check result, "F - test-gap-buffer-equal-from-start" 324 } 325 -326 fn test-gap-buffer-equal-fails { +326 fn test-gap-buffer-equal-fails { 327 # g = "aaa" -328 var _g: gap-buffer -329 var g/esi: (addr gap-buffer) <- address _g -330 initialize-gap-buffer g +328 var _g: gap-buffer +329 var g/esi: (addr gap-buffer) <- address _g +330 initialize-gap-buffer g 331 var c/eax: grapheme <- copy 0x61/a -332 add-grapheme-at-gap g, c -333 add-grapheme-at-gap g, c -334 add-grapheme-at-gap g, c +332 add-grapheme-at-gap g, c +333 add-grapheme-at-gap g, c +334 add-grapheme-at-gap g, c 335 # -336 var result/eax: boolean <- gap-buffer-equal? g, "aa" -337 check-not result, "F - test-gap-buffer-equal-fails" +336 var result/eax: boolean <- gap-buffer-equal? g, "aa" +337 check-not result, "F - test-gap-buffer-equal-fails" 338 } 339 -340 fn gap-buffers-equal? self: (addr gap-buffer), g: (addr gap-buffer) -> _/eax: boolean { -341 var tmp/eax: int <- gap-buffer-length self +340 fn gap-buffers-equal? self: (addr gap-buffer), g: (addr gap-buffer) -> _/eax: boolean { +341 var tmp/eax: int <- gap-buffer-length self 342 var len/ecx: int <- copy tmp -343 var leng/eax: int <- gap-buffer-length g +343 var leng/eax: int <- gap-buffer-length g 344 compare len, leng 345 { 346 break-if-= @@ -410,9 +410,9 @@ if ('onhashchange' in window) { 351 compare i, len 352 break-if->= 353 { -354 var tmp/eax: grapheme <- gap-index self, i +354 var tmp/eax: grapheme <- gap-index self, i 355 var curr/ecx: grapheme <- copy tmp -356 var currg/eax: grapheme <- gap-index g, i +356 var currg/eax: grapheme <- gap-index g, i 357 compare curr, currg 358 break-if-= 359 return 0/false @@ -423,167 +423,167 @@ if ('onhashchange' in window) { 364 return 1/true 365 } 366 -367 fn gap-index _self: (addr gap-buffer), _n: int -> _/eax: grapheme { -368 var self/esi: (addr gap-buffer) <- copy _self +367 fn gap-index _self: (addr gap-buffer), _n: int -> _/eax: grapheme { +368 var self/esi: (addr gap-buffer) <- copy _self 369 var n/ebx: int <- copy _n 370 # if n < left->length, index into left -371 var left/edi: (addr grapheme-stack) <- get self, left -372 var left-len-a/edx: (addr int) <- get left, top +371 var left/edi: (addr grapheme-stack) <- get self, left +372 var left-len-a/edx: (addr int) <- get left, top 373 compare n, *left-len-a 374 { 375 break-if->= -376 var data-ah/eax: (addr handle array grapheme) <- get left, data -377 var data/eax: (addr array grapheme) <- lookup *data-ah +376 var data-ah/eax: (addr handle array grapheme) <- get left, data +377 var data/eax: (addr array grapheme) <- lookup *data-ah 378 var result/eax: (addr grapheme) <- index data, n 379 return *result 380 } 381 # shrink n 382 n <- subtract *left-len-a 383 # if n < right->length, index into right -384 var right/edi: (addr grapheme-stack) <- get self, right -385 var right-len-a/edx: (addr int) <- get right, top +384 var right/edi: (addr grapheme-stack) <- get self, right +385 var right-len-a/edx: (addr int) <- get right, top 386 compare n, *right-len-a 387 { 388 break-if->= -389 var data-ah/eax: (addr handle array grapheme) <- get right, data -390 var data/eax: (addr array grapheme) <- lookup *data-ah +389 var data-ah/eax: (addr handle array grapheme) <- get right, data +390 var data/eax: (addr array grapheme) <- lookup *data-ah 391 var result/eax: (addr grapheme) <- index data, n 392 return *result 393 } 394 # error -395 abort "gap-index: out of bounds" +395 abort "gap-index: out of bounds" 396 return 0 397 } 398 -399 fn test-gap-buffers-equal? { -400 var _a: gap-buffer -401 var a/esi: (addr gap-buffer) <- address _a -402 initialize-gap-buffer-with a, "abc" -403 var _b: gap-buffer -404 var b/edi: (addr gap-buffer) <- address _b -405 initialize-gap-buffer-with b, "abc" -406 var _c: gap-buffer -407 var c/ebx: (addr gap-buffer) <- address _c -408 initialize-gap-buffer-with c, "ab" -409 var _d: gap-buffer -410 var d/edx: (addr gap-buffer) <- address _d -411 initialize-gap-buffer-with d, "abd" +399 fn test-gap-buffers-equal? { +400 var _a: gap-buffer +401 var a/esi: (addr gap-buffer) <- address _a +402 initialize-gap-buffer-with a, "abc" +403 var _b: gap-buffer +404 var b/edi: (addr gap-buffer) <- address _b +405 initialize-gap-buffer-with b, "abc" +406 var _c: gap-buffer +407 var c/ebx: (addr gap-buffer) <- address _c +408 initialize-gap-buffer-with c, "ab" +409 var _d: gap-buffer +410 var d/edx: (addr gap-buffer) <- address _d +411 initialize-gap-buffer-with d, "abd" 412 # -413 var result/eax: boolean <- gap-buffers-equal? a, a -414 check result, "F - test-gap-buffers-equal? - reflexive" -415 result <- gap-buffers-equal? a, b -416 check result, "F - test-gap-buffers-equal? - equal" +413 var result/eax: boolean <- gap-buffers-equal? a, a +414 check result, "F - test-gap-buffers-equal? - reflexive" +415 result <- gap-buffers-equal? a, b +416 check result, "F - test-gap-buffers-equal? - equal" 417 # length not equal -418 result <- gap-buffers-equal? a, c -419 check-not result, "F - test-gap-buffers-equal? - not equal" +418 result <- gap-buffers-equal? a, c +419 check-not result, "F - test-gap-buffers-equal? - not equal" 420 # contents not equal -421 result <- gap-buffers-equal? a, d -422 check-not result, "F - test-gap-buffers-equal? - not equal 2" -423 result <- gap-buffers-equal? d, a -424 check-not result, "F - test-gap-buffers-equal? - not equal 3" +421 result <- gap-buffers-equal? a, d +422 check-not result, "F - test-gap-buffers-equal? - not equal 2" +423 result <- gap-buffers-equal? d, a +424 check-not result, "F - test-gap-buffers-equal? - not equal 3" 425 } 426 -427 fn copy-gap-buffer _src-ah: (addr handle gap-buffer), _dest-ah: (addr handle gap-buffer) { +427 fn copy-gap-buffer _src-ah: (addr handle gap-buffer), _dest-ah: (addr handle gap-buffer) { 428 # obtain src-a, dest-a -429 var src-ah/eax: (addr handle gap-buffer) <- copy _src-ah -430 var _src-a/eax: (addr gap-buffer) <- lookup *src-ah -431 var src-a/esi: (addr gap-buffer) <- copy _src-a -432 var dest-ah/eax: (addr handle gap-buffer) <- copy _dest-ah -433 var _dest-a/eax: (addr gap-buffer) <- lookup *dest-ah -434 var dest-a/edi: (addr gap-buffer) <- copy _dest-a +429 var src-ah/eax: (addr handle gap-buffer) <- copy _src-ah +430 var _src-a/eax: (addr gap-buffer) <- lookup *src-ah +431 var src-a/esi: (addr gap-buffer) <- copy _src-a +432 var dest-ah/eax: (addr handle gap-buffer) <- copy _dest-ah +433 var _dest-a/eax: (addr gap-buffer) <- lookup *dest-ah +434 var dest-a/edi: (addr gap-buffer) <- copy _dest-a 435 # copy left grapheme-stack -436 var src/ecx: (addr grapheme-stack) <- get src-a, left -437 var dest/edx: (addr grapheme-stack) <- get dest-a, left -438 copy-grapheme-stack src, dest +436 var src/ecx: (addr grapheme-stack) <- get src-a, left +437 var dest/edx: (addr grapheme-stack) <- get dest-a, left +438 copy-grapheme-stack src, dest 439 # copy right grapheme-stack -440 src <- get src-a, right -441 dest <- get dest-a, right -442 copy-grapheme-stack src, dest +440 src <- get src-a, right +441 dest <- get dest-a, right +442 copy-grapheme-stack src, dest 443 } 444 -445 fn gap-buffer-is-decimal-integer? _self: (addr gap-buffer) -> _/eax: boolean { -446 var self/esi: (addr gap-buffer) <- copy _self -447 var curr/ecx: (addr grapheme-stack) <- get self, left -448 var result/eax: boolean <- grapheme-stack-is-decimal-integer? curr +445 fn gap-buffer-is-decimal-integer? _self: (addr gap-buffer) -> _/eax: boolean { +446 var self/esi: (addr gap-buffer) <- copy _self +447 var curr/ecx: (addr grapheme-stack) <- get self, left +448 var result/eax: boolean <- grapheme-stack-is-decimal-integer? curr 449 { 450 compare result, 0/false 451 break-if-= -452 curr <- get self, right -453 result <- grapheme-stack-is-decimal-integer? curr +452 curr <- get self, right +453 result <- grapheme-stack-is-decimal-integer? curr 454 } 455 return result 456 } 457 -458 fn test-render-gap-buffer-without-cursor { +458 fn test-render-gap-buffer-without-cursor { 459 # setup -460 var gap-storage: gap-buffer -461 var gap/esi: (addr gap-buffer) <- address gap-storage -462 initialize-gap-buffer-with gap, "abc" +460 var gap-storage: gap-buffer +461 var gap/esi: (addr gap-buffer) <- address gap-storage +462 initialize-gap-buffer-with gap, "abc" 463 # setup: screen -464 var screen-on-stack: screen -465 var screen/edi: (addr screen) <- address screen-on-stack -466 initialize-screen screen, 5, 4 +464 var screen-on-stack: screen +465 var screen/edi: (addr screen) <- address screen-on-stack +466 initialize-screen screen, 5, 4 467 # -468 var x/eax: int <- render-gap-buffer screen, gap, 0/x, 0/y, 0/no-cursor -469 check-screen-row screen, 0/y, "abc ", "F - test-render-gap-buffer-without-cursor" -470 check-ints-equal x, 4, "F - test-render-gap-buffer-without-cursor: result" +468 var x/eax: int <- render-gap-buffer screen, gap, 0/x, 0/y, 0/no-cursor +469 check-screen-row screen, 0/y, "abc ", "F - test-render-gap-buffer-without-cursor" +470 check-ints-equal x, 4, "F - test-render-gap-buffer-without-cursor: result" 471 # abc -472 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-render-gap-buffer-without-cursor: bg" +472 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-render-gap-buffer-without-cursor: bg" 473 } 474 -475 fn test-render-gap-buffer-with-cursor-at-end { +475 fn test-render-gap-buffer-with-cursor-at-end { 476 # setup -477 var gap-storage: gap-buffer -478 var gap/esi: (addr gap-buffer) <- address gap-storage -479 initialize-gap-buffer-with gap, "abc" -480 gap-to-end gap +477 var gap-storage: gap-buffer +478 var gap/esi: (addr gap-buffer) <- address gap-storage +479 initialize-gap-buffer-with gap, "abc" +480 gap-to-end gap 481 # setup: screen -482 var screen-on-stack: screen -483 var screen/edi: (addr screen) <- address screen-on-stack -484 initialize-screen screen, 5, 4 +482 var screen-on-stack: screen +483 var screen/edi: (addr screen) <- address screen-on-stack +484 initialize-screen screen, 5, 4 485 # -486 var x/eax: int <- render-gap-buffer screen, gap, 0/x, 0/y, 1/show-cursor -487 check-screen-row screen, 0/y, "abc ", "F - test-render-gap-buffer-with-cursor-at-end" +486 var x/eax: int <- render-gap-buffer screen, gap, 0/x, 0/y, 1/show-cursor +487 check-screen-row screen, 0/y, "abc ", "F - test-render-gap-buffer-with-cursor-at-end" 488 # we've drawn one extra grapheme for the cursor -489 check-ints-equal x, 4, "F - test-render-gap-buffer-with-cursor-at-end: result" +489 check-ints-equal x, 4, "F - test-render-gap-buffer-with-cursor-at-end: result" 490 # abc -491 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " |", "F - test-render-gap-buffer-with-cursor-at-end: bg" +491 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " |", "F - test-render-gap-buffer-with-cursor-at-end: bg" 492 } 493 -494 fn test-render-gap-buffer-with-cursor-in-middle { +494 fn test-render-gap-buffer-with-cursor-in-middle { 495 # setup -496 var gap-storage: gap-buffer -497 var gap/esi: (addr gap-buffer) <- address gap-storage -498 initialize-gap-buffer-with gap, "abc" -499 gap-to-end gap -500 var dummy/eax: grapheme <- gap-left gap +496 var gap-storage: gap-buffer +497 var gap/esi: (addr gap-buffer) <- address gap-storage +498 initialize-gap-buffer-with gap, "abc" +499 gap-to-end gap +500 var dummy/eax: grapheme <- gap-left gap 501 # setup: screen -502 var screen-on-stack: screen -503 var screen/edi: (addr screen) <- address screen-on-stack -504 initialize-screen screen, 5, 4 +502 var screen-on-stack: screen +503 var screen/edi: (addr screen) <- address screen-on-stack +504 initialize-screen screen, 5, 4 505 # -506 var x/eax: int <- render-gap-buffer screen, gap, 0/x, 0/y, 1/show-cursor -507 check-screen-row screen, 0/y, "abc ", "F - test-render-gap-buffer-with-cursor-in-middle" -508 check-ints-equal x, 4, "F - test-render-gap-buffer-with-cursor-in-middle: result" +506 var x/eax: int <- render-gap-buffer screen, gap, 0/x, 0/y, 1/show-cursor +507 check-screen-row screen, 0/y, "abc ", "F - test-render-gap-buffer-with-cursor-in-middle" +508 check-ints-equal x, 4, "F - test-render-gap-buffer-with-cursor-in-middle: result" 509 # abc -510 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-gap-buffer-with-cursor-in-middle: bg" +510 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " | ", "F - test-render-gap-buffer-with-cursor-in-middle: bg" 511 } 512 -513 fn test-render-gap-buffer-with-cursor-at-start { -514 var gap-storage: gap-buffer -515 var gap/esi: (addr gap-buffer) <- address gap-storage -516 initialize-gap-buffer-with gap, "abc" -517 gap-to-start gap +513 fn test-render-gap-buffer-with-cursor-at-start { +514 var gap-storage: gap-buffer +515 var gap/esi: (addr gap-buffer) <- address gap-storage +516 initialize-gap-buffer-with gap, "abc" +517 gap-to-start gap 518 # setup: screen -519 var screen-on-stack: screen -520 var screen/edi: (addr screen) <- address screen-on-stack -521 initialize-screen screen, 5, 4 +519 var screen-on-stack: screen +520 var screen/edi: (addr screen) <- address screen-on-stack +521 initialize-screen screen, 5, 4 522 # -523 var x/eax: int <- render-gap-buffer screen, gap, 0/x, 0/y, 1/show-cursor -524 check-screen-row screen, 0/y, "abc ", "F - test-render-gap-buffer-with-cursor-at-start" -525 check-ints-equal x, 4, "F - test-render-gap-buffer-with-cursor-at-start: result" +523 var x/eax: int <- render-gap-buffer screen, gap, 0/x, 0/y, 1/show-cursor +524 check-screen-row screen, 0/y, "abc ", "F - test-render-gap-buffer-with-cursor-at-start" +525 check-ints-equal x, 4, "F - test-render-gap-buffer-with-cursor-at-start: result" 526 # abc -527 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "| ", "F - test-render-gap-buffer-with-cursor-at-start: bg" +527 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "| ", "F - test-render-gap-buffer-with-cursor-at-start: bg" 528 } diff --git a/html/baremetal/shell/grapheme-stack.mu.html b/html/baremetal/shell/grapheme-stack.mu.html index b77ff59d..3c38fee7 100644 --- a/html/baremetal/shell/grapheme-stack.mu.html +++ b/html/baremetal/shell/grapheme-stack.mu.html @@ -60,28 +60,28 @@ if ('onhashchange' in window) { 1 # grapheme stacks are the smallest unit of editable text 2 # they are typically rendered horizontally 3 - 4 type grapheme-stack { + 4 type grapheme-stack { 5 data: (handle array grapheme) - 6 top: int + 6 top: int 7 } 8 - 9 fn initialize-grapheme-stack _self: (addr grapheme-stack), n: int { - 10 var self/esi: (addr grapheme-stack) <- copy _self - 11 var d/edi: (addr handle array grapheme) <- get self, data + 9 fn initialize-grapheme-stack _self: (addr grapheme-stack), n: int { + 10 var self/esi: (addr grapheme-stack) <- copy _self + 11 var d/edi: (addr handle array grapheme) <- get self, data 12 populate d, n - 13 var top/eax: (addr int) <- get self, top + 13 var top/eax: (addr int) <- get self, top 14 copy-to *top, 0 15 } 16 - 17 fn clear-grapheme-stack _self: (addr grapheme-stack) { - 18 var self/esi: (addr grapheme-stack) <- copy _self - 19 var top/eax: (addr int) <- get self, top + 17 fn clear-grapheme-stack _self: (addr grapheme-stack) { + 18 var self/esi: (addr grapheme-stack) <- copy _self + 19 var top/eax: (addr int) <- get self, top 20 copy-to *top, 0 21 } 22 - 23 fn grapheme-stack-empty? _self: (addr grapheme-stack) -> _/eax: boolean { - 24 var self/esi: (addr grapheme-stack) <- copy _self - 25 var top/eax: (addr int) <- get self, top + 23 fn grapheme-stack-empty? _self: (addr grapheme-stack) -> _/eax: boolean { + 24 var self/esi: (addr grapheme-stack) <- copy _self + 25 var top/eax: (addr int) <- get self, top 26 compare *top, 0 27 { 28 break-if-!= @@ -90,46 +90,46 @@ if ('onhashchange' in window) { 31 return 0/false 32 } 33 - 34 fn push-grapheme-stack _self: (addr grapheme-stack), _val: grapheme { - 35 var self/esi: (addr grapheme-stack) <- copy _self - 36 var top-addr/ecx: (addr int) <- get self, top - 37 var data-ah/edx: (addr handle array grapheme) <- get self, data - 38 var data/eax: (addr array grapheme) <- lookup *data-ah - 39 var top/edx: int <- copy *top-addr - 40 var dest-addr/edx: (addr grapheme) <- index data, top + 34 fn push-grapheme-stack _self: (addr grapheme-stack), _val: grapheme { + 35 var self/esi: (addr grapheme-stack) <- copy _self + 36 var top-addr/ecx: (addr int) <- get self, top + 37 var data-ah/edx: (addr handle array grapheme) <- get self, data + 38 var data/eax: (addr array grapheme) <- lookup *data-ah + 39 var top/edx: int <- copy *top-addr + 40 var dest-addr/edx: (addr grapheme) <- index data, top 41 var val/eax: grapheme <- copy _val 42 copy-to *dest-addr, val 43 add-to *top-addr, 1 44 } 45 - 46 fn pop-grapheme-stack _self: (addr grapheme-stack) -> _/eax: grapheme { - 47 var self/esi: (addr grapheme-stack) <- copy _self - 48 var top-addr/ecx: (addr int) <- get self, top + 46 fn pop-grapheme-stack _self: (addr grapheme-stack) -> _/eax: grapheme { + 47 var self/esi: (addr grapheme-stack) <- copy _self + 48 var top-addr/ecx: (addr int) <- get self, top 49 { 50 compare *top-addr, 0 51 break-if-> 52 return -1 53 } 54 subtract-from *top-addr, 1 - 55 var data-ah/edx: (addr handle array grapheme) <- get self, data - 56 var data/eax: (addr array grapheme) <- lookup *data-ah - 57 var top/edx: int <- copy *top-addr - 58 var result-addr/eax: (addr grapheme) <- index data, top + 55 var data-ah/edx: (addr handle array grapheme) <- get self, data + 56 var data/eax: (addr array grapheme) <- lookup *data-ah + 57 var top/edx: int <- copy *top-addr + 58 var result-addr/eax: (addr grapheme) <- index data, top 59 return *result-addr 60 } 61 - 62 fn copy-grapheme-stack _src: (addr grapheme-stack), dest: (addr grapheme-stack) { - 63 var src/esi: (addr grapheme-stack) <- copy _src - 64 var data-ah/edi: (addr handle array grapheme) <- get src, data - 65 var _data/eax: (addr array grapheme) <- lookup *data-ah + 62 fn copy-grapheme-stack _src: (addr grapheme-stack), dest: (addr grapheme-stack) { + 63 var src/esi: (addr grapheme-stack) <- copy _src + 64 var data-ah/edi: (addr handle array grapheme) <- get src, data + 65 var _data/eax: (addr array grapheme) <- lookup *data-ah 66 var data/edi: (addr array grapheme) <- copy _data - 67 var top-addr/ecx: (addr int) <- get src, top + 67 var top-addr/ecx: (addr int) <- get src, top 68 var i/eax: int <- copy 0 69 { 70 compare i, *top-addr 71 break-if->= 72 var g/edx: (addr grapheme) <- index data, i - 73 push-grapheme-stack dest, *g + 73 push-grapheme-stack dest, *g 74 i <- increment 75 loop 76 } @@ -137,18 +137,18 @@ if ('onhashchange' in window) { 78 79 # dump stack to screen from bottom to top 80 # colors hardcoded - 81 fn render-stack-from-bottom screen: (addr screen), _self: (addr grapheme-stack), x: int, y: int -> _/eax: int { - 82 var self/esi: (addr grapheme-stack) <- copy _self - 83 var data-ah/edi: (addr handle array grapheme) <- get self, data - 84 var _data/eax: (addr array grapheme) <- lookup *data-ah + 81 fn render-stack-from-bottom screen: (addr screen), _self: (addr grapheme-stack), x: int, y: int -> _/eax: int { + 82 var self/esi: (addr grapheme-stack) <- copy _self + 83 var data-ah/edi: (addr handle array grapheme) <- get self, data + 84 var _data/eax: (addr array grapheme) <- lookup *data-ah 85 var data/edi: (addr array grapheme) <- copy _data - 86 var top-addr/ecx: (addr int) <- get self, top + 86 var top-addr/ecx: (addr int) <- get self, top 87 var i/eax: int <- copy 0 88 { 89 compare i, *top-addr 90 break-if->= 91 var g/edx: (addr grapheme) <- index data, i - 92 draw-grapheme screen, *g, x, y, 3/fg=cyan, 0/bg + 92 draw-grapheme screen, *g, x, y, 3/fg=cyan, 0/bg 93 i <- increment 94 increment x # assume left to right 95 loop @@ -158,12 +158,12 @@ if ('onhashchange' in window) { 99 100 # dump stack to screen from top to bottom 101 # optionally render a 'cursor' with the top grapheme -102 fn render-stack-from-top screen: (addr screen), _self: (addr grapheme-stack), x: int, y: int, render-cursor?: boolean -> _/eax: int { -103 var self/esi: (addr grapheme-stack) <- copy _self -104 var data-ah/edi: (addr handle array grapheme) <- get self, data -105 var _data/eax: (addr array grapheme) <- lookup *data-ah +102 fn render-stack-from-top screen: (addr screen), _self: (addr grapheme-stack), x: int, y: int, render-cursor?: boolean -> _/eax: int { +103 var self/esi: (addr grapheme-stack) <- copy _self +104 var data-ah/edi: (addr handle array grapheme) <- get self, data +105 var _data/eax: (addr array grapheme) <- lookup *data-ah 106 var data/edi: (addr array grapheme) <- copy _data -107 var top-addr/ecx: (addr int) <- get self, top +107 var top-addr/ecx: (addr int) <- get self, top 108 var i/eax: int <- copy *top-addr 109 i <- decrement 110 # if render-cursor?, peel off first iteration @@ -173,7 +173,7 @@ if ('onhashchange' in window) { 114 compare i, 0 115 break-if-< 116 var g/edx: (addr grapheme) <- index data, i -117 draw-grapheme screen, *g, x, y, 3/fg=cyan, 7/bg=cursor +117 draw-grapheme screen, *g, x, y, 3/fg=cyan, 7/bg=cursor 118 i <- decrement 119 increment x # assume left to right 120 } @@ -182,7 +182,7 @@ if ('onhashchange' in window) { 123 compare i, 0 124 break-if-< 125 var g/edx: (addr grapheme) <- index data, i -126 draw-grapheme screen, *g, x, y, 3/fg=cyan, 0/bg +126 draw-grapheme screen, *g, x, y, 3/fg=cyan, 0/bg 127 i <- decrement 128 increment x # assume left to right 129 loop @@ -190,46 +190,46 @@ if ('onhashchange' in window) { 131 return x 132 } 133 -134 fn test-render-grapheme-stack { +134 fn test-render-grapheme-stack { 135 # setup: gs = "abc" -136 var gs-storage: grapheme-stack -137 var gs/edi: (addr grapheme-stack) <- address gs-storage -138 initialize-grapheme-stack gs, 5 +136 var gs-storage: grapheme-stack +137 var gs/edi: (addr grapheme-stack) <- address gs-storage +138 initialize-grapheme-stack gs, 5 139 var g/eax: grapheme <- copy 0x61/a -140 push-grapheme-stack gs, g +140 push-grapheme-stack gs, g 141 g <- copy 0x62/b -142 push-grapheme-stack gs, g +142 push-grapheme-stack gs, g 143 g <- copy 0x63/c -144 push-grapheme-stack gs, g +144 push-grapheme-stack gs, g 145 # setup: screen -146 var screen-on-stack: screen -147 var screen/esi: (addr screen) <- address screen-on-stack -148 initialize-screen screen, 5, 4 +146 var screen-on-stack: screen +147 var screen/esi: (addr screen) <- address screen-on-stack +148 initialize-screen screen, 5, 4 149 # -150 var x/eax: int <- render-stack-from-bottom screen, gs, 0/x, 0/y -151 check-screen-row screen, 0/y, "abc ", "F - test-render-grapheme-stack from bottom" -152 check-ints-equal x, 3, "F - test-render-grapheme-stack from bottom: result" -153 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-render-grapheme-stack from bottom: bg" +150 var x/eax: int <- render-stack-from-bottom screen, gs, 0/x, 0/y +151 check-screen-row screen, 0/y, "abc ", "F - test-render-grapheme-stack from bottom" +152 check-ints-equal x, 3, "F - test-render-grapheme-stack from bottom: result" +153 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-render-grapheme-stack from bottom: bg" 154 # -155 var x/eax: int <- render-stack-from-top screen, gs, 0/x, 1/y, 0/cursor=false -156 check-screen-row screen, 1/y, "cba ", "F - test-render-grapheme-stack from top without cursor" -157 check-ints-equal x, 3, "F - test-render-grapheme-stack from top without cursor: result" -158 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-render-grapheme-stack from top without cursor: bg" +155 var x/eax: int <- render-stack-from-top screen, gs, 0/x, 1/y, 0/cursor=false +156 check-screen-row screen, 1/y, "cba ", "F - test-render-grapheme-stack from top without cursor" +157 check-ints-equal x, 3, "F - test-render-grapheme-stack from top without cursor: result" +158 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-render-grapheme-stack from top without cursor: bg" 159 # -160 var x/eax: int <- render-stack-from-top screen, gs, 0/x, 2/y, 1/cursor=true -161 check-screen-row screen, 2/y, "cba ", "F - test-render-grapheme-stack from top with cursor" -162 check-ints-equal x, 3, "F - test-render-grapheme-stack from top without cursor: result" -163 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "| ", "F - test-render-grapheme-stack from top with cursor: bg" +160 var x/eax: int <- render-stack-from-top screen, gs, 0/x, 2/y, 1/cursor=true +161 check-screen-row screen, 2/y, "cba ", "F - test-render-grapheme-stack from top with cursor" +162 check-ints-equal x, 3, "F - test-render-grapheme-stack from top without cursor: result" +163 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "| ", "F - test-render-grapheme-stack from top with cursor: bg" 164 } 165 166 # compare from bottom 167 # beware: modifies 'stream', which must be disposed of after a false result -168 fn prefix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> _/eax: boolean { -169 var self/esi: (addr grapheme-stack) <- copy _self -170 var data-ah/edi: (addr handle array grapheme) <- get self, data -171 var _data/eax: (addr array grapheme) <- lookup *data-ah +168 fn prefix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> _/eax: boolean { +169 var self/esi: (addr grapheme-stack) <- copy _self +170 var data-ah/edi: (addr handle array grapheme) <- get self, data +171 var _data/eax: (addr array grapheme) <- lookup *data-ah 172 var data/edi: (addr array grapheme) <- copy _data -173 var top-addr/ecx: (addr int) <- get self, top +173 var top-addr/ecx: (addr int) <- get self, top 174 var i/ebx: int <- copy 0 175 { 176 compare i, *top-addr @@ -237,7 +237,7 @@ if ('onhashchange' in window) { 178 # if curr != expected, return false 179 { 180 var curr-a/edx: (addr grapheme) <- index data, i -181 var expected/eax: grapheme <- read-grapheme s +181 var expected/eax: grapheme <- read-grapheme s 182 { 183 compare expected, *curr-a 184 break-if-= @@ -252,12 +252,12 @@ if ('onhashchange' in window) { 193 194 # compare from bottom 195 # beware: modifies 'stream', which must be disposed of after a false result -196 fn suffix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> _/eax: boolean { -197 var self/esi: (addr grapheme-stack) <- copy _self -198 var data-ah/edi: (addr handle array grapheme) <- get self, data -199 var _data/eax: (addr array grapheme) <- lookup *data-ah +196 fn suffix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> _/eax: boolean { +197 var self/esi: (addr grapheme-stack) <- copy _self +198 var data-ah/edi: (addr handle array grapheme) <- get self, data +199 var _data/eax: (addr array grapheme) <- lookup *data-ah 200 var data/edi: (addr array grapheme) <- copy _data -201 var top-addr/eax: (addr int) <- get self, top +201 var top-addr/eax: (addr int) <- get self, top 202 var i/ebx: int <- copy *top-addr 203 i <- decrement 204 { @@ -265,7 +265,7 @@ if ('onhashchange' in window) { 206 break-if-< 207 { 208 var curr-a/edx: (addr grapheme) <- index data, i -209 var expected/eax: grapheme <- read-grapheme s +209 var expected/eax: grapheme <- read-grapheme s 210 # if curr != expected, return false 211 { 212 compare expected, *curr-a @@ -279,19 +279,19 @@ if ('onhashchange' in window) { 220 return 1 # true 221 } 222 -223 fn grapheme-stack-is-decimal-integer? _self: (addr grapheme-stack) -> _/eax: boolean { -224 var self/esi: (addr grapheme-stack) <- copy _self -225 var data-ah/eax: (addr handle array grapheme) <- get self, data -226 var _data/eax: (addr array grapheme) <- lookup *data-ah +223 fn grapheme-stack-is-decimal-integer? _self: (addr grapheme-stack) -> _/eax: boolean { +224 var self/esi: (addr grapheme-stack) <- copy _self +225 var data-ah/eax: (addr handle array grapheme) <- get self, data +226 var _data/eax: (addr array grapheme) <- lookup *data-ah 227 var data/edx: (addr array grapheme) <- copy _data -228 var top-addr/ecx: (addr int) <- get self, top +228 var top-addr/ecx: (addr int) <- get self, top 229 var i/ebx: int <- copy 0 230 var result/eax: boolean <- copy 1/true 231 $grapheme-stack-is-integer?:loop: { 232 compare i, *top-addr 233 break-if->= 234 var g/edx: (addr grapheme) <- index data, i -235 result <- is-decimal-digit? *g +235 result <- is-decimal-digit? *g 236 compare result, 0/false 237 break-if-= 238 i <- increment diff --git a/html/baremetal/shell/line.mu.html b/html/baremetal/shell/line.mu.html index c106a0ea..383c56ef 100644 --- a/html/baremetal/shell/line.mu.html +++ b/html/baremetal/shell/line.mu.html @@ -58,76 +58,76 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/main/baremetal/shell/line.mu
-  1 type line {
+  1 type line {
   2   name: (handle array byte)
-  3   data: (handle word)
-  4   cursor: (handle word)
-  5   next: (handle line)
-  6   prev: (handle line)
+  3   data: (handle word)
+  4   cursor: (handle word)
+  5   next: (handle line)
+  6   prev: (handle line)
   7 }
   8 
   9 # initialize line with a single empty word
- 10 fn initialize-line _line: (addr line) {
- 11   var line/esi: (addr line) <- copy _line
- 12   var word-ah/eax: (addr handle word) <- get line, data
- 13   allocate word-ah
- 14   var cursor-ah/ecx: (addr handle word) <- get line, cursor
+ 10 fn initialize-line _line: (addr line) {
+ 11   var line/esi: (addr line) <- copy _line
+ 12   var word-ah/eax: (addr handle word) <- get line, data
+ 13   allocate word-ah
+ 14   var cursor-ah/ecx: (addr handle word) <- get line, cursor
  15   copy-object word-ah, cursor-ah
- 16   var word/eax: (addr word) <- lookup *word-ah
- 17   initialize-word word
+ 16   var word/eax: (addr word) <- lookup *word-ah
+ 17   initialize-word word
  18 }
  19 
- 20 fn num-words-in-line _in: (addr line) -> _/eax: int {
- 21   var in/esi: (addr line) <- copy _in
- 22   var curr-ah/ecx: (addr handle word) <- get in, data
+ 20 fn num-words-in-line _in: (addr line) -> _/eax: int {
+ 21   var in/esi: (addr line) <- copy _in
+ 22   var curr-ah/ecx: (addr handle word) <- get in, data
  23   var result/edi: int <- copy 0
  24   {
- 25     var curr/eax: (addr word) <- lookup *curr-ah
+ 25     var curr/eax: (addr word) <- lookup *curr-ah
  26     compare curr, 0
  27     break-if-=
- 28     curr-ah <- get curr, next
+ 28     curr-ah <- get curr, next
  29     result <- increment
  30     loop
  31   }
  32   return result
  33 }
  34 
- 35 fn line-list-length lines: (addr handle line) -> _/eax: int {
- 36   var curr-ah/esi: (addr handle line) <- copy lines
+ 35 fn line-list-length lines: (addr handle line) -> _/eax: int {
+ 36   var curr-ah/esi: (addr handle line) <- copy lines
  37   var result/edi: int <- copy 0
  38   {
- 39     var curr/eax: (addr line) <- lookup *curr-ah
+ 39     var curr/eax: (addr line) <- lookup *curr-ah
  40     compare curr, 0
  41     break-if-=
- 42     curr-ah <- get curr, next
+ 42     curr-ah <- get curr, next
  43     result <- increment
  44     loop
  45   }
  46   return result
  47 }
  48 
- 49 fn render-line screen: (addr screen), _line: (addr line), x: int, y: int, render-cursor?: boolean -> _/eax: int {
- 50   var line/eax: (addr line) <- copy _line
- 51   var first-word-ah/esi: (addr handle word) <- get line, data
+ 49 fn render-line screen: (addr screen), _line: (addr line), x: int, y: int, render-cursor?: boolean -> _/eax: int {
+ 50   var line/eax: (addr line) <- copy _line
+ 51   var first-word-ah/esi: (addr handle word) <- get line, data
  52   # cursor-word
  53   var cursor-word/edi: int <- copy 0
  54   compare render-cursor?, 0/false
  55   {
  56     break-if-=
- 57     var cursor-word-ah/eax: (addr handle word) <- get line, cursor
- 58     var _cursor-word/eax: (addr word) <- lookup *cursor-word-ah
+ 57     var cursor-word-ah/eax: (addr handle word) <- get line, cursor
+ 58     var _cursor-word/eax: (addr word) <- lookup *cursor-word-ah
  59     cursor-word <- copy _cursor-word
  60   }
  61   #
- 62   var result/eax: int <- render-words screen, first-word-ah, x, y, cursor-word
+ 62   var result/eax: int <- render-words screen, first-word-ah, x, y, cursor-word
  63   return result
  64 }
  65 
- 66 fn parse-line in: (addr array byte), _out: (addr line) {
- 67   var out/edi: (addr line) <- copy _out
- 68   initialize-line out
- 69   var dest/eax: (addr handle word) <- get out, data
- 70   parse-words in, dest
+ 66 fn parse-line in: (addr array byte), _out: (addr line) {
+ 67   var out/edi: (addr line) <- copy _out
+ 68   initialize-line out
+ 69   var dest/eax: (addr handle word) <- get out, data
+ 70   parse-words in, dest
  71 }
  72 
  73 #? fn main {
@@ -146,28 +146,28 @@ if ('onhashchange' in window) {
  86 #?   var dummy/eax: int <- render-line 0/screen, line-addr, 0/x, 0/y, 1/render-cursor
  87 #? }
  88 
- 89 fn render-line-with-stack screen: (addr screen), _line: (addr line), x: int, y: int, render-cursor?: boolean -> _/eax: int, _/ecx: int {
- 90   var line/esi: (addr line) <- copy _line
+ 89 fn render-line-with-stack screen: (addr screen), _line: (addr line), x: int, y: int, render-cursor?: boolean -> _/eax: int, _/ecx: int {
+ 90   var line/esi: (addr line) <- copy _line
  91   # cursor-word
  92   var cursor-word/edi: int <- copy 0
  93   compare render-cursor?, 0/false
  94   {
  95     break-if-=
- 96     var cursor-word-ah/eax: (addr handle word) <- get line, cursor
- 97     var _cursor-word/eax: (addr word) <- lookup *cursor-word-ah
+ 96     var cursor-word-ah/eax: (addr handle word) <- get line, cursor
+ 97     var _cursor-word/eax: (addr word) <- lookup *cursor-word-ah
  98     cursor-word <- copy _cursor-word
  99   }
 100   #
-101   var curr-word-ah/eax: (addr handle word) <- get line, data
-102   var _curr-word/eax: (addr word) <- lookup *curr-word-ah
-103   var curr-word/edx: (addr word) <- copy _curr-word
+101   var curr-word-ah/eax: (addr handle word) <- get line, data
+102   var _curr-word/eax: (addr word) <- lookup *curr-word-ah
+103   var curr-word/edx: (addr word) <- copy _curr-word
 104   var new-x/eax: int <- copy x  # increases each iteration
 105   var new-y/ebx: int <- copy y  # compute max across all iterations
 106   {
 107     compare curr-word, 0
 108     break-if-=
 109     var curr-y/ecx: int <- copy 0
-110     new-x, curr-y <- render-word-with-stack-and-cursor screen, line, curr-word, new-x, y, cursor-word
+110     new-x, curr-y <- render-word-with-stack-and-cursor screen, line, curr-word, new-x, y, cursor-word
 111     compare curr-y, new-y
 112     {
 113       break-if-<=
@@ -175,15 +175,15 @@ if ('onhashchange' in window) {
 115     }
 116     new-x <- add 1/inter-word-spacing
 117     # update
-118     var next-word-ah/eax: (addr handle word) <- get curr-word, next
-119     var next-word/eax: (addr word) <- lookup *next-word-ah
-120     curr-word <- copy next-word
+118     var next-word-ah/eax: (addr handle word) <- get curr-word, next
+119     var next-word/eax: (addr word) <- lookup *next-word-ah
+120     curr-word <- copy next-word
 121     loop
 122   }
 123   return new-x, new-y
 124 }
 125 
-126 fn render-word-with-stack-and-cursor screen: (addr screen), line: (addr line), curr-word: (addr word), x: int, y: int, _cursor-word-addr: int -> _/eax: int, _/ecx: int {
+126 fn render-word-with-stack-and-cursor screen: (addr screen), line: (addr line), curr-word: (addr word), x: int, y: int, _cursor-word-addr: int -> _/eax: int, _/ecx: int {
 127   # print curr-word, with cursor if necessary
 128   var render-cursor?/eax: boolean <- copy 0/false
 129   var cursor-word-addr/ecx: int <- copy _cursor-word-addr
@@ -192,16 +192,16 @@ if ('onhashchange' in window) {
 132     break-if-!=
 133     render-cursor? <- copy 1/true
 134   }
-135   var new-x/eax: int <- render-word screen, curr-word, x, y, render-cursor?
+135   var new-x/eax: int <- render-word screen, curr-word, x, y, render-cursor?
 136   var new-x-saved/edx: int <- copy new-x
 137   add-to y, 2/word-stack-spacing
 138   # compute stack until word
-139   var stack-storage: value-stack
-140   var stack/edi: (addr value-stack) <- address stack-storage
-141   evaluate line, curr-word, stack
+139   var stack-storage: value-stack
+140   var stack/edi: (addr value-stack) <- address stack-storage
+141   evaluate line, curr-word, stack
 142   # render stack
 143   var new-y/ecx: int <- copy 0
-144   new-x, new-y <- render-value-stack screen, stack, x, y
+144   new-x, new-y <- render-value-stack screen, stack, x, y
 145 #?   draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, new-x, 0xc/fg, 0/bg
 146 #?   draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, new-y, 3/fg, 0/bg
 147   compare new-x, new-x-saved
@@ -213,81 +213,81 @@ if ('onhashchange' in window) {
 153   return new-x, new-y
 154 }
 155 
-156 fn test-render-line-with-stack-singleton {
+156 fn test-render-line-with-stack-singleton {
 157   # line = [1]
-158   var line-storage: line
-159   var line/esi: (addr line) <- address line-storage
-160   parse-line "1", line
+158   var line-storage: line
+159   var line/esi: (addr line) <- address line-storage
+160   parse-line "1", line
 161   # setup: screen
-162   var screen-on-stack: screen
-163   var screen/edi: (addr screen) <- address screen-on-stack
-164   initialize-screen screen, 0x20, 4
+162   var screen-on-stack: screen
+163   var screen/edi: (addr screen) <- address screen-on-stack
+164   initialize-screen screen, 0x20, 4
 165   #
 166   var new-x/eax: int <- copy 0
 167   var new-y/ecx: int <- copy 0
-168   new-x, new-y <- render-line-with-stack screen, line, 0/x, 0/y, 0/no-cursor
-169   check-screen-row screen, 0/y, "1  ", "F - test-render-line-with-stack-singleton/0"
-170   check-screen-row screen, 1/y, "   ", "F - test-render-line-with-stack-singleton/1"
-171   check-screen-row screen, 2/y, " 1 ", "F - test-render-line-with-stack-singleton/2"
+168   new-x, new-y <- render-line-with-stack screen, line, 0/x, 0/y, 0/no-cursor
+169   check-screen-row screen, 0/y, "1  ", "F - test-render-line-with-stack-singleton/0"
+170   check-screen-row screen, 1/y, "   ", "F - test-render-line-with-stack-singleton/1"
+171   check-screen-row screen, 2/y, " 1 ", "F - test-render-line-with-stack-singleton/2"
 172   # not bothering to test hash colors for numbers
 173 }
 174 
-175 fn test-render-line-with-stack {
+175 fn test-render-line-with-stack {
 176   # line = [1 2]
-177   var line-storage: line
-178   var line/esi: (addr line) <- address line-storage
-179   parse-line "1 2", line
+177   var line-storage: line
+178   var line/esi: (addr line) <- address line-storage
+179   parse-line "1 2", line
 180   # setup: screen
-181   var screen-on-stack: screen
-182   var screen/edi: (addr screen) <- address screen-on-stack
-183   initialize-screen screen, 0x20, 4
+181   var screen-on-stack: screen
+182   var screen/edi: (addr screen) <- address screen-on-stack
+183   initialize-screen screen, 0x20, 4
 184   #
 185   var new-x/eax: int <- copy 0
 186   var new-y/ecx: int <- copy 0
-187   new-x, new-y <- render-line-with-stack screen, line, 0/x, 0/y, 0/no-cursor
-188   check-screen-row screen, 0/y, "1   2 ", "F - test-render-line-with-stack/0"
-189   check-screen-row screen, 1/y, "       ", "F - test-render-line-with-stack/1"
+187   new-x, new-y <- render-line-with-stack screen, line, 0/x, 0/y, 0/no-cursor
+188   check-screen-row screen, 0/y, "1   2 ", "F - test-render-line-with-stack/0"
+189   check-screen-row screen, 1/y, "       ", "F - test-render-line-with-stack/1"
 190                                 #___ ___
-191   check-screen-row screen, 2/y, " 1   2 ", "F - test-render-line-with-stack/2"
-192   check-screen-row screen, 3/y, "     1 ", "F - test-render-line-with-stack/3"
+191   check-screen-row screen, 2/y, " 1   2 ", "F - test-render-line-with-stack/2"
+192   check-screen-row screen, 3/y, "     1 ", "F - test-render-line-with-stack/3"
 193   # not bothering to test hash colors for numbers
 194 }
 195 
-196 fn edit-line _self: (addr line), key: byte {
-197   var self/esi: (addr line) <- copy _self
-198   var cursor-word-ah/edx: (addr handle word) <- get self, cursor
-199   var _cursor-word/eax: (addr word) <- lookup *cursor-word-ah
-200   var cursor-word/ecx: (addr word) <- copy _cursor-word
+196 fn edit-line _self: (addr line), key: byte {
+197   var self/esi: (addr line) <- copy _self
+198   var cursor-word-ah/edx: (addr handle word) <- get self, cursor
+199   var _cursor-word/eax: (addr word) <- lookup *cursor-word-ah
+200   var cursor-word/ecx: (addr word) <- copy _cursor-word
 201   compare key, 0x20/space
 202   $edit-line:space: {
 203     break-if-!=
-204     append-word cursor-word-ah
-205     var next-word-ah/eax: (addr handle word) <- get cursor-word, next
+204     append-word cursor-word-ah
+205     var next-word-ah/eax: (addr handle word) <- get cursor-word, next
 206     copy-object next-word-ah, cursor-word-ah
 207     return
 208   }
 209   # otherwise insert key within current word
 210   var g/edx: grapheme <- copy key
-211   add-grapheme-to-word cursor-word, g
+211   add-grapheme-to-word cursor-word, g
 212   # silently ignore other hotkeys
 213 }
 214 
-215 fn main {
-216   var line-storage: line
-217   var line/esi: (addr line) <- address line-storage
-218   initialize-line line
+215 fn main {
+216   var line-storage: line
+217   var line/esi: (addr line) <- address line-storage
+218   initialize-line line
 219   $main:loop: {
-220     clear-screen 0/screen
+220     clear-screen 0/screen
 221     var dummy1/eax: int <- copy 0
 222     var dummy2/ecx: int <- copy 0
-223     dummy1, dummy2 <- render-line-with-stack 0/screen, line, 2/x, 2/y, 1/show-cursor
+223     dummy1, dummy2 <- render-line-with-stack 0/screen, line, 2/x, 2/y, 1/show-cursor
 224     {
-225       var key/eax: byte <- read-key 0/keyboard
+225       var key/eax: byte <- read-key 0/keyboard
 226       compare key, 0
 227       loop-if-=
 228       compare key, 0x71/q
 229       break-if-= $main:loop
-230       edit-line line, key
+230       edit-line line, key
 231     }
 232     loop
 233   }
diff --git a/html/baremetal/shell/value-stack.mu.html b/html/baremetal/shell/value-stack.mu.html
index 1174da46..2b167886 100644
--- a/html/baremetal/shell/value-stack.mu.html
+++ b/html/baremetal/shell/value-stack.mu.html
@@ -60,155 +60,155 @@ if ('onhashchange' in window) {
   1 # value stacks encode the result of a program at a single point in time
   2 # they are typically rendered vertically
   3 
-  4 type value-stack {
-  5   data: (handle array value)
-  6   top: int
+  4 type value-stack {
+  5   data: (handle array value)
+  6   top: int
   7 }
   8 
-  9 fn initialize-value-stack _self: (addr value-stack), n: int {
- 10   var self/esi: (addr value-stack) <- copy _self
- 11   var d/edi: (addr handle array value) <- get self, data
+  9 fn initialize-value-stack _self: (addr value-stack), n: int {
+ 10   var self/esi: (addr value-stack) <- copy _self
+ 11   var d/edi: (addr handle array value) <- get self, data
  12   populate d, n
- 13   var top/eax: (addr int) <- get self, top
+ 13   var top/eax: (addr int) <- get self, top
  14   copy-to *top, 0
  15 }
  16 
- 17 fn clear-value-stack _self: (addr value-stack) {
- 18   var self/esi: (addr value-stack) <- copy _self
- 19   var top/eax: (addr int) <- get self, top
+ 17 fn clear-value-stack _self: (addr value-stack) {
+ 18   var self/esi: (addr value-stack) <- copy _self
+ 19   var top/eax: (addr int) <- get self, top
  20   copy-to *top, 0
  21 }
  22 
- 23 fn push-number-to-value-stack _self: (addr value-stack), _val: float {
- 24   var self/esi: (addr value-stack) <- copy _self
- 25   var top-addr/ecx: (addr int) <- get self, top
- 26   var data-ah/edx: (addr handle array value) <- get self, data
- 27   var data/eax: (addr array value) <- lookup *data-ah
- 28   var top/edx: int <- copy *top-addr
- 29   var dest-offset/edx: (offset value) <- compute-offset data, top
- 30   var dest-addr/edx: (addr value) <- index data, dest-offset
- 31   var dest-addr2/eax: (addr float) <- get dest-addr, number-data
+ 23 fn push-number-to-value-stack _self: (addr value-stack), _val: float {
+ 24   var self/esi: (addr value-stack) <- copy _self
+ 25   var top-addr/ecx: (addr int) <- get self, top
+ 26   var data-ah/edx: (addr handle array value) <- get self, data
+ 27   var data/eax: (addr array value) <- lookup *data-ah
+ 28   var top/edx: int <- copy *top-addr
+ 29   var dest-offset/edx: (offset value) <- compute-offset data, top
+ 30   var dest-addr/edx: (addr value) <- index data, dest-offset
+ 31   var dest-addr2/eax: (addr float) <- get dest-addr, number-data
  32   var val/xmm0: float <- copy _val
  33   copy-to *dest-addr2, val
  34   increment *top-addr
- 35   var type-addr/eax: (addr int) <- get dest-addr, type
+ 35   var type-addr/eax: (addr int) <- get dest-addr, type
  36   copy-to *type-addr, 0/number
  37 }
  38 
- 39 fn push-int-to-value-stack _self: (addr value-stack), _val: int {
- 40   var self/esi: (addr value-stack) <- copy _self
- 41   var top-addr/ecx: (addr int) <- get self, top
- 42   var data-ah/edx: (addr handle array value) <- get self, data
- 43   var data/eax: (addr array value) <- lookup *data-ah
- 44   var top/edx: int <- copy *top-addr
- 45   var dest-offset/edx: (offset value) <- compute-offset data, top
- 46   var dest-addr/edx: (addr value) <- index data, dest-offset
- 47   var dest-addr2/eax: (addr float) <- get dest-addr, number-data
+ 39 fn push-int-to-value-stack _self: (addr value-stack), _val: int {
+ 40   var self/esi: (addr value-stack) <- copy _self
+ 41   var top-addr/ecx: (addr int) <- get self, top
+ 42   var data-ah/edx: (addr handle array value) <- get self, data
+ 43   var data/eax: (addr array value) <- lookup *data-ah
+ 44   var top/edx: int <- copy *top-addr
+ 45   var dest-offset/edx: (offset value) <- compute-offset data, top
+ 46   var dest-addr/edx: (addr value) <- index data, dest-offset
+ 47   var dest-addr2/eax: (addr float) <- get dest-addr, number-data
  48   var val/xmm0: float <- convert _val
  49   copy-to *dest-addr2, val
  50   increment *top-addr
- 51   var type-addr/eax: (addr int) <- get dest-addr, type
+ 51   var type-addr/eax: (addr int) <- get dest-addr, type
  52   copy-to *type-addr, 0/number
  53 }
  54 
- 55 fn push-string-to-value-stack _self: (addr value-stack), val: (handle array byte) {
- 56   var self/esi: (addr value-stack) <- copy _self
- 57   var top-addr/ecx: (addr int) <- get self, top
- 58   var data-ah/edx: (addr handle array value) <- get self, data
- 59   var data/eax: (addr array value) <- lookup *data-ah
- 60   var top/edx: int <- copy *top-addr
- 61   var dest-offset/edx: (offset value) <- compute-offset data, top
- 62   var dest-addr/edx: (addr value) <- index data, dest-offset
- 63   var dest-addr2/eax: (addr handle array byte) <- get dest-addr, text-data
- 64   copy-handle val, dest-addr2
- 65   var dest-addr3/eax: (addr int) <- get dest-addr, type
+ 55 fn push-string-to-value-stack _self: (addr value-stack), val: (handle array byte) {
+ 56   var self/esi: (addr value-stack) <- copy _self
+ 57   var top-addr/ecx: (addr int) <- get self, top
+ 58   var data-ah/edx: (addr handle array value) <- get self, data
+ 59   var data/eax: (addr array value) <- lookup *data-ah
+ 60   var top/edx: int <- copy *top-addr
+ 61   var dest-offset/edx: (offset value) <- compute-offset data, top
+ 62   var dest-addr/edx: (addr value) <- index data, dest-offset
+ 63   var dest-addr2/eax: (addr handle array byte) <- get dest-addr, text-data
+ 64   copy-handle val, dest-addr2
+ 65   var dest-addr3/eax: (addr int) <- get dest-addr, type
  66   copy-to *dest-addr3, 1/string
  67   increment *top-addr
  68 }
  69 
- 70 fn push-array-to-value-stack _self: (addr value-stack), val: (handle array value) {
- 71   var self/esi: (addr value-stack) <- copy _self
- 72   var top-addr/ecx: (addr int) <- get self, top
- 73   var data-ah/edx: (addr handle array value) <- get self, data
- 74   var data/eax: (addr array value) <- lookup *data-ah
- 75   var top/edx: int <- copy *top-addr
- 76   var dest-offset/edx: (offset value) <- compute-offset data, top
- 77   var dest-addr/edx: (addr value) <- index data, dest-offset
- 78   var dest-addr2/eax: (addr handle array value) <- get dest-addr, array-data
- 79   copy-handle val, dest-addr2
+ 70 fn push-array-to-value-stack _self: (addr value-stack), val: (handle array value) {
+ 71   var self/esi: (addr value-stack) <- copy _self
+ 72   var top-addr/ecx: (addr int) <- get self, top
+ 73   var data-ah/edx: (addr handle array value) <- get self, data
+ 74   var data/eax: (addr array value) <- lookup *data-ah
+ 75   var top/edx: int <- copy *top-addr
+ 76   var dest-offset/edx: (offset value) <- compute-offset data, top
+ 77   var dest-addr/edx: (addr value) <- index data, dest-offset
+ 78   var dest-addr2/eax: (addr handle array value) <- get dest-addr, array-data
+ 79   copy-handle val, dest-addr2
  80   # update type
- 81   var dest-addr3/eax: (addr int) <- get dest-addr, type
+ 81   var dest-addr3/eax: (addr int) <- get dest-addr, type
  82   copy-to *dest-addr3, 2/array
  83   increment *top-addr
  84 }
  85 
- 86 fn push-boolean-to-value-stack _self: (addr value-stack), _val: boolean {
- 87   var self/esi: (addr value-stack) <- copy _self
- 88   var top-addr/ecx: (addr int) <- get self, top
- 89   var data-ah/edx: (addr handle array value) <- get self, data
- 90   var data/eax: (addr array value) <- lookup *data-ah
- 91   var top/edx: int <- copy *top-addr
- 92   var dest-offset/edx: (offset value) <- compute-offset data, top
- 93   var dest-addr/edx: (addr value) <- index data, dest-offset
- 94   var dest-addr2/eax: (addr boolean) <- get dest-addr, boolean-data
+ 86 fn push-boolean-to-value-stack _self: (addr value-stack), _val: boolean {
+ 87   var self/esi: (addr value-stack) <- copy _self
+ 88   var top-addr/ecx: (addr int) <- get self, top
+ 89   var data-ah/edx: (addr handle array value) <- get self, data
+ 90   var data/eax: (addr array value) <- lookup *data-ah
+ 91   var top/edx: int <- copy *top-addr
+ 92   var dest-offset/edx: (offset value) <- compute-offset data, top
+ 93   var dest-addr/edx: (addr value) <- index data, dest-offset
+ 94   var dest-addr2/eax: (addr boolean) <- get dest-addr, boolean-data
  95   var val/esi: boolean <- copy _val
  96   copy-to *dest-addr2, val
  97   increment *top-addr
- 98   var type-addr/eax: (addr int) <- get dest-addr, type
+ 98   var type-addr/eax: (addr int) <- get dest-addr, type
  99   copy-to *type-addr, 3/boolean
 100 }
 101 
-102 fn push-value-stack _self: (addr value-stack), val: (addr value) {
-103   var self/esi: (addr value-stack) <- copy _self
-104   var top-addr/ecx: (addr int) <- get self, top
-105   var data-ah/edx: (addr handle array value) <- get self, data
-106   var data/eax: (addr array value) <- lookup *data-ah
-107   var top/edx: int <- copy *top-addr
-108   var dest-offset/edx: (offset value) <- compute-offset data, top
-109   var dest-addr/edx: (addr value) <- index data, dest-offset
+102 fn push-value-stack _self: (addr value-stack), val: (addr value) {
+103   var self/esi: (addr value-stack) <- copy _self
+104   var top-addr/ecx: (addr int) <- get self, top
+105   var data-ah/edx: (addr handle array value) <- get self, data
+106   var data/eax: (addr array value) <- lookup *data-ah
+107   var top/edx: int <- copy *top-addr
+108   var dest-offset/edx: (offset value) <- compute-offset data, top
+109   var dest-addr/edx: (addr value) <- index data, dest-offset
 110   copy-object val, dest-addr
 111   increment *top-addr
 112 }
 113 
-114 fn pop-number-from-value-stack _self: (addr value-stack) -> _/xmm0: float {
-115   var self/esi: (addr value-stack) <- copy _self
-116   var top-addr/ecx: (addr int) <- get self, top
+114 fn pop-number-from-value-stack _self: (addr value-stack) -> _/xmm0: float {
+115   var self/esi: (addr value-stack) <- copy _self
+116   var top-addr/ecx: (addr int) <- get self, top
 117   {
 118     compare *top-addr, 0
 119     break-if->
-120     abort "pop number: empty stack"
+120     abort "pop number: empty stack"
 121   }
 122   decrement *top-addr
-123   var data-ah/edx: (addr handle array value) <- get self, data
-124   var data/eax: (addr array value) <- lookup *data-ah
-125   var top/edx: int <- copy *top-addr
-126   var dest-offset/edx: (offset value) <- compute-offset data, top
-127   var result-addr/eax: (addr value) <- index data, dest-offset
-128   var result-addr2/eax: (addr float) <- get result-addr, number-data
+123   var data-ah/edx: (addr handle array value) <- get self, data
+124   var data/eax: (addr array value) <- lookup *data-ah
+125   var top/edx: int <- copy *top-addr
+126   var dest-offset/edx: (offset value) <- compute-offset data, top
+127   var result-addr/eax: (addr value) <- index data, dest-offset
+128   var result-addr2/eax: (addr float) <- get result-addr, number-data
 129   return *result-addr2
 130 }
 131 
-132 fn pop-boolean-from-value-stack _self: (addr value-stack) -> _/eax: boolean {
-133   var self/esi: (addr value-stack) <- copy _self
-134   var top-addr/ecx: (addr int) <- get self, top
+132 fn pop-boolean-from-value-stack _self: (addr value-stack) -> _/eax: boolean {
+133   var self/esi: (addr value-stack) <- copy _self
+134   var top-addr/ecx: (addr int) <- get self, top
 135   {
 136     compare *top-addr, 0
 137     break-if->
-138     abort "pop boolean: empty stack"
+138     abort "pop boolean: empty stack"
 139   }
 140   decrement *top-addr
-141   var data-ah/edx: (addr handle array value) <- get self, data
-142   var data/eax: (addr array value) <- lookup *data-ah
-143   var top/edx: int <- copy *top-addr
-144   var dest-offset/edx: (offset value) <- compute-offset data, top
-145   var result-addr/eax: (addr value) <- index data, dest-offset
-146   var result-addr2/eax: (addr boolean) <- get result-addr, boolean-data
+141   var data-ah/edx: (addr handle array value) <- get self, data
+142   var data/eax: (addr array value) <- lookup *data-ah
+143   var top/edx: int <- copy *top-addr
+144   var dest-offset/edx: (offset value) <- compute-offset data, top
+145   var result-addr/eax: (addr value) <- index data, dest-offset
+146   var result-addr2/eax: (addr boolean) <- get result-addr, boolean-data
 147   return *result-addr2
 148 }
 149 
-150 fn value-stack-empty? _self: (addr value-stack) -> _/eax: boolean {
-151   var self/esi: (addr value-stack) <- copy _self
-152   var top/eax: (addr int) <- get self, top
+150 fn value-stack-empty? _self: (addr value-stack) -> _/eax: boolean {
+151   var self/esi: (addr value-stack) <- copy _self
+152   var top/eax: (addr int) <- get self, top
 153   compare *top, 0
 154   {
 155     break-if-!=
@@ -217,60 +217,60 @@ if ('onhashchange' in window) {
 158   return 0/false
 159 }
 160 
-161 fn value-stack-length _self: (addr value-stack) -> _/eax: int {
-162   var self/esi: (addr value-stack) <- copy _self
-163   var top-addr/eax: (addr int) <- get self, top
+161 fn value-stack-length _self: (addr value-stack) -> _/eax: int {
+162   var self/esi: (addr value-stack) <- copy _self
+163   var top-addr/eax: (addr int) <- get self, top
 164   return *top-addr
 165 }
 166 
-167 fn test-boolean {
-168   var stack-storage: value-stack
-169   var stack/esi: (addr value-stack) <- address stack-storage
-170   push-boolean-to-value-stack stack, 0/false
-171   var result/eax: boolean <- pop-boolean-from-value-stack stack
-172   check-not result, "F - test-boolean/false"
-173   push-boolean-to-value-stack stack, 1/true
-174   var result/eax: boolean <- pop-boolean-from-value-stack stack
-175   check result, "F - test-boolean/true"
+167 fn test-boolean {
+168   var stack-storage: value-stack
+169   var stack/esi: (addr value-stack) <- address stack-storage
+170   push-boolean-to-value-stack stack, 0/false
+171   var result/eax: boolean <- pop-boolean-from-value-stack stack
+172   check-not result, "F - test-boolean/false"
+173   push-boolean-to-value-stack stack, 1/true
+174   var result/eax: boolean <- pop-boolean-from-value-stack stack
+175   check result, "F - test-boolean/true"
 176 }
 177 
-178 fn dump-stack _self: (addr value-stack) {
-179   var self/esi: (addr value-stack) <- copy _self
-180   var data-ah/eax: (addr handle array value) <- get self, data
-181   var _data/eax: (addr array value) <- lookup *data-ah
-182   var data/edi: (addr array value) <- copy _data
-183   var top-addr/ecx: (addr int) <- get self, top
-184   var top/ecx: int <- copy *top-addr
-185   top <- decrement
+178 fn dump-stack _self: (addr value-stack) {
+179   var self/esi: (addr value-stack) <- copy _self
+180   var data-ah/eax: (addr handle array value) <- get self, data
+181   var _data/eax: (addr array value) <- lookup *data-ah
+182   var data/edi: (addr array value) <- copy _data
+183   var top-addr/ecx: (addr int) <- get self, top
+184   var top/ecx: int <- copy *top-addr
+185   top <- decrement
 186   var y/edx: int <- copy 0xa
-187   var dummy/eax: int <- draw-text-rightward-over-full-screen 0/screen, "==", 0/x, 9/y, 0xc/red, 0/bg
+187   var dummy/eax: int <- draw-text-rightward-over-full-screen 0/screen, "==", 0/x, 9/y, 0xc/red, 0/bg
 188   {
-189     compare top, 0
+189     compare top, 0
 190     break-if-<
-191     var dest-offset/eax: (offset value) <- compute-offset data, top
-192     var curr/eax: (addr value) <- index data, dest-offset
-193     var dummy/eax: int <- render-value 0/screen, curr, 0/x, y, 0/no-color
-194     top <- decrement
+191     var dest-offset/eax: (offset value) <- compute-offset data, top
+192     var curr/eax: (addr value) <- index data, dest-offset
+193     var dummy/eax: int <- render-value 0/screen, curr, 0/x, y, 0/no-color
+194     top <- decrement
 195     y <- increment
 196     loop
 197   }
 198 }
 199 
-200 fn render-value-stack screen: (addr screen), _self: (addr value-stack), x: int, y: int -> _/eax: int, _/ecx: int {
-201   var self/ecx: (addr value-stack) <- copy _self
-202   var data-ah/eax: (addr handle array value) <- get self, data
-203   var _data/eax: (addr array value) <- lookup *data-ah
-204   var data/edi: (addr array value) <- copy _data
-205   var top-addr/eax: (addr int) <- get self, top
+200 fn render-value-stack screen: (addr screen), _self: (addr value-stack), x: int, y: int -> _/eax: int, _/ecx: int {
+201   var self/ecx: (addr value-stack) <- copy _self
+202   var data-ah/eax: (addr handle array value) <- get self, data
+203   var _data/eax: (addr array value) <- lookup *data-ah
+204   var data/edi: (addr array value) <- copy _data
+205   var top-addr/eax: (addr int) <- get self, top
 206   var curr-idx/ecx: int <- copy *top-addr
 207   curr-idx <- decrement
 208   var new-x/edx: int <- copy 0
 209   {
 210     compare curr-idx, 0
 211     break-if-<
-212     var dest-offset/eax: (offset value) <- compute-offset data, curr-idx
-213     var curr/eax: (addr value) <- index data, dest-offset
-214     var curr-x/eax: int <- render-value screen, curr, x, y, 1/top-level
+212     var dest-offset/eax: (offset value) <- compute-offset data, curr-idx
+213     var curr/eax: (addr value) <- index data, dest-offset
+214     var curr-x/eax: int <- render-value screen, curr, x, y, 1/top-level
 215     {
 216       compare curr-x, new-x
 217       break-if-<=
@@ -283,20 +283,20 @@ if ('onhashchange' in window) {
 224   return new-x, y
 225 }
 226 
-227 fn test-render-value-stack {
-228   var stack-storage: value-stack
-229   var stack/esi: (addr value-stack) <- address stack-storage
-230   push-int-to-value-stack stack, 3
+227 fn test-render-value-stack {
+228   var stack-storage: value-stack
+229   var stack/esi: (addr value-stack) <- address stack-storage
+230   push-int-to-value-stack stack, 3
 231   # setup: screen
-232   var screen-on-stack: screen
-233   var screen/edi: (addr screen) <- address screen-on-stack
-234   initialize-screen screen, 0x20, 4
+232   var screen-on-stack: screen
+233   var screen/edi: (addr screen) <- address screen-on-stack
+234   initialize-screen screen, 0x20, 4
 235   #
 236   var final-x/eax: int <- copy 0
 237   var final-y/ecx: int <- copy 0
-238   final-x, final-y <- render-value-stack screen, stack, 0/x, 0/y
-239   check-ints-equal final-y, 1, "F - test-render-value-stack y"
-240   check-ints-equal final-x, 3, "F - test-render-value-stack x"
+238   final-x, final-y <- render-value-stack screen, stack, 0/x, 0/y
+239   check-ints-equal final-y, 1, "F - test-render-value-stack y"
+240   check-ints-equal final-x, 3, "F - test-render-value-stack x"
 241 }
 
diff --git a/html/baremetal/shell/value.mu.html b/html/baremetal/shell/value.mu.html index 33050043..34998ed2 100644 --- a/html/baremetal/shell/value.mu.html +++ b/html/baremetal/shell/value.mu.html @@ -58,80 +58,80 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/main/baremetal/shell/value.mu
   1 # todo: turn this into a sum type
-  2 type value {
+  2 type value {
   3   type: int
   4   number-data: float  # if type = 0
   5   text-data: (handle array byte)  # if type = 1
-  6   array-data: (handle array value)  # if type = 2
+  6   array-data: (handle array value)  # if type = 2
   7   boolean-data: boolean  # if type = 3
   8 }
   9 
  10 # top-level? is a hack just for numbers
  11 # we'll eventually need to return a y coordinate as well to render 2D values
- 12 fn render-value screen: (addr screen), _val: (addr value), x: int, y: int, top-level?: boolean -> _/eax: int {
- 13   var val/esi: (addr value) <- copy _val
- 14   var val-type/ecx: (addr int) <- get val, type
+ 12 fn render-value screen: (addr screen), _val: (addr value), x: int, y: int, top-level?: boolean -> _/eax: int {
+ 13   var val/esi: (addr value) <- copy _val
+ 14   var val-type/ecx: (addr int) <- get val, type
  15   compare *val-type, 1/string
  16   {
  17     break-if-!=
- 18     var val-ah/eax: (addr handle array byte) <- get val, text-data
- 19     var _val-string/eax: (addr array byte) <- lookup *val-ah
+ 18     var val-ah/eax: (addr handle array byte) <- get val, text-data
+ 19     var _val-string/eax: (addr array byte) <- lookup *val-ah
  20     var val-string/ecx: (addr array byte) <- copy _val-string
- 21     var new-x/eax: int <- render-string screen, val-string, x, y
+ 21     var new-x/eax: int <- render-string screen, val-string, x, y
  22     return new-x
  23   }
  24   compare *val-type, 2/array
  25   {
  26     break-if-!=
- 27     var val-ah/eax: (addr handle array value) <- get val, array-data
- 28     var _val-array/eax: (addr array value) <- lookup *val-ah
- 29     var val-array/edx: (addr array value) <- copy _val-array
- 30     var new-x/eax: int <- render-array screen, val-array, x, y
+ 27     var val-ah/eax: (addr handle array value) <- get val, array-data
+ 28     var _val-array/eax: (addr array value) <- lookup *val-ah
+ 29     var val-array/edx: (addr array value) <- copy _val-array
+ 30     var new-x/eax: int <- render-array screen, val-array, x, y
  31     return new-x
  32   }
  33   compare *val-type, 3/boolean
  34   {
  35     break-if-!=
- 36     var val/eax: (addr boolean) <- get val, boolean-data
- 37     var new-x/eax: int <- render-boolean screen, *val, x, y
+ 36     var val/eax: (addr boolean) <- get val, boolean-data
+ 37     var new-x/eax: int <- render-boolean screen, *val, x, y
  38     return new-x
  39   }
  40   # render ints by default for now
- 41   var val-num/eax: (addr float) <- get val, number-data
- 42   var new-x/eax: int <- render-number screen, *val-num, x, y, top-level?
+ 41   var val-num/eax: (addr float) <- get val, number-data
+ 42   var new-x/eax: int <- render-number screen, *val-num, x, y, top-level?
  43   return new-x
  44 }
  45 
- 46 fn initialize-value-with-integer _self: (addr value), n: int {
- 47   var self/esi: (addr value) <- copy _self
- 48   var type/eax: (addr int) <- get self, type
+ 46 fn initialize-value-with-integer _self: (addr value), n: int {
+ 47   var self/esi: (addr value) <- copy _self
+ 48   var type/eax: (addr int) <- get self, type
  49   copy-to *type, 0/number
  50   var val/xmm0: float <- convert n
- 51   var dest/eax: (addr float) <- get self, number-data
+ 51   var dest/eax: (addr float) <- get self, number-data
  52   copy-to *dest, val
  53 }
  54 
- 55 fn initialize-value-with-float _self: (addr value), n: float {
- 56   var self/esi: (addr value) <- copy _self
- 57   var type/eax: (addr int) <- get self, type
+ 55 fn initialize-value-with-float _self: (addr value), n: float {
+ 56   var self/esi: (addr value) <- copy _self
+ 57   var type/eax: (addr int) <- get self, type
  58   copy-to *type, 0/number
  59   var val/xmm0: float <- copy n
- 60   var dest/eax: (addr float) <- get self, number-data
+ 60   var dest/eax: (addr float) <- get self, number-data
  61   copy-to *dest, val
  62 }
  63 
  64 # synaesthesia
  65 # TODO: right-justify
- 66 fn render-number screen: (addr screen), val: float, x: int, y: int, top-level?: boolean -> _/eax: int {
+ 66 fn render-number screen: (addr screen), val: float, x: int, y: int, top-level?: boolean -> _/eax: int {
  67   # if we're inside an array, don't color
  68   compare top-level?, 0
  69   {
  70     break-if-!=
- 71     var new-x/eax: int <- render-float-decimal screen, val, 3/precision, x, y, 3/fg, 0/bg
+ 71     var new-x/eax: int <- render-float-decimal screen, val, 3/precision, x, y, 3/fg, 0/bg
  72     return new-x
  73   }
  74   var val-int/eax: int <- convert val
- 75   var _bg/eax: int <- hash-color val-int
+ 75   var _bg/eax: int <- hash-color val-int
  76   var bg/ecx: int <- copy _bg
  77   var fg/edx: int <- copy 7
  78   {
@@ -149,42 +149,42 @@ if ('onhashchange' in window) {
  90     break-if-!=
  91     fg <- copy 0
  92   }
- 93   draw-code-point screen, 0x20/space, x, y, fg, bg
+ 93   draw-code-point screen, 0x20/space, x, y, fg, bg
  94   increment x
- 95   var new-x/eax: int <- render-float-decimal screen, val, 3/precision, x, y, fg, bg
- 96   draw-code-point screen, 0x20/space, new-x, y, fg, bg
+ 95   var new-x/eax: int <- render-float-decimal screen, val, 3/precision, x, y, fg, bg
+ 96   draw-code-point screen, 0x20/space, new-x, y, fg, bg
  97   new-x <- increment
  98   return new-x
  99 }
 100 
-101 fn hash-color val: int -> _/eax: int {
+101 fn hash-color val: int -> _/eax: int {
 102   var quotient/eax: int <- copy 0
 103   var remainder/edx: int <- copy 0
-104   quotient, remainder <- integer-divide val, 7  # assumes that 7 is always the background color
+104   quotient, remainder <- integer-divide val, 7  # assumes that 7 is always the background color
 105   return remainder
 106 }
 107 
-108 fn test-render-number {
+108 fn test-render-number {
 109   # setup: screen
-110   var screen-on-stack: screen
-111   var screen/edi: (addr screen) <- address screen-on-stack
-112   initialize-screen screen, 0x20, 4
+110   var screen-on-stack: screen
+111   var screen/edi: (addr screen) <- address screen-on-stack
+112   initialize-screen screen, 0x20, 4
 113   # integers render with some padding spaces
-114   var new-x/eax: int <- render-number screen, 0/n, 0/x, 0/y, 1/at-top-level
-115   check-screen-row screen, 0/y, " 0 ", "F - test-render-number"
-116   check-ints-equal new-x, 3, "F - test-render-number: result"
+114   var new-x/eax: int <- render-number screen, 0/n, 0/x, 0/y, 1/at-top-level
+115   check-screen-row screen, 0/y, " 0 ", "F - test-render-number"
+116   check-ints-equal new-x, 3, "F - test-render-number: result"
 117   # we won't bother testing the background colors; lots of flexibility there
 118 }
 119 
-120 fn initialize-value-with-string _self: (addr value), s: (addr array byte) {
-121   var self/esi: (addr value) <- copy _self
-122   var type/eax: (addr int) <- get self, type
+120 fn initialize-value-with-string _self: (addr value), s: (addr array byte) {
+121   var self/esi: (addr value) <- copy _self
+122   var type/eax: (addr int) <- get self, type
 123   copy-to *type, 1/string
-124   var dest/eax: (addr handle array byte) <- get self, text-data
-125   copy-array-object s, dest
+124   var dest/eax: (addr handle array byte) <- get self, text-data
+125   copy-array-object s, dest
 126 }
 127 
-128 fn render-string screen: (addr screen), _val: (addr array byte), x: int, y: int -> _/eax: int {
+128 fn render-string screen: (addr screen), _val: (addr array byte), x: int, y: int -> _/eax: int {
 129   var val/esi: (addr array byte) <- copy _val
 130   compare val, 0
 131   {
@@ -196,50 +196,50 @@ if ('onhashchange' in window) {
 137   # TODO: more sophisticated interactive rendering
 138   var truncated: (handle array byte)
 139   var truncated-ah/eax: (addr handle array byte) <- address truncated
-140   substring val, 0, 0xc, truncated-ah
-141   var _truncated-string/eax: (addr array byte) <- lookup *truncated-ah
+140   substring val, 0, 0xc, truncated-ah
+141   var _truncated-string/eax: (addr array byte) <- lookup *truncated-ah
 142   var truncated-string/edx: (addr array byte) <- copy _truncated-string
 143   var len/ebx: int <- length truncated-string
-144   draw-code-point screen, 0x22/double-quote, x, y, 7/fg, 0/bg
+144   draw-code-point screen, 0x22/double-quote, x, y, 7/fg, 0/bg
 145   increment x
-146   var new-x/eax: int <- draw-text-rightward-over-full-screen screen, truncated-string, x, y, 7/fg, 0/bg
+146   var new-x/eax: int <- draw-text-rightward-over-full-screen screen, truncated-string, x, y, 7/fg, 0/bg
 147   compare len, orig-len
 148   {
 149     break-if-=
-150     new-x <- draw-text-rightward-over-full-screen screen, "...", new-x, y, 7/fg, 0/bg
+150     new-x <- draw-text-rightward-over-full-screen screen, "...", new-x, y, 7/fg, 0/bg
 151   }
-152   draw-code-point screen, 0x22/double-quote, new-x, y, 7/fg, 0/bg
+152   draw-code-point screen, 0x22/double-quote, new-x, y, 7/fg, 0/bg
 153   new-x <- increment
 154   return new-x
 155 }
 156 
-157 fn test-render-string {
+157 fn test-render-string {
 158   # setup: screen
-159   var screen-on-stack: screen
-160   var screen/edi: (addr screen) <- address screen-on-stack
-161   initialize-screen screen, 0x20, 4
+159   var screen-on-stack: screen
+160   var screen/edi: (addr screen) <- address screen-on-stack
+161   initialize-screen screen, 0x20, 4
 162   # strings render with quotes
-163   var new-x/eax: int <- render-string screen, "abc", 0/x, 0/y
-164   check-screen-row screen, 0/y, "\"abc\"", "F - test-render-string"
-165   check-ints-equal new-x, 5, "F - test-render-string: result"
+163   var new-x/eax: int <- render-string screen, "abc", 0/x, 0/y
+164   check-screen-row screen, 0/y, "\"abc\"", "F - test-render-string"
+165   check-ints-equal new-x, 5, "F - test-render-string: result"
 166 }
 167 
-168 fn initialize-value-with-array-of-integers _self: (addr value), s: (addr array byte) {
+168 fn initialize-value-with-array-of-integers _self: (addr value), s: (addr array byte) {
 169   # parse s into a temporary array of ints
 170   var tmp-storage: (handle array int)
 171   var tmp-ah/eax: (addr handle array int) <- address tmp-storage
-172   parse-array-of-decimal-ints s, tmp-ah  # leak
-173   var _tmp/eax: (addr array int ) <- lookup *tmp-ah
+172   parse-array-of-decimal-ints s, tmp-ah  # leak
+173   var _tmp/eax: (addr array int ) <- lookup *tmp-ah
 174   var tmp/esi: (addr array int ) <- copy _tmp
 175   # load the array into values
-176   var self/edi: (addr value) <- copy _self
-177   var type/eax: (addr int) <- get self, type
+176   var self/edi: (addr value) <- copy _self
+177   var type/eax: (addr int) <- get self, type
 178   copy-to *type, 2/string
-179   var dest-array-ah/eax: (addr handle array value) <- get self, array-data
+179   var dest-array-ah/eax: (addr handle array value) <- get self, array-data
 180   var len/ebx: int <- length tmp
 181   populate dest-array-ah, len
-182   var _dest-array/eax: (addr array value) <- lookup *dest-array-ah
-183   var dest-array/edi: (addr array value) <- copy _dest-array
+182   var _dest-array/eax: (addr array value) <- lookup *dest-array-ah
+183   var dest-array/edi: (addr array value) <- copy _dest-array
 184   var i/eax: int <- copy 0
 185   {
 186     compare i, len
@@ -247,20 +247,20 @@ if ('onhashchange' in window) {
 188     var src-addr/ecx: (addr int) <- index tmp, i
 189     var src/ecx: int <- copy *src-addr
 190     var src-f/xmm0: float <- convert src
-191     var dest-offset/edx: (offset value) <- compute-offset dest-array, i
-192     var dest-val/edx: (addr value) <- index dest-array, dest-offset
-193     var dest/edx: (addr float) <- get dest-val, number-data
+191     var dest-offset/edx: (offset value) <- compute-offset dest-array, i
+192     var dest-val/edx: (addr value) <- index dest-array, dest-offset
+193     var dest/edx: (addr float) <- get dest-val, number-data
 194     copy-to *dest, src-f
 195     i <- increment
 196     loop
 197   }
 198 }
 199 
-200 fn render-array screen: (addr screen), _arr: (addr array value), x: int, y: int -> _/eax: int {
+200 fn render-array screen: (addr screen), _arr: (addr array value), x: int, y: int -> _/eax: int {
 201   # don't surround in spaces
-202   draw-code-point screen, 0x5b/open-bracket, x, y, 7/fg, 0/bg
+202   draw-code-point screen, 0x5b/open-bracket, x, y, 7/fg, 0/bg
 203   increment x
-204   var arr/esi: (addr array value) <- copy _arr
+204   var arr/esi: (addr array value) <- copy _arr
 205   var max/ecx: int <- length arr
 206   var i/edx: int <- copy 0
 207   var new-x/eax: int <- copy x
@@ -270,54 +270,54 @@ if ('onhashchange' in window) {
 211     {
 212       compare i, 0
 213       break-if-=
-214       draw-code-point screen, 0x20/space, new-x, y, 7/fg, 0/bg
+214       draw-code-point screen, 0x20/space, new-x, y, 7/fg, 0/bg
 215       new-x <- increment
 216     }
-217     var off/ecx: (offset value) <- compute-offset arr, i
-218     var x/ecx: (addr value) <- index arr, off
-219     new-x <- render-value screen, x, new-x, y, 0/nested
+217     var off/ecx: (offset value) <- compute-offset arr, i
+218     var x/ecx: (addr value) <- index arr, off
+219     new-x <- render-value screen, x, new-x, y, 0/nested
 220     i <- increment
 221     loop
 222   }
-223   draw-code-point screen, 0x5d/close-bracket, new-x, y, 7/fg, 0/bg
+223   draw-code-point screen, 0x5d/close-bracket, new-x, y, 7/fg, 0/bg
 224   new-x <- increment
 225   return new-x
 226 }
 227 
-228 fn test-render-array {
+228 fn test-render-array {
 229   # setup: screen
-230   var screen-on-stack: screen
-231   var screen/edi: (addr screen) <- address screen-on-stack
-232   initialize-screen screen, 0x20, 4
+230   var screen-on-stack: screen
+231   var screen/edi: (addr screen) <- address screen-on-stack
+232   initialize-screen screen, 0x20, 4
 233   #
-234   var val-storage: value
-235   var val/eax: (addr value) <- address val-storage
-236   initialize-value-with-array-of-integers val, "0 1 2"
-237   var val-array-ah/eax: (addr handle array value) <- get val, array-data
-238   var val-array/eax: (addr array value) <- lookup *val-array-ah
-239   var new-x/eax: int <- render-array screen, val-array, 0/x, 0/y
-240   check-screen-row screen, 0/y, "[0 1 2]", "F - test-render-array"
-241   check-ints-equal new-x, 7, "F - test-render-array: result"
+234   var val-storage: value
+235   var val/eax: (addr value) <- address val-storage
+236   initialize-value-with-array-of-integers val, "0 1 2"
+237   var val-array-ah/eax: (addr handle array value) <- get val, array-data
+238   var val-array/eax: (addr array value) <- lookup *val-array-ah
+239   var new-x/eax: int <- render-array screen, val-array, 0/x, 0/y
+240   check-screen-row screen, 0/y, "[0 1 2]", "F - test-render-array"
+241   check-ints-equal new-x, 7, "F - test-render-array: result"
 242 }
 243 
-244 fn initialize-value-with-boolean _self: (addr value), _b: boolean {
-245   var self/esi: (addr value) <- copy _self
-246   var type/eax: (addr int) <- get self, type
+244 fn initialize-value-with-boolean _self: (addr value), _b: boolean {
+245   var self/esi: (addr value) <- copy _self
+246   var type/eax: (addr int) <- get self, type
 247   copy-to *type, 3/boolean
-248   var dest/edi: (addr boolean) <- get self, boolean-data
+248   var dest/edi: (addr boolean) <- get self, boolean-data
 249   var b/esi: boolean <- copy _b
 250   copy-to *dest, b
 251 }
 252 
-253 fn render-boolean screen: (addr screen), val: boolean, x: int, y: int -> _/eax: int {
+253 fn render-boolean screen: (addr screen), val: boolean, x: int, y: int -> _/eax: int {
 254   var new-x/eax: int <- copy 0
 255   compare val, 0/false
 256   {
 257     break-if-=
-258     new-x <- draw-text-rightward-over-full-screen screen, "true", new-x, y, 7/fg, 0/bg
+258     new-x <- draw-text-rightward-over-full-screen screen, "true", new-x, y, 7/fg, 0/bg
 259     return new-x
 260   }
-261   new-x <- draw-text-rightward-over-full-screen screen, "false", new-x, y, 7/fg, 0/bg
+261   new-x <- draw-text-rightward-over-full-screen screen, "false", new-x, y, 7/fg, 0/bg
 262   return new-x
 263 }
 
diff --git a/html/baremetal/shell/word.mu.html b/html/baremetal/shell/word.mu.html index 40412697..f69a8c09 100644 --- a/html/baremetal/shell/word.mu.html +++ b/html/baremetal/shell/word.mu.html @@ -57,142 +57,142 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/main/baremetal/shell/word.mu
-  1 type word {
-  2   scalar-data: (handle gap-buffer)
-  3   next: (handle word)
-  4   prev: (handle word)
+  1 type word {
+  2   scalar-data: (handle gap-buffer)
+  3   next: (handle word)
+  4   prev: (handle word)
   5 }
   6 
-  7 fn initialize-word _self: (addr word) {
-  8   var self/esi: (addr word) <- copy _self
-  9   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
- 10   allocate data-ah
- 11   var data/eax: (addr gap-buffer) <- lookup *data-ah
- 12   initialize-gap-buffer data
+  7 fn initialize-word _self: (addr word) {
+  8   var self/esi: (addr word) <- copy _self
+  9   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+ 10   allocate data-ah
+ 11   var data/eax: (addr gap-buffer) <- lookup *data-ah
+ 12   initialize-gap-buffer data
  13 }
  14 
  15 ## some helpers for creating words. mostly for tests
  16 
- 17 fn initialize-word-with _self: (addr word), s: (addr array byte) {
- 18   var self/esi: (addr word) <- copy _self
- 19   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
- 20   allocate data-ah
- 21   var data/eax: (addr gap-buffer) <- lookup *data-ah
- 22   initialize-gap-buffer-with data, s
+ 17 fn initialize-word-with _self: (addr word), s: (addr array byte) {
+ 18   var self/esi: (addr word) <- copy _self
+ 19   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+ 20   allocate data-ah
+ 21   var data/eax: (addr gap-buffer) <- lookup *data-ah
+ 22   initialize-gap-buffer-with data, s
  23 }
  24 
- 25 fn allocate-word-with _out: (addr handle word), s: (addr array byte) {
- 26   var out/eax: (addr handle word) <- copy _out
- 27   allocate out
- 28   var out-addr/eax: (addr word) <- lookup *out
- 29   initialize-word-with out-addr, s
+ 25 fn allocate-word-with _out: (addr handle word), s: (addr array byte) {
+ 26   var out/eax: (addr handle word) <- copy _out
+ 27   allocate out
+ 28   var out-addr/eax: (addr word) <- lookup *out
+ 29   initialize-word-with out-addr, s
  30 }
  31 
  32 # just for tests for now
  33 # TODO: handle existing next
  34 # one implication of handles: append must take a handle
- 35 fn append-word-with self-h: (handle word), s: (addr array byte) {
- 36   var self/eax: (addr word) <- lookup self-h
- 37   var next-ah/eax: (addr handle word) <- get self, next
- 38   allocate-word-with next-ah, s
- 39   var next/eax: (addr word) <- lookup *next-ah
- 40   var prev-ah/eax: (addr handle word) <- get next, prev
- 41   copy-handle self-h, prev-ah
+ 35 fn append-word-with self-h: (handle word), s: (addr array byte) {
+ 36   var self/eax: (addr word) <- lookup self-h
+ 37   var next-ah/eax: (addr handle word) <- get self, next
+ 38   allocate-word-with next-ah, s
+ 39   var next/eax: (addr word) <- lookup *next-ah
+ 40   var prev-ah/eax: (addr handle word) <- get next, prev
+ 41   copy-handle self-h, prev-ah
  42 }
  43 
  44 # just for tests for now
  45 # TODO: handle existing prev
- 46 fn prepend-word-with self-h: (handle word), s: (addr array byte) {
- 47   var self/eax: (addr word) <- lookup self-h
- 48   var prev-ah/eax: (addr handle word) <- get self, prev
- 49   allocate-word-with prev-ah, s
- 50   var prev/eax: (addr word) <- lookup *prev-ah
- 51   var next-ah/eax: (addr handle word) <- get prev, next
- 52   copy-handle self-h, next-ah
+ 46 fn prepend-word-with self-h: (handle word), s: (addr array byte) {
+ 47   var self/eax: (addr word) <- lookup self-h
+ 48   var prev-ah/eax: (addr handle word) <- get self, prev
+ 49   allocate-word-with prev-ah, s
+ 50   var prev/eax: (addr word) <- lookup *prev-ah
+ 51   var next-ah/eax: (addr handle word) <- get prev, next
+ 52   copy-handle self-h, next-ah
  53 }
  54 
  55 ## real primitives
  56 
- 57 fn move-word-contents _src-ah: (addr handle word), _dest-ah: (addr handle word) {
- 58   var dest-ah/eax: (addr handle word) <- copy _dest-ah
- 59   var _dest/eax: (addr word) <- lookup *dest-ah
- 60   var dest/edi: (addr word) <- copy _dest
- 61   var src-ah/eax: (addr handle word) <- copy _src-ah
- 62   var _src/eax: (addr word) <- lookup *src-ah
- 63   var src/esi: (addr word) <- copy _src
- 64   cursor-to-start src
- 65   var src-data-ah/eax: (addr handle gap-buffer) <- get src, scalar-data
- 66   var src-data/eax: (addr gap-buffer) <- lookup *src-data-ah
- 67   var src-stack/ecx: (addr grapheme-stack) <- get src-data, right
+ 57 fn move-word-contents _src-ah: (addr handle word), _dest-ah: (addr handle word) {
+ 58   var dest-ah/eax: (addr handle word) <- copy _dest-ah
+ 59   var _dest/eax: (addr word) <- lookup *dest-ah
+ 60   var dest/edi: (addr word) <- copy _dest
+ 61   var src-ah/eax: (addr handle word) <- copy _src-ah
+ 62   var _src/eax: (addr word) <- lookup *src-ah
+ 63   var src/esi: (addr word) <- copy _src
+ 64   cursor-to-start src
+ 65   var src-data-ah/eax: (addr handle gap-buffer) <- get src, scalar-data
+ 66   var src-data/eax: (addr gap-buffer) <- lookup *src-data-ah
+ 67   var src-stack/ecx: (addr grapheme-stack) <- get src-data, right
  68   {
- 69     var done?/eax: boolean <- grapheme-stack-empty? src-stack
+ 69     var done?/eax: boolean <- grapheme-stack-empty? src-stack
  70     compare done?, 0/false
  71     break-if-!=
- 72     var g/eax: grapheme <- pop-grapheme-stack src-stack
- 73     add-grapheme-to-word dest, g
+ 72     var g/eax: grapheme <- pop-grapheme-stack src-stack
+ 73     add-grapheme-to-word dest, g
  74     loop
  75   }
  76 }
  77 
- 78 fn copy-word-contents-before-cursor _src-ah: (addr handle word), _dest-ah: (addr handle word) {
- 79   var dest-ah/eax: (addr handle word) <- copy _dest-ah
- 80   var _dest/eax: (addr word) <- lookup *dest-ah
- 81   var dest/edi: (addr word) <- copy _dest
- 82   var src-ah/eax: (addr handle word) <- copy _src-ah
- 83   var src/eax: (addr word) <- lookup *src-ah
- 84   var src-data-ah/eax: (addr handle gap-buffer) <- get src, scalar-data
- 85   var src-data/eax: (addr gap-buffer) <- lookup *src-data-ah
- 86   var src-stack/ecx: (addr grapheme-stack) <- get src-data, left
- 87   var src-stack-data-ah/eax: (addr handle array grapheme) <- get src-stack, data
- 88   var _src-stack-data/eax: (addr array grapheme) <- lookup *src-stack-data-ah
+ 78 fn copy-word-contents-before-cursor _src-ah: (addr handle word), _dest-ah: (addr handle word) {
+ 79   var dest-ah/eax: (addr handle word) <- copy _dest-ah
+ 80   var _dest/eax: (addr word) <- lookup *dest-ah
+ 81   var dest/edi: (addr word) <- copy _dest
+ 82   var src-ah/eax: (addr handle word) <- copy _src-ah
+ 83   var src/eax: (addr word) <- lookup *src-ah
+ 84   var src-data-ah/eax: (addr handle gap-buffer) <- get src, scalar-data
+ 85   var src-data/eax: (addr gap-buffer) <- lookup *src-data-ah
+ 86   var src-stack/ecx: (addr grapheme-stack) <- get src-data, left
+ 87   var src-stack-data-ah/eax: (addr handle array grapheme) <- get src-stack, data
+ 88   var _src-stack-data/eax: (addr array grapheme) <- lookup *src-stack-data-ah
  89   var src-stack-data/edx: (addr array grapheme) <- copy _src-stack-data
- 90   var top-addr/ecx: (addr int) <- get src-stack, top
+ 90   var top-addr/ecx: (addr int) <- get src-stack, top
  91   var i/eax: int <- copy 0
  92   {
  93     compare i, *top-addr
  94     break-if->=
  95     var g/edx: (addr grapheme) <- index src-stack-data, i
- 96     add-grapheme-to-word dest, *g
+ 96     add-grapheme-to-word dest, *g
  97     i <- increment
  98     loop
  99   }
 100 }
 101 
-102 fn word-equal? _self: (addr word), s: (addr array byte) -> _/eax: boolean {
-103   var self/esi: (addr word) <- copy _self
-104   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-105   var data/eax: (addr gap-buffer) <- lookup *data-ah
-106   var result/eax: boolean <- gap-buffer-equal? data, s
+102 fn word-equal? _self: (addr word), s: (addr array byte) -> _/eax: boolean {
+103   var self/esi: (addr word) <- copy _self
+104   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+105   var data/eax: (addr gap-buffer) <- lookup *data-ah
+106   var result/eax: boolean <- gap-buffer-equal? data, s
 107   return result
 108 }
 109 
-110 fn words-equal? _self: (addr word), _w: (addr word) -> _/eax: boolean {
-111   var self/eax: (addr word) <- copy _self
-112   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-113   var _data/eax: (addr gap-buffer) <- lookup *data-ah
-114   var data/ecx: (addr gap-buffer) <- copy _data
-115   var w/eax: (addr word) <- copy _w
-116   var w-data-ah/eax: (addr handle gap-buffer) <- get w, scalar-data
-117   var w-data/eax: (addr gap-buffer) <- lookup *w-data-ah
-118   var result/eax: boolean <- gap-buffers-equal? data, w-data
+110 fn words-equal? _self: (addr word), _w: (addr word) -> _/eax: boolean {
+111   var self/eax: (addr word) <- copy _self
+112   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+113   var _data/eax: (addr gap-buffer) <- lookup *data-ah
+114   var data/ecx: (addr gap-buffer) <- copy _data
+115   var w/eax: (addr word) <- copy _w
+116   var w-data-ah/eax: (addr handle gap-buffer) <- get w, scalar-data
+117   var w-data/eax: (addr gap-buffer) <- lookup *w-data-ah
+118   var result/eax: boolean <- gap-buffers-equal? data, w-data
 119   return result
 120 }
 121 
-122 fn word-length _self: (addr word) -> _/eax: int {
-123   var self/esi: (addr word) <- copy _self
-124   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-125   var data/eax: (addr gap-buffer) <- lookup *data-ah
-126   var result/eax: int <- gap-buffer-length data
+122 fn word-length _self: (addr word) -> _/eax: int {
+123   var self/esi: (addr word) <- copy _self
+124   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+125   var data/eax: (addr gap-buffer) <- lookup *data-ah
+126   var result/eax: int <- gap-buffer-length data
 127   return result
 128 }
 129 
-130 fn first-word _in: (addr handle word), out: (addr handle word) {
-131   var curr-ah/esi: (addr handle word) <- copy _in
-132   var curr/eax: (addr word) <- lookup *curr-ah
-133   var prev/edi: (addr handle word) <- copy 0
+130 fn first-word _in: (addr handle word), out: (addr handle word) {
+131   var curr-ah/esi: (addr handle word) <- copy _in
+132   var curr/eax: (addr word) <- lookup *curr-ah
+133   var prev/edi: (addr handle word) <- copy 0
 134   {
-135     prev <- get curr, prev
-136     var curr/eax: (addr word) <- lookup *prev
+135     prev <- get curr, prev
+136     var curr/eax: (addr word) <- lookup *prev
 137     compare curr, 0
 138     break-if-=
 139     copy-object prev, curr-ah
@@ -201,16 +201,16 @@ if ('onhashchange' in window) {
 142   copy-object curr-ah, out
 143 }
 144 
-145 fn final-word _in: (addr handle word), out: (addr handle word) {
-146   var curr-h: (handle word)
-147   var curr-ah/esi: (addr handle word) <- address curr-h
+145 fn final-word _in: (addr handle word), out: (addr handle word) {
+146   var curr-h: (handle word)
+147   var curr-ah/esi: (addr handle word) <- address curr-h
 148   copy-object _in, curr-ah
-149   var curr/eax: (addr word) <- copy 0
-150   var next/edi: (addr handle word) <- copy 0
+149   var curr/eax: (addr word) <- copy 0
+150   var next/edi: (addr handle word) <- copy 0
 151   {
-152     curr <- lookup *curr-ah
-153     next <- get curr, next
-154     curr <- lookup *next
+152     curr <- lookup *curr-ah
+153     next <- get curr, next
+154     curr <- lookup *next
 155     compare curr, 0
 156     break-if-=
 157     copy-object next, curr-ah
@@ -219,124 +219,124 @@ if ('onhashchange' in window) {
 160   copy-object curr-ah, out  # modify 'out' right at the end, just in case it's same as 'in'
 161 }
 162 
-163 fn first-grapheme _self: (addr word) -> _/eax: grapheme {
-164   var self/esi: (addr word) <- copy _self
-165   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-166   var data/eax: (addr gap-buffer) <- lookup *data-ah
-167   var result/eax: grapheme <- first-grapheme-in-gap-buffer data
+163 fn first-grapheme _self: (addr word) -> _/eax: grapheme {
+164   var self/esi: (addr word) <- copy _self
+165   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+166   var data/eax: (addr gap-buffer) <- lookup *data-ah
+167   var result/eax: grapheme <- first-grapheme-in-gap-buffer data
 168   return result
 169 }
 170 
-171 fn grapheme-before-cursor _self: (addr word) -> _/eax: grapheme {
-172   var self/esi: (addr word) <- copy _self
-173   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-174   var data/eax: (addr gap-buffer) <- lookup *data-ah
-175   var result/eax: grapheme <- grapheme-before-cursor-in-gap-buffer data
+171 fn grapheme-before-cursor _self: (addr word) -> _/eax: grapheme {
+172   var self/esi: (addr word) <- copy _self
+173   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+174   var data/eax: (addr gap-buffer) <- lookup *data-ah
+175   var result/eax: grapheme <- grapheme-before-cursor-in-gap-buffer data
 176   return result
 177 }
 178 
-179 fn add-grapheme-to-word _self: (addr word), c: grapheme {
-180   var self/esi: (addr word) <- copy _self
-181   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-182   var data/eax: (addr gap-buffer) <- lookup *data-ah
-183   add-grapheme-at-gap data, c
+179 fn add-grapheme-to-word _self: (addr word), c: grapheme {
+180   var self/esi: (addr word) <- copy _self
+181   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+182   var data/eax: (addr gap-buffer) <- lookup *data-ah
+183   add-grapheme-at-gap data, c
 184 }
 185 
-186 fn cursor-at-start? _self: (addr word) -> _/eax: boolean {
-187   var self/esi: (addr word) <- copy _self
-188   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-189   var data/eax: (addr gap-buffer) <- lookup *data-ah
-190   var result/eax: boolean <- gap-at-start? data
+186 fn cursor-at-start? _self: (addr word) -> _/eax: boolean {
+187   var self/esi: (addr word) <- copy _self
+188   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+189   var data/eax: (addr gap-buffer) <- lookup *data-ah
+190   var result/eax: boolean <- gap-at-start? data
 191   return result
 192 }
 193 
-194 fn cursor-at-end? _self: (addr word) -> _/eax: boolean {
-195   var self/esi: (addr word) <- copy _self
-196   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-197   var data/eax: (addr gap-buffer) <- lookup *data-ah
-198   var result/eax: boolean <- gap-at-end? data
+194 fn cursor-at-end? _self: (addr word) -> _/eax: boolean {
+195   var self/esi: (addr word) <- copy _self
+196   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+197   var data/eax: (addr gap-buffer) <- lookup *data-ah
+198   var result/eax: boolean <- gap-at-end? data
 199   return result
 200 }
 201 
-202 fn cursor-left _self: (addr word) {
-203   var self/esi: (addr word) <- copy _self
-204   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-205   var data/eax: (addr gap-buffer) <- lookup *data-ah
-206   var dummy/eax: grapheme <- gap-left data
+202 fn cursor-left _self: (addr word) {
+203   var self/esi: (addr word) <- copy _self
+204   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+205   var data/eax: (addr gap-buffer) <- lookup *data-ah
+206   var dummy/eax: grapheme <- gap-left data
 207 }
 208 
-209 fn cursor-right _self: (addr word) {
-210   var self/esi: (addr word) <- copy _self
-211   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-212   var data/eax: (addr gap-buffer) <- lookup *data-ah
-213   var dummy/eax: grapheme <- gap-right data
+209 fn cursor-right _self: (addr word) {
+210   var self/esi: (addr word) <- copy _self
+211   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+212   var data/eax: (addr gap-buffer) <- lookup *data-ah
+213   var dummy/eax: grapheme <- gap-right data
 214 }
 215 
-216 fn cursor-to-start _self: (addr word) {
-217   var self/esi: (addr word) <- copy _self
-218   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-219   var data/eax: (addr gap-buffer) <- lookup *data-ah
-220   gap-to-start data
+216 fn cursor-to-start _self: (addr word) {
+217   var self/esi: (addr word) <- copy _self
+218   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+219   var data/eax: (addr gap-buffer) <- lookup *data-ah
+220   gap-to-start data
 221 }
 222 
-223 fn cursor-to-end _self: (addr word) {
-224   var self/esi: (addr word) <- copy _self
-225   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-226   var data/eax: (addr gap-buffer) <- lookup *data-ah
-227   gap-to-end data
+223 fn cursor-to-end _self: (addr word) {
+224   var self/esi: (addr word) <- copy _self
+225   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+226   var data/eax: (addr gap-buffer) <- lookup *data-ah
+227   gap-to-end data
 228 }
 229 
-230 fn cursor-index _self: (addr word) -> _/eax: int {
-231   var self/esi: (addr word) <- copy _self
-232   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-233   var data/eax: (addr gap-buffer) <- lookup *data-ah
-234   var result/eax: int <- index-of-gap data
+230 fn cursor-index _self: (addr word) -> _/eax: int {
+231   var self/esi: (addr word) <- copy _self
+232   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+233   var data/eax: (addr gap-buffer) <- lookup *data-ah
+234   var result/eax: int <- index-of-gap data
 235   return result
 236 }
 237 
-238 fn delete-before-cursor _self: (addr word) {
-239   var self/esi: (addr word) <- copy _self
-240   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-241   var data/eax: (addr gap-buffer) <- lookup *data-ah
-242   delete-before-gap data
+238 fn delete-before-cursor _self: (addr word) {
+239   var self/esi: (addr word) <- copy _self
+240   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+241   var data/eax: (addr gap-buffer) <- lookup *data-ah
+242   delete-before-gap data
 243 }
 244 
-245 fn pop-after-cursor _self: (addr word) -> _/eax: grapheme {
-246   var self/esi: (addr word) <- copy _self
-247   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-248   var data/eax: (addr gap-buffer) <- lookup *data-ah
-249   var result/eax: grapheme <- pop-after-gap data
+245 fn pop-after-cursor _self: (addr word) -> _/eax: grapheme {
+246   var self/esi: (addr word) <- copy _self
+247   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+248   var data/eax: (addr gap-buffer) <- lookup *data-ah
+249   var result/eax: grapheme <- pop-after-gap data
 250   return result
 251 }
 252 
-253 fn delete-next _self: (addr word) {
-254   var self/esi: (addr word) <- copy _self
-255   var next-ah/edi: (addr handle word) <- get self, next
-256   var next/eax: (addr word) <- lookup *next-ah
+253 fn delete-next _self: (addr word) {
+254   var self/esi: (addr word) <- copy _self
+255   var next-ah/edi: (addr handle word) <- get self, next
+256   var next/eax: (addr word) <- lookup *next-ah
 257   compare next, 0
 258   break-if-=
-259   var next-next-ah/ecx: (addr handle word) <- get next, next
-260   var self-ah/esi: (addr handle word) <- get next, prev
+259   var next-next-ah/ecx: (addr handle word) <- get next, next
+260   var self-ah/esi: (addr handle word) <- get next, prev
 261   copy-object next-next-ah, next-ah
-262   var new-next/eax: (addr word) <- lookup *next-next-ah
+262   var new-next/eax: (addr word) <- lookup *next-next-ah
 263   compare new-next, 0
 264   break-if-=
-265   var dest/eax: (addr handle word) <- get new-next, prev
+265   var dest/eax: (addr handle word) <- get new-next, prev
 266   copy-object self-ah, dest
 267 }
 268 
-269 fn render-word screen: (addr screen), _self: (addr word), x: int, y: int, render-cursor?: boolean -> _/eax: int {
-270   var self/esi: (addr word) <- copy _self
-271   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-272   var data/eax: (addr gap-buffer) <- lookup *data-ah
-273   var result/eax: int <- render-gap-buffer screen, data, x, y, render-cursor?
+269 fn render-word screen: (addr screen), _self: (addr word), x: int, y: int, render-cursor?: boolean -> _/eax: int {
+270   var self/esi: (addr word) <- copy _self
+271   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+272   var data/eax: (addr gap-buffer) <- lookup *data-ah
+273   var result/eax: int <- render-gap-buffer screen, data, x, y, render-cursor?
 274   return result
 275 }
 276 
-277 fn render-words screen: (addr screen), _words-ah: (addr handle word), x: int, y: int, cursor-word-addr: int -> _/eax: int {
-278   var words-ah/eax: (addr handle word) <- copy _words-ah
-279   var _words-a/eax: (addr word) <- lookup *words-ah
-280   var words-a/ecx: (addr word) <- copy _words-a
+277 fn render-words screen: (addr screen), _words-ah: (addr handle word), x: int, y: int, cursor-word-addr: int -> _/eax: int {
+278   var words-ah/eax: (addr handle word) <- copy _words-ah
+279   var _words-a/eax: (addr word) <- lookup *words-ah
+280   var words-a/ecx: (addr word) <- copy _words-a
 281   compare words-a, 0
 282   {
 283     break-if-!=
@@ -349,97 +349,97 @@ if ('onhashchange' in window) {
 290     break-if-!=
 291     render-cursor? <- copy 1/true
 292   }
-293   var next-x/eax: int <- render-word screen, words-a, x, y, render-cursor?
+293   var next-x/eax: int <- render-word screen, words-a, x, y, render-cursor?
 294   var space/edx: grapheme <- copy 0x20/space
-295   draw-grapheme screen, space, next-x, y, 3/fg=cyan, 0/bg
+295   draw-grapheme screen, space, next-x, y, 3/fg=cyan, 0/bg
 296   next-x <- increment
 297   # recurse
-298   var next-ah/ecx: (addr handle word) <- get words-a, next
-299   next-x <- render-words screen, next-ah, next-x, y, cursor-word-addr
+298   var next-ah/ecx: (addr handle word) <- get words-a, next
+299   next-x <- render-words screen, next-ah, next-x, y, cursor-word-addr
 300   return next-x
 301 }
 302 
-303 fn test-render-words {
+303 fn test-render-words {
 304   # words = [aaa, bbb, ccc, ddd]
-305   var w-storage: (handle word)
-306   var w-ah/esi: (addr handle word) <- address w-storage
-307   allocate-word-with w-ah, "aaa"
-308   append-word-at-end-with w-ah, "bbb"
-309   append-word-at-end-with w-ah, "ccc"
-310   append-word-at-end-with w-ah, "ddd"
+305   var w-storage: (handle word)
+306   var w-ah/esi: (addr handle word) <- address w-storage
+307   allocate-word-with w-ah, "aaa"
+308   append-word-at-end-with w-ah, "bbb"
+309   append-word-at-end-with w-ah, "ccc"
+310   append-word-at-end-with w-ah, "ddd"
 311   # setup: screen
-312   var screen-on-stack: screen
-313   var screen/edi: (addr screen) <- address screen-on-stack
-314   initialize-screen screen, 0x20, 4
+312   var screen-on-stack: screen
+313   var screen/edi: (addr screen) <- address screen-on-stack
+314   initialize-screen screen, 0x20, 4
 315   #
-316   var _w/eax: (addr word) <- lookup *w-ah
-317   var w/ecx: (addr word) <- copy _w
+316   var _w/eax: (addr word) <- lookup *w-ah
+317   var w/ecx: (addr word) <- copy _w
 318   var cursor-word/eax: int <- copy w
-319   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
-320   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
-321   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "   |                ", "F - test-render-words/0 cursor"
+319   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
+320   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
+321   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "   |                ", "F - test-render-words/0 cursor"
 322   # - start moving cursor left through final word
-323   cursor-left w
+323   cursor-left w
 324   var cursor-word/eax: int <- copy w
-325   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
-326   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
-327   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "  |                 ", "F - test-render-words/1 cursor"
+325   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
+326   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
+327   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "  |                 ", "F - test-render-words/1 cursor"
 328   #
-329   cursor-left w
+329   cursor-left w
 330   var cursor-word/eax: int <- copy w
-331   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
-332   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
-333   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  " |                  ", "F - test-render-words/2 cursor"
+331   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
+332   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
+333   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  " |                  ", "F - test-render-words/2 cursor"
 334   #
-335   cursor-left w
+335   cursor-left w
 336   var cursor-word/eax: int <- copy w
-337   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
-338   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
-339   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "|                   ", "F - test-render-words/3 cursor"
+337   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
+338   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
+339   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "|                   ", "F - test-render-words/3 cursor"
 340   # further moves left within the word change nothing
-341   cursor-left w
+341   cursor-left w
 342   var cursor-word/eax: int <- copy w
-343   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
-344   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
-345   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "|                   ", "F - test-render-words/4 cursor"
+343   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
+344   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
+345   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "|                   ", "F - test-render-words/4 cursor"
 346   # - switch to next word
-347   var w2-ah/eax: (addr handle word) <- get w, next
-348   var _w/eax: (addr word) <- lookup *w2-ah
-349   var w/ecx: (addr word) <- copy _w
+347   var w2-ah/eax: (addr handle word) <- get w, next
+348   var _w/eax: (addr word) <- lookup *w2-ah
+349   var w/ecx: (addr word) <- copy _w
 350   var cursor-word/eax: int <- copy w
-351   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
-352   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
-353   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "        |           ", "F - test-render-words/5 cursor"
+351   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
+352   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
+353   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "        |           ", "F - test-render-words/5 cursor"
 354   # now speed up a little
-355   cursor-left w
-356   cursor-left w
+355   cursor-left w
+356   cursor-left w
 357   var cursor-word/eax: int <- copy w
-358   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
-359   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
-360   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "      |             ", "F - test-render-words/6 cursor"
+358   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
+359   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
+360   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "      |             ", "F - test-render-words/6 cursor"
 361   #
-362   var w2-ah/eax: (addr handle word) <- get w, next
-363   var _w/eax: (addr word) <- lookup *w2-ah
-364   var w/ecx: (addr word) <- copy _w
-365   cursor-left w
+362   var w2-ah/eax: (addr handle word) <- get w, next
+363   var _w/eax: (addr word) <- lookup *w2-ah
+364   var w/ecx: (addr word) <- copy _w
+365   cursor-left w
 366   var cursor-word/eax: int <- copy w
-367   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
-368   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
-369   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "            |       ", "F - test-render-words/7 cursor"
+367   var new-x/eax: int <- render-words screen, w-ah, 0/x, 0/y, cursor-word
+368   check-screen-row screen, 0/y,                                   "aaa  bbb  ccc  ddd  ", "F - test-render-words/0"
+369   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "            |       ", "F - test-render-words/7 cursor"
 370 }
 371 
-372 fn render-words-in-reverse screen: (addr screen), _words-ah: (addr handle word), x: int, y: int, cursor-word-addr: int -> _/eax: int {
-373   var words-ah/eax: (addr handle word) <- copy _words-ah
-374   var _words-a/eax: (addr word) <- lookup *words-ah
-375   var words-a/ecx: (addr word) <- copy _words-a
+372 fn render-words-in-reverse screen: (addr screen), _words-ah: (addr handle word), x: int, y: int, cursor-word-addr: int -> _/eax: int {
+373   var words-ah/eax: (addr handle word) <- copy _words-ah
+374   var _words-a/eax: (addr word) <- lookup *words-ah
+375   var words-a/ecx: (addr word) <- copy _words-a
 376   compare words-a, 0
 377   {
 378     break-if-!=
 379     return x
 380   }
 381   # recurse
-382   var next-ah/eax: (addr handle word) <- get words-a, next
-383   var next-x/eax: int <- render-words-in-reverse screen, next-ah, x, y, cursor-word-addr
+382   var next-ah/eax: (addr handle word) <- get words-a, next
+383   var next-x/eax: int <- render-words-in-reverse screen, next-ah, x, y, cursor-word-addr
 384   # print
 385   var render-cursor?/edx: boolean <- copy 0/false
 386   {
@@ -447,244 +447,244 @@ if ('onhashchange' in window) {
 388     break-if-!=
 389     render-cursor? <- copy 1/true
 390   }
-391   next-x <- render-word screen, words-a, next-x, y, render-cursor?
+391   next-x <- render-word screen, words-a, next-x, y, render-cursor?
 392   var space/ecx: grapheme <- copy 0x20/space
-393   draw-grapheme screen, space, next-x, y, 3/fg=cyan, 0/bg
+393   draw-grapheme screen, space, next-x, y, 3/fg=cyan, 0/bg
 394   next-x <- increment
 395   return next-x
 396 }
 397 
-398 fn test-render-words-in-reverse {
+398 fn test-render-words-in-reverse {
 399   # words = [aaa, bbb, ccc, ddd]
-400   var w-storage: (handle word)
-401   var w-ah/esi: (addr handle word) <- address w-storage
-402   allocate-word-with w-ah, "aaa"
-403   append-word-at-end-with w-ah, "bbb"
-404   append-word-at-end-with w-ah, "ccc"
-405   append-word-at-end-with w-ah, "ddd"
+400   var w-storage: (handle word)
+401   var w-ah/esi: (addr handle word) <- address w-storage
+402   allocate-word-with w-ah, "aaa"
+403   append-word-at-end-with w-ah, "bbb"
+404   append-word-at-end-with w-ah, "ccc"
+405   append-word-at-end-with w-ah, "ddd"
 406   # setup: screen
-407   var screen-on-stack: screen
-408   var screen/edi: (addr screen) <- address screen-on-stack
-409   initialize-screen screen, 0x20, 4
+407   var screen-on-stack: screen
+408   var screen/edi: (addr screen) <- address screen-on-stack
+409   initialize-screen screen, 0x20, 4
 410   #
-411   var _w/eax: (addr word) <- lookup *w-ah
-412   var w/ecx: (addr word) <- copy _w
+411   var _w/eax: (addr word) <- lookup *w-ah
+412   var w/ecx: (addr word) <- copy _w
 413   var cursor-word/eax: int <- copy w
-414   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
-415   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/0"
-416   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "                  | ", "F - test-render-words-in-reverse/0 cursor"
+414   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
+415   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/0"
+416   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "                  | ", "F - test-render-words-in-reverse/0 cursor"
 417   # - start moving cursor left through final word
-418   cursor-left w
+418   cursor-left w
 419   var cursor-word/eax: int <- copy w
-420   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
-421   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/1"
-422   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "                 |  ", "F - test-render-words-in-reverse/1 cursor"
+420   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
+421   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/1"
+422   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "                 |  ", "F - test-render-words-in-reverse/1 cursor"
 423   #
-424   cursor-left w
+424   cursor-left w
 425   var cursor-word/eax: int <- copy w
-426   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
-427   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/2"
-428   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "                |   ", "F - test-render-words-in-reverse/2 cursor"
+426   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
+427   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/2"
+428   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "                |   ", "F - test-render-words-in-reverse/2 cursor"
 429   #
-430   cursor-left w
+430   cursor-left w
 431   var cursor-word/eax: int <- copy w
-432   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
-433   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/3"
-434   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "               |    ", "F - test-render-words-in-reverse/3 cursor"
+432   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
+433   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/3"
+434   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "               |    ", "F - test-render-words-in-reverse/3 cursor"
 435   # further moves left within the word change nothing
-436   cursor-left w
+436   cursor-left w
 437   var cursor-word/eax: int <- copy w
-438   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
-439   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/4"
-440   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "               |    ", "F - test-render-words-in-reverse/4 cursor"
+438   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
+439   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/4"
+440   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "               |    ", "F - test-render-words-in-reverse/4 cursor"
 441   # - switch to next word
-442   var w2-ah/eax: (addr handle word) <- get w, next
-443   var _w/eax: (addr word) <- lookup *w2-ah
-444   var w/ecx: (addr word) <- copy _w
+442   var w2-ah/eax: (addr handle word) <- get w, next
+443   var _w/eax: (addr word) <- lookup *w2-ah
+444   var w/ecx: (addr word) <- copy _w
 445   var cursor-word/eax: int <- copy w
-446   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
-447   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/5"
-448   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "             |      ", "F - test-render-words-in-reverse/5 cursor"
+446   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
+447   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/5"
+448   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "             |      ", "F - test-render-words-in-reverse/5 cursor"
 449   # now speed up a little
-450   cursor-left w
-451   cursor-left w
+450   cursor-left w
+451   cursor-left w
 452   var cursor-word/eax: int <- copy w
-453   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
-454   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/6"
-455   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "           |        ", "F - test-render-words-in-reverse/6 cursor"
+453   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
+454   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/6"
+455   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "           |        ", "F - test-render-words-in-reverse/6 cursor"
 456   #
-457   var w2-ah/eax: (addr handle word) <- get w, next
-458   var _w/eax: (addr word) <- lookup *w2-ah
-459   var w/ecx: (addr word) <- copy _w
-460   cursor-left w
+457   var w2-ah/eax: (addr handle word) <- get w, next
+458   var _w/eax: (addr word) <- lookup *w2-ah
+459   var w/ecx: (addr word) <- copy _w
+460   cursor-left w
 461   var cursor-word/eax: int <- copy w
-462   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
-463   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/7"
-464   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "       |            ", "F - test-render-words-in-reverse/7 cursor"
+462   var new-x/eax: int <- render-words-in-reverse screen, w-ah, 0/x, 0/y, cursor-word
+463   check-screen-row screen, 0/y,                                   "ddd  ccc  bbb  aaa  ", "F - test-render-words-in-reverse/7"
+464   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y,  "       |            ", "F - test-render-words-in-reverse/7 cursor"
 465 }
 466 
 467 # Gotcha with some word operations: ensure dest-ah isn't in the middle of some
 468 # existing chain of words. There are two pointers to patch, and you'll forget
 469 # to do the other one.
-470 fn copy-words _src-ah: (addr handle word), _dest-ah: (addr handle word) {
-471   var src-ah/eax: (addr handle word) <- copy _src-ah
-472   var src-a/eax: (addr word) <- lookup *src-ah
+470 fn copy-words _src-ah: (addr handle word), _dest-ah: (addr handle word) {
+471   var src-ah/eax: (addr handle word) <- copy _src-ah
+472   var src-a/eax: (addr word) <- lookup *src-ah
 473   compare src-a, 0
 474   break-if-=
 475   # copy
-476   var dest-ah/edi: (addr handle word) <- copy _dest-ah
-477   copy-word src-a, dest-ah
+476   var dest-ah/edi: (addr handle word) <- copy _dest-ah
+477   copy-word src-a, dest-ah
 478   # recurse
-479   var rest: (handle word)
-480   var rest-ah/ecx: (addr handle word) <- address rest
-481   var next-src-ah/esi: (addr handle word) <- get src-a, next
-482   copy-words next-src-ah, rest-ah
-483   chain-words dest-ah, rest-ah
+479   var rest: (handle word)
+480   var rest-ah/ecx: (addr handle word) <- address rest
+481   var next-src-ah/esi: (addr handle word) <- get src-a, next
+482   copy-words next-src-ah, rest-ah
+483   chain-words dest-ah, rest-ah
 484 }
 485 
-486 fn copy-words-in-reverse _src-ah: (addr handle word), _dest-ah: (addr handle word) {
-487   var src-ah/eax: (addr handle word) <- copy _src-ah
-488   var _src-a/eax: (addr word) <- lookup *src-ah
-489   var src-a/esi: (addr word) <- copy _src-a
+486 fn copy-words-in-reverse _src-ah: (addr handle word), _dest-ah: (addr handle word) {
+487   var src-ah/eax: (addr handle word) <- copy _src-ah
+488   var _src-a/eax: (addr word) <- lookup *src-ah
+489   var src-a/esi: (addr word) <- copy _src-a
 490   compare src-a, 0
 491   break-if-=
 492   # recurse
-493   var next-src-ah/ecx: (addr handle word) <- get src-a, next
-494   var dest-ah/edi: (addr handle word) <- copy _dest-ah
-495   copy-words-in-reverse next-src-ah, dest-ah
+493   var next-src-ah/ecx: (addr handle word) <- get src-a, next
+494   var dest-ah/edi: (addr handle word) <- copy _dest-ah
+495   copy-words-in-reverse next-src-ah, dest-ah
 496   #
-497   copy-word-at-end src-a, dest-ah
+497   copy-word-at-end src-a, dest-ah
 498 }
 499 
-500 fn copy-word-at-end src: (addr word), _dest-ah: (addr handle word) {
-501   var dest-ah/edi: (addr handle word) <- copy _dest-ah
+500 fn copy-word-at-end src: (addr word), _dest-ah: (addr handle word) {
+501   var dest-ah/edi: (addr handle word) <- copy _dest-ah
 502   # if dest is null, copy and return
-503   var dest-a/eax: (addr word) <- lookup *dest-ah
+503   var dest-a/eax: (addr word) <- lookup *dest-ah
 504   compare dest-a, 0
 505   {
 506     break-if-!=
-507     copy-word src, dest-ah
+507     copy-word src, dest-ah
 508     return
 509   }
 510   # copy current word
-511   var new: (handle word)
-512   var new-ah/ecx: (addr handle word) <- address new
-513   copy-word src, new-ah
+511   var new: (handle word)
+512   var new-ah/ecx: (addr handle word) <- address new
+513   copy-word src, new-ah
 514   # append it at the end
-515   var curr-ah/edi: (addr handle word) <- copy dest-ah
+515   var curr-ah/edi: (addr handle word) <- copy dest-ah
 516   {
-517     var curr-a/eax: (addr word) <- lookup *curr-ah  # curr-a guaranteed not to be null
-518     var next-ah/ecx: (addr handle word) <- get curr-a, next
-519     var next-a/eax: (addr word) <- lookup *next-ah
+517     var curr-a/eax: (addr word) <- lookup *curr-ah  # curr-a guaranteed not to be null
+518     var next-ah/ecx: (addr handle word) <- get curr-a, next
+519     var next-a/eax: (addr word) <- lookup *next-ah
 520     compare next-a, 0
 521     break-if-=
 522     curr-ah <- copy next-ah
 523     loop
 524   }
-525   chain-words curr-ah, new-ah
+525   chain-words curr-ah, new-ah
 526 }
 527 
-528 fn append-word-at-end-with _dest-ah: (addr handle word), s: (addr array byte) {
-529   var dest-ah/edi: (addr handle word) <- copy _dest-ah
+528 fn append-word-at-end-with _dest-ah: (addr handle word), s: (addr array byte) {
+529   var dest-ah/edi: (addr handle word) <- copy _dest-ah
 530   # if dest is null, copy and return
-531   var dest-a/eax: (addr word) <- lookup *dest-ah
+531   var dest-a/eax: (addr word) <- lookup *dest-ah
 532   compare dest-a, 0
 533   {
 534     break-if-!=
-535     allocate-word-with dest-ah, s
+535     allocate-word-with dest-ah, s
 536     return
 537   }
 538   # otherwise append at end
-539   var curr-ah/edi: (addr handle word) <- copy dest-ah
+539   var curr-ah/edi: (addr handle word) <- copy dest-ah
 540   {
-541     var curr-a/eax: (addr word) <- lookup *curr-ah  # curr-a guaranteed not to be null
-542     var next-ah/ecx: (addr handle word) <- get curr-a, next
-543     var next-a/eax: (addr word) <- lookup *next-ah
+541     var curr-a/eax: (addr word) <- lookup *curr-ah  # curr-a guaranteed not to be null
+542     var next-ah/ecx: (addr handle word) <- get curr-a, next
+543     var next-a/eax: (addr word) <- lookup *next-ah
 544     compare next-a, 0
 545     break-if-=
 546     curr-ah <- copy next-ah
 547     loop
 548   }
-549   append-word-with *curr-ah, s
+549   append-word-with *curr-ah, s
 550 }
 551 
-552 fn copy-word _src-a: (addr word), _dest-ah: (addr handle word) {
-553   var dest-ah/eax: (addr handle word) <- copy _dest-ah
-554   allocate dest-ah
-555   var _dest-a/eax: (addr word) <- lookup *dest-ah
-556   var dest-a/eax: (addr word) <- copy _dest-a
-557   initialize-word dest-a
-558   var dest/edi: (addr handle gap-buffer) <- get dest-a, scalar-data
-559   var src-a/eax: (addr word) <- copy _src-a
-560   var src/eax: (addr handle gap-buffer) <- get src-a, scalar-data
-561   copy-gap-buffer src, dest
+552 fn copy-word _src-a: (addr word), _dest-ah: (addr handle word) {
+553   var dest-ah/eax: (addr handle word) <- copy _dest-ah
+554   allocate dest-ah
+555   var _dest-a/eax: (addr word) <- lookup *dest-ah
+556   var dest-a/eax: (addr word) <- copy _dest-a
+557   initialize-word dest-a
+558   var dest/edi: (addr handle gap-buffer) <- get dest-a, scalar-data
+559   var src-a/eax: (addr word) <- copy _src-a
+560   var src/eax: (addr handle gap-buffer) <- get src-a, scalar-data
+561   copy-gap-buffer src, dest
 562 }
 563 
 564 # one implication of handles: append must take a handle
-565 fn append-word _self-ah: (addr handle word) {
-566   var saved-self-storage: (handle word)
-567   var saved-self/eax: (addr handle word) <- address saved-self-storage
+565 fn append-word _self-ah: (addr handle word) {
+566   var saved-self-storage: (handle word)
+567   var saved-self/eax: (addr handle word) <- address saved-self-storage
 568   copy-object _self-ah, saved-self
-569   var self-ah/esi: (addr handle word) <- copy _self-ah
-570   var _self/eax: (addr word) <- lookup *self-ah
-571   var self/ebx: (addr word) <- copy _self
+569   var self-ah/esi: (addr handle word) <- copy _self-ah
+570   var _self/eax: (addr word) <- lookup *self-ah
+571   var self/ebx: (addr word) <- copy _self
 572   # allocate new handle
-573   var new: (handle word)
-574   var new-ah/ecx: (addr handle word) <- address new
-575   allocate new-ah
-576   var new-addr/eax: (addr word) <- lookup new
-577   initialize-word new-addr
+573   var new: (handle word)
+574   var new-ah/ecx: (addr handle word) <- address new
+575   allocate new-ah
+576   var new-addr/eax: (addr word) <- lookup new
+577   initialize-word new-addr
 578   # new->next = self->next
-579   var src/esi: (addr handle word) <- get self, next
-580   var dest/edi: (addr handle word) <- get new-addr, next
+579   var src/esi: (addr handle word) <- get self, next
+580   var dest/edi: (addr handle word) <- get new-addr, next
 581   copy-object src, dest
 582   # new->next->prev = new
 583   {
-584     var next-addr/eax: (addr word) <- lookup *src
+584     var next-addr/eax: (addr word) <- lookup *src
 585     compare next-addr, 0
 586     break-if-=
-587     dest <- get next-addr, prev
+587     dest <- get next-addr, prev
 588     copy-object new-ah, dest
 589   }
 590   # new->prev = saved-self
-591   dest <- get new-addr, prev
-592   var saved-self-ah/eax: (addr handle word) <- address saved-self-storage
+591   dest <- get new-addr, prev
+592   var saved-self-ah/eax: (addr handle word) <- address saved-self-storage
 593   copy-object saved-self-ah, dest
 594   # self->next = new
-595   dest <- get self, next
+595   dest <- get self, next
 596   copy-object new-ah, dest
 597 }
 598 
-599 fn chain-words _self-ah: (addr handle word), _next: (addr handle word) {
-600   var self-ah/esi: (addr handle word) <- copy _self-ah
-601   var _self/eax: (addr word) <- lookup *self-ah
-602   var self/ecx: (addr word) <- copy _self
-603   var dest/edx: (addr handle word) <- get self, next
-604   var next-ah/edi: (addr handle word) <- copy _next
+599 fn chain-words _self-ah: (addr handle word), _next: (addr handle word) {
+600   var self-ah/esi: (addr handle word) <- copy _self-ah
+601   var _self/eax: (addr word) <- lookup *self-ah
+602   var self/ecx: (addr word) <- copy _self
+603   var dest/edx: (addr handle word) <- get self, next
+604   var next-ah/edi: (addr handle word) <- copy _next
 605   copy-object next-ah, dest
-606   var next/eax: (addr word) <- lookup *next-ah
+606   var next/eax: (addr word) <- lookup *next-ah
 607   compare next, 0
 608   break-if-=
-609   dest <- get next, prev
+609   dest <- get next, prev
 610   copy-object self-ah, dest
 611 }
 612 
-613 fn emit-word _self: (addr word), out: (addr stream byte) {
-614   var self/esi: (addr word) <- copy _self
-615   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-616   var data/eax: (addr gap-buffer) <- lookup *data-ah
-617   emit-gap-buffer data, out
+613 fn emit-word _self: (addr word), out: (addr stream byte) {
+614   var self/esi: (addr word) <- copy _self
+615   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+616   var data/eax: (addr gap-buffer) <- lookup *data-ah
+617   emit-gap-buffer data, out
 618 }
 619 
-620 fn word-is-decimal-integer? _self: (addr word) -> _/eax: boolean {
-621   var self/eax: (addr word) <- copy _self
-622   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
-623   var data/eax: (addr gap-buffer) <- lookup *data-ah
-624   var result/eax: boolean <- gap-buffer-is-decimal-integer? data
+620 fn word-is-decimal-integer? _self: (addr word) -> _/eax: boolean {
+621   var self/eax: (addr word) <- copy _self
+622   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
+623   var data/eax: (addr gap-buffer) <- lookup *data-ah
+624   var result/eax: boolean <- gap-buffer-is-decimal-integer? data
 625   return result
 626 }
 627 
-628 fn word-exists? haystack: (addr word), needle: (addr word) -> _/eax: boolean {
+628 fn word-exists? haystack: (addr word), needle: (addr word) -> _/eax: boolean {
 629   # base case
 630   compare haystack, 0
 631   {
@@ -692,89 +692,89 @@ if ('onhashchange' in window) {
 633     return 0/false
 634   }
 635   # check current word
-636   var found?/eax: boolean <- words-equal? haystack, needle
+636   var found?/eax: boolean <- words-equal? haystack, needle
 637   compare found?, 0/false
 638   {
 639     break-if-=
 640     return 1/true
 641   }
 642   # recurse
-643   var curr/eax: (addr word) <- copy haystack
-644   var next-ah/eax: (addr handle word) <- get curr, next
-645   var next/eax: (addr word) <- lookup *next-ah
-646   var result/eax: boolean <- word-exists? next, needle
+643   var curr/eax: (addr word) <- copy haystack
+644   var next-ah/eax: (addr handle word) <- get curr, next
+645   var next/eax: (addr word) <- lookup *next-ah
+646   var result/eax: boolean <- word-exists? next, needle
 647   return result
 648 }
 649 
-650 fn test-word-exists? {
-651   var needle-storage: word
-652   var needle/esi: (addr word) <- address needle-storage
-653   initialize-word-with needle, "abc"
-654   var w-storage: (handle word)
-655   var w-ah/edi: (addr handle word) <- address w-storage
-656   allocate w-ah
-657   var _w/eax: (addr word) <- lookup *w-ah
-658   var w/ecx: (addr word) <- copy _w
-659   initialize-word-with w, "aaa"
+650 fn test-word-exists? {
+651   var needle-storage: word
+652   var needle/esi: (addr word) <- address needle-storage
+653   initialize-word-with needle, "abc"
+654   var w-storage: (handle word)
+655   var w-ah/edi: (addr handle word) <- address w-storage
+656   allocate w-ah
+657   var _w/eax: (addr word) <- lookup *w-ah
+658   var w/ecx: (addr word) <- copy _w
+659   initialize-word-with w, "aaa"
 660   #
-661   var result/eax: boolean <- word-exists? w, w
-662   check result, "F - test-word-exists? reflexive"
-663   result <- word-exists? w, needle
-664   check-not result, "F - test-word-exists? 1"
-665   append-word-at-end-with w-ah, "bbb"
-666   result <- word-exists? w, needle
-667   check-not result, "F - test-word-exists? 2"
-668   append-word-at-end-with w-ah, "abc"
-669   result <- word-exists? w, needle
-670   check result, "F - test-word-exists? 3"
-671   append-word-at-end-with w-ah, "ddd"
-672   result <- word-exists? w, needle
-673   check result, "F - test-word-exists? 4"
+661   var result/eax: boolean <- word-exists? w, w
+662   check result, "F - test-word-exists? reflexive"
+663   result <- word-exists? w, needle
+664   check-not result, "F - test-word-exists? 1"
+665   append-word-at-end-with w-ah, "bbb"
+666   result <- word-exists? w, needle
+667   check-not result, "F - test-word-exists? 2"
+668   append-word-at-end-with w-ah, "abc"
+669   result <- word-exists? w, needle
+670   check result, "F - test-word-exists? 3"
+671   append-word-at-end-with w-ah, "ddd"
+672   result <- word-exists? w, needle
+673   check result, "F - test-word-exists? 4"
 674 }
 675 
-676 fn word-list-length words: (addr handle word) -> _/eax: int {
-677   var curr-ah/esi: (addr handle word) <- copy words
+676 fn word-list-length words: (addr handle word) -> _/eax: int {
+677   var curr-ah/esi: (addr handle word) <- copy words
 678   var result/edi: int <- copy 0
 679   {
-680     var curr/eax: (addr word) <- lookup *curr-ah
+680     var curr/eax: (addr word) <- lookup *curr-ah
 681     compare curr, 0
 682     break-if-=
 683     {
-684       var word-len/eax: int <- word-length curr
+684       var word-len/eax: int <- word-length curr
 685       result <- add word-len
 686       result <- add 1/inter-word-margin
 687     }
-688     curr-ah <- get curr, next
+688     curr-ah <- get curr, next
 689     loop
 690   }
 691   return result
 692 }
 693 
 694 # out-ah already has a word allocated and initialized
-695 fn parse-words in: (addr array byte), out-ah: (addr handle word) {
+695 fn parse-words in: (addr array byte), out-ah: (addr handle word) {
 696   var in-stream: (stream byte 0x100)
 697   var in-stream-a/esi: (addr stream byte) <- address in-stream
-698   write in-stream-a, in
-699   var cursor-word-ah/ebx: (addr handle word) <- copy out-ah
+698   write in-stream-a, in
+699   var cursor-word-ah/ebx: (addr handle word) <- copy out-ah
 700   $parse-words:loop: {
-701     var done?/eax: boolean <- stream-empty? in-stream-a
+701     var done?/eax: boolean <- stream-empty? in-stream-a
 702     compare done?, 0/false
 703     break-if-!=
-704     var _g/eax: grapheme <- read-grapheme in-stream-a
+704     var _g/eax: grapheme <- read-grapheme in-stream-a
 705     var g/ecx: grapheme <- copy _g
 706     # if not space, insert
 707     compare g, 0x20/space
 708     {
 709       break-if-=
-710       var cursor-word/eax: (addr word) <- lookup *cursor-word-ah
-711       add-grapheme-to-word cursor-word, g
+710       var cursor-word/eax: (addr word) <- lookup *cursor-word-ah
+711       add-grapheme-to-word cursor-word, g
 712       loop $parse-words:loop
 713     }
 714     # otherwise insert word after and move cursor to it
-715     append-word cursor-word-ah
-716     var cursor-word/eax: (addr word) <- lookup *cursor-word-ah
-717     cursor-to-start cursor-word  # reset cursor in each function
-718     cursor-word-ah <- get cursor-word, next
+715     append-word cursor-word-ah
+716     var cursor-word/eax: (addr word) <- lookup *cursor-word-ah
+717     cursor-to-start cursor-word  # reset cursor in each function
+718     cursor-word-ah <- get cursor-word, next
 719     loop
 720   }
 721 }
diff --git a/tools/update_html b/tools/update_html
index e53bf459..e040dc89 100755
--- a/tools/update_html
+++ b/tools/update_html
@@ -74,7 +74,6 @@ done
 for f in apps/*/*.mu
 do
   test $# -gt 0  &&  test $1 != $f  &&  continue
-  echo $f
   ( cd `dirname $f`
     ctags -x ../../[0-9]*.subx ../../[0-9]*.mu *.mu > /tmp/tags
   )
@@ -111,8 +110,8 @@ done
 for f in baremetal/*/*.mu
 do
   test $# -gt 0  &&  test $1 != $f  &&  continue
-  ( cd baremetal
-    ctags -R -x [0-9]*.subx [0-9]*.mu $(basename $(dirname $f)) > /tmp/tags
+  ( cd `dirname $f`
+    ctags -x ../../[0-9]*.subx ../../[0-9]*.mu *.mu > /tmp/tags
   )
   process $f
 done