about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-06-09 21:38:30 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-06-09 21:38:30 -0700
commiteb8260b2275f3631f5ac818e6728917555a78272 (patch)
tree59045e03b83b8ec74d1919ef7622563b2aa64cdd
parenta2d4e415836867967eb2b179eb825149d13aa245 (diff)
downloadmu-eb8260b2275f3631f5ac818e6728917555a78272.tar.gz
.
-rw-r--r--shell/global.mu60
-rw-r--r--shell/sandbox.mu19
2 files changed, 32 insertions, 47 deletions
diff --git a/shell/global.mu b/shell/global.mu
index 8506f4f6..f5f27ae4 100644
--- a/shell/global.mu
+++ b/shell/global.mu
@@ -516,54 +516,32 @@ fn mutate-binding-in-globals name: (addr stream byte), val: (addr handle cell),
   error-stream trace, stream
 }
 
-# Accepts an input s-expression, naively checks if it is a definition, and if
-# so saves the gap-buffer to the appropriate global.
-# Return true if stashed.
-fn maybe-stash-gap-buffer-to-global _globals: (addr global-table), _expr-ah: (addr handle cell), gap: (addr handle gap-buffer) -> _/eax: boolean {
-  # if 'expr' is not a pair, return
-  var expr-ah/eax: (addr handle cell) <- copy _expr-ah
-  var _expr/eax: (addr cell) <- lookup *expr-ah
-  var expr/esi: (addr cell) <- copy _expr
-  var expr-type/eax: (addr int) <- get expr, type
-  compare *expr-type, 0/pair
-  {
-    break-if-=
-    return 0/false
-  }
-  # if expr is not a definition, return
-  {
-    var is-definition?/eax: boolean <- is-definition? expr
-    compare is-definition?, 0/false
-    break-if-!=
-    return 0/false
-  }
-  # locate the global for definition->right->left
-  var right-ah/eax: (addr handle cell) <- get expr, right
-  var right/eax: (addr cell) <- lookup *right-ah
-  var defined-symbol-ah/eax: (addr handle cell) <- get right, left
-  var defined-symbol/eax: (addr cell) <- lookup *defined-symbol-ah
-  var defined-symbol-name-ah/eax: (addr handle stream byte) <- get defined-symbol, text-data
-  var defined-symbol-name/eax: (addr stream byte) <- lookup *defined-symbol-name-ah
-  var index/ecx: int <- find-symbol-in-globals _globals, defined-symbol-name
-  {
-    compare index, -1/not-found
-    break-if-!=
-    return 0/false
-  }
-  # stash 'gap' to it
+fn stash-gap-buffer-to-globals _globals: (addr global-table), definitions: (addr stream int), gap: (addr handle gap-buffer) {
   var globals/eax: (addr global-table) <- copy _globals
   compare globals, 0
   {
     break-if-!=
-    abort "stash to globals"
+    return
   }
   var global-data-ah/eax: (addr handle array global) <- get globals, data
   var global-data/eax: (addr array global) <- lookup *global-data-ah
-  var offset/ebx: (offset global) <- compute-offset global-data, index
-  var dest-global/eax: (addr global) <- index global-data, offset
-  var dest-ah/eax: (addr handle gap-buffer) <- get dest-global, input
-  copy-object gap, dest-ah
-  return 1/true
+  rewind-stream definitions
+  {
+    {
+      var done?/eax: boolean <- stream-empty? definitions
+      compare done?, 0/false
+    }
+    break-if-!=
+    var index: int
+    var index-addr/ecx: (addr int) <- address index
+    read-from-stream definitions, index-addr
+    var index/ecx: int <- copy *index-addr
+    var offset/ebx: (offset global) <- compute-offset global-data, index
+    var dest-global/eax: (addr global) <- index global-data, offset
+    var dest-ah/eax: (addr handle gap-buffer) <- get dest-global, input
+    copy-object gap, dest-ah
+    loop
+  }
 }
 
 fn is-definition? _expr: (addr cell) -> _/eax: boolean {
diff --git a/shell/sandbox.mu b/shell/sandbox.mu
index 5cc75a0f..09f6f4d1 100644
--- a/shell/sandbox.mu
+++ b/shell/sandbox.mu
@@ -659,7 +659,9 @@ fn run _in-ah: (addr handle gap-buffer), out: (addr stream byte), globals: (addr
 #?   set-cursor-position 0/screen, 0 0
 #?   turn-on-debug-print
   debug-print "^", 4/fg, 0/bg
-  evaluate read-result-ah, eval-result-ah, *nil-ah, globals, trace, screen-cell, keyboard-cell, 0/definitions-created, 1/call-number
+  var definitions-created-storage: (stream int 0x10)
+  var definitions-created/ecx: (addr stream int) <- address definitions-created-storage
+  evaluate read-result-ah, eval-result-ah, *nil-ah, globals, trace, screen-cell, keyboard-cell, definitions-created, 1/call-number
   debug-print "$", 4/fg, 0/bg
   var error?/eax: boolean <- has-errors? trace
   {
@@ -671,14 +673,19 @@ fn run _in-ah: (addr handle gap-buffer), out: (addr stream byte), globals: (addr
   print-cell eval-result-ah, out, trace
   # refresh various rendering caches
   mark-lines-dirty trace
-  # if there was no error and the read-result starts with "set" or "def", save
-  # the gap buffer in the modified global, then create a new one for the next
-  # command.
-  var stashed?/eax: boolean <- maybe-stash-gap-buffer-to-global globals, read-result-ah, _in-ah
+  # If any definitions were created or modified in the process, link this gap
+  # buffer to them.
+  # TODO: detect and create UI for conflicts.
+  stash-gap-buffer-to-globals globals, definitions-created, _in-ah
   # if necessary, initialize a new gap-buffer in 'gap'
   {
-    compare stashed?, 0/false
+    compare globals, 0
     break-if-=
+    rewind-stream definitions-created
+    var no-definitions?/eax: boolean <- stream-empty? definitions-created
+    compare no-definitions?, 0/false
+    break-if-!=
+    # some definitions were created; clear the gap buffer
     var in-ah/edi: (addr handle gap-buffer) <- copy _in-ah
     var in/eax: (addr gap-buffer) <- lookup *in-ah
     var capacity/ecx: int <- gap-buffer-capacity in