about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--050scenario.cc9
-rw-r--r--053rewrite_stash.cc2
-rw-r--r--070text.mu10
-rw-r--r--073list.mu40
4 files changed, 52 insertions, 9 deletions
diff --git a/050scenario.cc b/050scenario.cc
index 21afe341..10c65e21 100644
--- a/050scenario.cc
+++ b/050scenario.cc
@@ -438,25 +438,22 @@ case TRACE_SHOULD_CONTAIN: {
 :(code)
 // simplified version of check_trace_contents() that emits errors rather
 // than just printing to stderr
-bool check_trace(const string& expected) {
+void check_trace(const string& expected) {
   Trace_stream->newline();
   vector<trace_line> expected_lines = parse_trace(expected);
-  if (expected_lines.empty()) return true;
+  if (expected_lines.empty()) return;
   long long int curr_expected_line = 0;
   for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
     if (expected_lines.at(curr_expected_line).label != p->label) continue;
     if (expected_lines.at(curr_expected_line).contents != trim(p->contents)) continue;
     // match
     ++curr_expected_line;
-    if (curr_expected_line == SIZE(expected_lines)) {
-      return true;
-    }
+    if (curr_expected_line == SIZE(expected_lines)) return;
   }
 
   raise_error << "missing [" << expected_lines.at(curr_expected_line).contents << "] "
               << "in trace with label " << expected_lines.at(curr_expected_line).label << '\n' << end();
   Passed = false;
-  return false;
 }
 
 vector<trace_line> parse_trace(const string& expected) {
diff --git a/053rewrite_stash.cc b/053rewrite_stash.cc
index df64baaf..b6602041 100644
--- a/053rewrite_stash.cc
+++ b/053rewrite_stash.cc
@@ -35,7 +35,7 @@ void rewrite_stashes_to_text_named(recipe& caller) {
         if (is_literal(inst.ingredients.at(j))) continue;
         if (is_mu_string(inst.ingredients.at(j))) continue;
         instruction def;
-        def.name = "to-text";
+        def.name = "to-text-line";
         def.ingredients.push_back(inst.ingredients.at(j));
         ostringstream ingredient_name;
         ingredient_name << "stash_" << stash_instruction_idx << '_' << j << ":address:array:character";
diff --git a/070text.mu b/070text.mu
index eb3875d0..5de21e41 100644
--- a/070text.mu
+++ b/070text.mu
@@ -1,6 +1,14 @@
 # Some useful helpers for dealing with text (arrays of characters)
 
-# to-text gets called implicitly in various places
+# to-text-line gets called implicitly in various places
+# define it to be identical to 'to-text' by default
+recipe to-text-line x:_elem -> y:address:array:character [
+  local-scope
+  load-ingredients
+  y <- to-text x
+]
+
+# to-text on text is just the identity function
 recipe to-text x:address:array:character -> y:address:array:character [
   local-scope
   load-ingredients
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 -> ...
+  ]
+]