From c01289dddea2398fe7f4335f5d0babc4a9e789c5 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 9 Nov 2020 21:16:09 -0800 Subject: 7218 This bug was incredibly painful to track down: the one-line fix is to replace 'line' with 'first-line' in the call to 'evaluate' in render-line before recursing. Things that made it challenging: - A high degree of coiling with recursive calls and multiple places of evaluation. - An accidental aliasing in bindings (when rendering the main column in render-line) that masked the underlying bug and made things seem to work most of the time. - Too many fucking arguments to render-line, a maze of twisty line objects all alike. --- apps/tile/environment.mu | 35 +++++++++++++++--- apps/tile/main.mu | 11 +++--- apps/tile/rpn.mu | 6 ++-- apps/tile/table.mu | 93 ++++++++++++++++++++++++++++++++++++++++++++++++ apps/tile/value.mu | 5 ++- 5 files changed, 139 insertions(+), 11 deletions(-) diff --git a/apps/tile/environment.mu b/apps/tile/environment.mu index 597cad95..d9718525 100644 --- a/apps/tile/environment.mu +++ b/apps/tile/environment.mu @@ -1276,7 +1276,8 @@ fn call-path-element-length _x: (addr handle call-path-element) -> _/eax: int { # # Along the way, compute the column the cursor should be positioned at (cursor-col-addr). fn render-line screen: (addr screen), functions: (addr handle function), bindings: (addr table), first-line: (addr line), _line: (addr line), expanded-words: (addr handle call-path), top-row: int, left-col: int, curr-path: (addr handle call-path-element), cursor-word: (addr word), cursor-call-path: (addr handle call-path-element), cursor-row-addr: (addr int), cursor-col-addr: (addr int) -> _/ecx: int { -#? print-string 0, "--\n" + print-string 0, "## render-line: " + dump-table bindings # curr-word var line/esi: (addr line) <- copy _line var first-word-ah/eax: (addr handle word) <- get line, data @@ -1290,6 +1291,9 @@ fn render-line screen: (addr screen), functions: (addr handle function), binding { compare curr-word, 0 break-if-= + print-string 0, "-- word " + print-word 0, curr-word + print-string 0, "\n" #? print-string 0, "-- word in final line: " #? { #? var foo/eax: int <- copy curr-word @@ -1326,6 +1330,8 @@ fn render-line screen: (addr screen), functions: (addr handle function), binding increment top-row } # obtain stack at call site + print-string 0, "sub 0 bindings: " + dump-table bindings var stack-storage: value-stack var stack/edx: (addr value-stack) <- address stack-storage initialize-value-stack stack, 0x10 @@ -1334,8 +1340,12 @@ fn render-line screen: (addr screen), functions: (addr handle function), binding var prev-word/eax: (addr word) <- lookup *prev-word-ah compare prev-word, 0 break-if-= - evaluate functions, bindings, line, prev-word, stack + print-string 0, "sub 1 bindings: " + dump-table bindings + evaluate functions, bindings, first-line, prev-word, stack } + print-string 0, "sub 2 bindings: " + dump-table bindings # construct new bindings var callee-bindings-storage: table var callee-bindings/esi: (addr table) <- address callee-bindings-storage @@ -1347,7 +1357,11 @@ fn render-line screen: (addr screen), functions: (addr handle function), binding var callee-body-first-word/edx: (addr handle word) <- get callee-body, data # - render subsidiary stack push-to-call-path-element curr-path, callee-body-first-word # leak + print-string 0, "subsidiary { " + dump-table callee-bindings + syscall_exit curr-col <- render-line screen, functions, callee-bindings, callee-body, callee-body, expanded-words, top-row, curr-col, curr-path, cursor-word, cursor-call-path, cursor-row-addr, cursor-col-addr + print-string 0, "}\n" drop-from-call-path-element curr-path # move-cursor screen, top-row, curr-col @@ -1363,10 +1377,23 @@ fn render-line screen: (addr screen), functions: (addr handle function), binding #? print-string 0, "rendering column from " #? print-int32-decimal 0, curr-col #? print-string 0, "\n" + print-string 0, "main 0 bindings: " + dump-table bindings var bindings2-storage: table var bindings2/ebx: (addr table) <- address bindings2-storage shallow-copy-table-values bindings, bindings2 + print-string 0, "main 1 bindings: " + dump-table bindings + print-string 0, "main 1 bindings2: " + dump-table bindings2 + print-string 0, "word: " + print-word 0, curr-word + print-string 0, "\n" curr-col <- render-column screen, functions, bindings2, first-line, line, curr-word, top-row, curr-col + print-string 0, "main 2 bindings: " + dump-table bindings + print-string 0, "main 2 bindings2: " + dump-table bindings2 # cache cursor column if necessary $render-line:cache-cursor-column: { #? print-string 0, "cache cursor? " @@ -1423,8 +1450,8 @@ fn callee functions: (addr handle function), word: (addr word), out: (addr handl # # Return the farthest column written. fn render-column screen: (addr screen), functions: (addr handle function), bindings: (addr table), first-line: (addr line), line: (addr line), final-word: (addr word), top-row: int, left-col: int -> _/ecx: int { -#? print-string 0, "== " -#? print-string 0, "render-column\n" + print-string 0, "render-column: " + dump-table bindings var max-width/esi: int <- copy 0 { # indent stack diff --git a/apps/tile/main.mu b/apps/tile/main.mu index 6b18e82e..457c9816 100644 --- a/apps/tile/main.mu +++ b/apps/tile/main.mu @@ -71,11 +71,14 @@ fn test { initialize-environment-with-fake-screen env, 0x20, 0xa0 process-all env, "3 3 fake-screen =s" process env, 0xc # ctrl-l - process-all env, "s 1 down " + process-all env, "s 1 down 1 right" + process env, 4 # ctrl-d: start defining function + process-all env, "foo" + process env, 0xa # newline: define function + process env, 0x435b1b # right-arrow +#? process env, 5 # ctrl-e: end of line + process env, 0xa # newline: expand render env -#? var fake-screen-ah/eax: (addr handle screen) <- get env, screen -#? var fake-screen/eax: (addr screen) <- lookup *fake-screen-ah -#? render-screen 0, 1, 1, fake-screen } fn process-all env: (addr environment), cmds: (addr array byte) { diff --git a/apps/tile/rpn.mu b/apps/tile/rpn.mu index 2cb61757..6b53f888 100644 --- a/apps/tile/rpn.mu +++ b/apps/tile/rpn.mu @@ -11,8 +11,9 @@ fn evaluate functions: (addr handle function), bindings: (addr table), scratch: break-if-= # update curr-stream emit-word curr, curr-stream -#? print-stream-to-real-screen curr-stream -#? print-string-to-real-screen "\n" + print-string-to-real-screen "eval: " + print-stream-to-real-screen curr-stream + print-string-to-real-screen "\n" $evaluate:process-word: { ### if curr-stream is an operator, perform it ## numbers @@ -648,6 +649,7 @@ fn evaluate functions: (addr handle function), bindings: (addr table), scratch: var val/eax: (addr value) <- lookup *val-ah compare val, 0 break-if-= +#? print-string-to-real-screen "AA\n" push-value-stack out, val #? var tmp-ah/eax: (addr handle screen) <- get val, screen-data #? var tmp/eax: (addr screen) <- lookup *tmp-ah diff --git a/apps/tile/table.mu b/apps/tile/table.mu index 23924d16..5e8bfeb3 100644 --- a/apps/tile/table.mu +++ b/apps/tile/table.mu @@ -6,6 +6,8 @@ fn initialize-table _self: (addr table), n: int { fn shallow-copy-table-values _src: (addr table), dest: (addr table) { var src/eax: (addr table) <- copy _src +#? print-string 0, "before copy: " +#? dump-table src var src-data-ah/eax: (addr handle array bind) <- get src, data var _src-data/eax: (addr array bind) <- lookup *src-data-ah var src-data/esi: (addr array bind) <- copy _src-data @@ -24,7 +26,69 @@ fn shallow-copy-table-values _src: (addr table), dest: (addr table) { break-if-= var val-ah/eax: (addr handle value) <- get src-bind, value var val/eax: (addr value) <- lookup *val-ah +#? { +#? print-string-to-real-screen "before\n" +#? var val2/ecx: (addr value) <- copy val +#? var foo5/eax: (addr int) <- get val2, type +#? print-int32-decimal-to-real-screen *foo5 +#? print-string-to-real-screen ": " +#? var foo6/eax: (addr int) <- get val2, int-data +#? print-int32-decimal-to-real-screen *foo6 +#? var foo7/eax: (addr handle array byte) <- get val2, text-data +#? var foo8/eax: (addr array byte) <- lookup *foo7 +#? var foo9/eax: int <- copy foo8 +#? print-int32-decimal-to-real-screen foo9 +#? var foo10/eax: (addr handle array value) <- get val2, array-data +#? var foo11/eax: (addr array value) <- lookup *foo10 +#? var foo12/eax: int <- copy foo11 +#? print-int32-decimal-to-real-screen foo12 +#? var foo13/eax: (addr handle buffered-file) <- get val2, file-data +#? var foo14/eax: (addr buffered-file) <- lookup *foo13 +#? var foo15/eax: int <- copy foo14 +#? print-int32-decimal-to-real-screen foo15 +#? var foo16/eax: (addr handle screen) <- get val2, screen-data +#? var foo17/eax: (addr screen) <- lookup *foo16 +#? var foo18/eax: int <- copy foo17 +#? print-int32-decimal-to-real-screen foo18 +#? print-string-to-real-screen "\n" +#? } bind-in-table dest, key-ah, val + var foo: (handle value) + var foo2/ecx: (addr handle value) <- address foo + var foo3/eax: (addr array byte) <- lookup *key-ah + print-string-to-real-screen foo3 + print-string-to-real-screen " -> " + lookup-binding dest, foo3, foo2 + var _foo4/eax: (addr value) <- lookup *foo2 + var foo4/ecx: (addr value) <- copy _foo4 + var foo5/eax: (addr int) <- get foo4, type + print-int32-hex-to-real-screen *foo5 + print-string-to-real-screen ": " + var foo6/eax: (addr int) <- get foo4, int-data + print-int32-hex-to-real-screen *foo6 + print-string-to-real-screen " " + var foo7/eax: (addr handle array byte) <- get foo4, text-data + var foo8/eax: (addr array byte) <- lookup *foo7 + var foo9/eax: int <- copy foo8 + print-int32-hex-to-real-screen foo9 + print-string-to-real-screen " " + var foo10/eax: (addr handle array value) <- get foo4, array-data + var foo11/eax: (addr array value) <- lookup *foo10 + var foo12/eax: int <- copy foo11 + print-int32-hex-to-real-screen foo12 + print-string-to-real-screen " " + var foo10/eax: (addr handle array value) <- get foo4, array-data + var foo13/eax: (addr handle buffered-file) <- get foo4, file-data + var foo14/eax: (addr buffered-file) <- lookup *foo13 + var foo15/eax: int <- copy foo14 + print-int32-hex-to-real-screen foo15 + print-string-to-real-screen " " + var foo10/eax: (addr handle array value) <- get foo4, array-data + var foo16/eax: (addr handle screen) <- get foo4, screen-data + var foo17/eax: (addr screen) <- lookup *foo16 + var foo18/eax: int <- copy foo17 + print-int32-hex-to-real-screen foo18 + print-string-to-real-screen "\n" } i <- increment loop @@ -116,3 +180,32 @@ fn lookup-binding _self: (addr table), key: (addr array byte), out: (addr handle loop } } + +fn dump-table _self: (addr table) { + var self/esi: (addr table) <- copy _self + var data-ah/esi: (addr handle array bind) <- get self, data + var _data/eax: (addr array bind) <- lookup *data-ah + var data/esi: (addr array bind) <- copy _data + var len/edx: int <- length data + var i/ebx: int <- copy 0 + { + compare i, len + break-if->= + var offset/edx: (offset bind) <- compute-offset data, i + var target-bind/esi: (addr bind) <- index data, offset + var key-ah/edx: (addr handle array byte) <- get target-bind, key + var key/eax: (addr array byte) <- lookup *key-ah + compare key, 0 + break-if-= + print-string 0, key + print-string 0, ": " + var val-ah/eax: (addr handle value) <- get target-bind, value + var val/eax: (addr value) <- lookup *val-ah + var type/eax: (addr int) <- get val, type + print-int32-hex 0, *type + print-string 0, "\n" + i <- increment + loop + } + print-string 0, "\n" +} diff --git a/apps/tile/value.mu b/apps/tile/value.mu index 9e8c0050..cc046a04 100644 --- a/apps/tile/value.mu +++ b/apps/tile/value.mu @@ -5,6 +5,9 @@ fn render-value-at screen: (addr screen), row: int, col: int, _val: (addr value) move-cursor screen, row, col var val/esi: (addr value) <- copy _val var val-type/ecx: (addr int) <- get val, type +#? print-string-to-real-screen "value type: " +#? print-int32-decimal-to-real-screen *val-type +#? print-string-to-real-screen "\n" # per-type rendering logic goes here compare *val-type, 1 # string { @@ -54,7 +57,7 @@ fn render-value-at screen: (addr screen), row: int, col: int, _val: (addr value) print-string screen, " FILE " return } - compare *val-type, 4 # file + compare *val-type, 4 # screen { break-if-!= var val-ah/eax: (addr handle screen) <- get val, screen-data -- cgit 1.4.1-2-gfad0