about summary refs log tree commit diff stats
path: root/073list.mu
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-11-29 01:00:30 -0800
committerKartik K. Agaram <vc@akkartik.com>2015-11-29 01:00:30 -0800
commitafb467ea0270c59f9fdcad9fe5303d0ed526177c (patch)
treea8254143010d612908b9b4cc534bf4ab1da199a7 /073list.mu
parentc9b98c21ffea7a2e48e10e01b80dabad42641e57 (diff)
downloadmu-afb467ea0270c59f9fdcad9fe5303d0ed526177c.tar.gz
2606 - handle cycles inside stash
The idea is that to-text-line should truncate blindly past some
threshold, even if to-text isn't smart enough to avoid infinite loops.

Maybe I should define a 'truncating buffer' which stops once it fills
up. That would be an easy way to eliminate all infinite loops in
to-text-line.
Diffstat (limited to '073list.mu')
-rw-r--r--073list.mu40
1 files changed, 39 insertions, 1 deletions
diff --git a/073list.mu b/073list.mu
index 7b7d9e18..7e068b60 100644
--- a/073list.mu
+++ b/073list.mu
@@ -61,6 +61,16 @@ recipe to-text in:address:list:_elem -> result:address:array:character [
   result <- buffer-to-array buf
 ]
 
+# variant of 'to-text' which stops printing after a few elements (and so is robust to cycles)
+recipe to-text-line in:address:list:_elem -> result:address:array:character [
+  local-scope
+#?   $print [to text line: list], 10/newline
+  load-ingredients
+  buf:address:buffer <- new-buffer 80
+  buf <- to-buffer in, buf, 6  # max elements to display
+  result <- buffer-to-array buf
+]
+
 recipe to-buffer in:address:list:_elem, buf:address:buffer -> buf:address:buffer [
   local-scope
 #?   $print [to buffer: list], 10/newline
@@ -85,7 +95,23 @@ recipe to-buffer in:address:list:_elem, buf:address:buffer -> buf:address:buffer
   n:number <- length *s
   buf <- append buf, s
   # and recurse
-  buf <- to-buffer next, buf
+  remaining:number, optional-ingredient-found?:boolean <- next-ingredient
+  {
+    break-if optional-ingredient-found?
+    # unlimited recursion
+    buf <- to-buffer next, buf
+    reply
+  }
+  {
+    break-unless remaining
+    # limited recursion
+    remaining <- subtract remaining, 1
+    buf <- to-buffer next, buf, remaining
+    reply
+  }
+  # past recursion depth; insert ellipses and stop
+  s:address:array:character <- new [...]
+  append buf, s
 ]
 
 scenario stash-on-list-converts-to-text [
@@ -99,3 +125,15 @@ scenario stash-on-list-converts-to-text [
     app: foo foo 6 -> 5 -> 4
   ]
 ]
+
+scenario stash-handles-list-with-cycle [
+  run [
+    x:address:list:number <- push 4, 0
+    y:address:address:list:number <- get-address *x, next:offset
+    *y <- copy x
+    stash [foo foo], x
+  ]
+  trace-should-contain [
+    app: foo foo 4 -> 4 -> 4 -> 4 -> 4 -> 4 -> 4 -> ...
+  ]
+]