about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-11-09 21:16:09 -0800
committerKartik Agaram <vc@akkartik.com>2020-11-09 21:16:09 -0800
commitc01289dddea2398fe7f4335f5d0babc4a9e789c5 (patch)
tree26aa680c9633a19f1692140f00750aba615b7db5
parent148f2c9b65bcb53379d1c6bf7ec1204735bb2393 (diff)
downloadmu-c01289dddea2398fe7f4335f5d0babc4a9e789c5.tar.gz
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.
-rw-r--r--apps/tile/environment.mu35
-rw-r--r--apps/tile/main.mu11
-rw-r--r--apps/tile/rpn.mu6
-rw-r--r--apps/tile/table.mu93
-rw-r--r--apps/tile/value.mu5
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