about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-09-16 16:04:11 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-09-16 16:04:11 -0700
commitced133e40290c30809e6d632cdf1e6f749ea9dd5 (patch)
tree8e217620ee5016db6d1be429d2724bd9adfd0881
parentaa2fd725c0e5129bd4a750261f97ababa8af9a12 (diff)
downloadmu-ced133e40290c30809e6d632cdf1e6f749ea9dd5.tar.gz
3371
-rw-r--r--html/003trace.cc.html9
-rw-r--r--html/011load.cc.html8
-rw-r--r--html/014literal_string.cc.html4
-rw-r--r--html/020run.cc.html4
-rw-r--r--html/026call.cc.html5
-rw-r--r--html/032array.cc.html2
-rw-r--r--html/050scenario.cc.html2
-rw-r--r--html/059to_text.mu.html17
-rw-r--r--html/061text.mu.html99
-rw-r--r--html/062convert_ingredients_to_text.cc.html (renamed from html/062rewrite_stash.cc.html)67
-rw-r--r--html/101run_sandboxed.cc.html33
-rw-r--r--html/edit/010-sandbox-trace.mu.html12
12 files changed, 173 insertions, 89 deletions
diff --git a/html/003trace.cc.html b/html/003trace.cc.html
index 0e35ce97..7a7cb31f 100644
--- a/html/003trace.cc.html
+++ b/html/003trace.cc.html
@@ -166,10 +166,11 @@ Hide_errors = <span class="Constant">false</span><span class="Delimiter">;</span
 <span class="Normal">void</span> trace_stream::newline<span class="Delimiter">()</span> <span class="Delimiter">{</span>
   <span class="Normal">if</span> <span class="Delimiter">(</span>!curr_stream<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
   string curr_contents = curr_stream<span class="Delimiter">-&gt;</span>str<span class="Delimiter">();</span>
-  <span class="Normal">if</span> <span class="Delimiter">(</span>curr_contents<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
-  past_lines<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>trace_line<span class="Delimiter">(</span>curr_depth<span class="Delimiter">,</span> trim<span class="Delimiter">(</span>curr_label<span class="Delimiter">),</span> curr_contents<span class="Delimiter">));</span>  <span class="Comment">// preserve indent in contents</span>
-  <span class="Normal">if</span> <span class="Delimiter">(</span>!Hide_errors &amp;&amp; curr_label == <span class="Constant">&quot;error&quot;</span><span class="Delimiter">)</span>
-    cerr &lt;&lt; curr_label &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; curr_contents &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>!curr_contents<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span>
+    past_lines<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>trace_line<span class="Delimiter">(</span>curr_depth<span class="Delimiter">,</span> trim<span class="Delimiter">(</span>curr_label<span class="Delimiter">),</span> curr_contents<span class="Delimiter">));</span>  <span class="Comment">// preserve indent in contents</span>
+    <span class="Normal">if</span> <span class="Delimiter">(</span>!Hide_errors &amp;&amp; curr_label == <span class="Constant">&quot;error&quot;</span><span class="Delimiter">)</span>
+      cerr &lt;&lt; curr_label &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; curr_contents &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
   <span class="Normal">delete</span> curr_stream<span class="Delimiter">;</span>
   curr_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span>
   curr_label<span class="Delimiter">.</span>clear<span class="Delimiter">();</span>
diff --git a/html/011load.cc.html b/html/011load.cc.html
index 0a232b80..bf642aaf 100644
--- a/html/011load.cc.html
+++ b/html/011load.cc.html
@@ -263,6 +263,14 @@ Disable_redefine_checks = <span class="Constant">false</span><span class="Delimi
   exit<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
 <span class="Delimiter">}</span>
 
+<span class="Delimiter">:(scenario recipe_instead_of_def)</span>
+recipe main [
+  <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">23</span>
+]
+<span class="traceContains">+parse: instruction: copy</span>
+<span class="traceContains">+parse:   ingredient: {23: &quot;literal&quot;}</span>
+<span class="traceContains">+parse:   product: {1: &quot;number&quot;}</span>
+
 <span class="Delimiter">:(scenario parse_comment_outside_recipe)</span>
 <span class="Comment"># this comment will be dropped by the tangler, so we need a dummy recipe to stop that</span>
 def f1 [
diff --git a/html/014literal_string.cc.html b/html/014literal_string.cc.html
index 52a1b264..bb6eba51 100644
--- a/html/014literal_string.cc.html
+++ b/html/014literal_string.cc.html
@@ -254,8 +254,8 @@ def main [
 
 <span class="Delimiter">:(scenario multiple_unfinished_recipes)</span>
 <span class="Special">% Hide_errors = true;</span>
-recipe f1 [
-recipe f2 [
+def f1 [
+def f2 [
 <span class="traceContains">+error: unbalanced '['</span>
 </pre>
 </body>
diff --git a/html/020run.cc.html b/html/020run.cc.html
index a4ddb087..08909f94 100644
--- a/html/020run.cc.html
+++ b/html/020run.cc.html
@@ -160,6 +160,10 @@ map&lt;string<span class="Delimiter">,</span> <span class="Normal">int</span>&gt
   <span class="Identifier">return</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>running_recipe<span class="Delimiter">).</span>name<span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
+<span class="Normal">const</span> recipe&amp; current_recipe<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  <span class="Identifier">return</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>running_recipe<span class="Delimiter">);</span>
+<span class="Delimiter">}</span>
+
 <span class="Normal">const</span> instruction&amp; current_instruction<span class="Delimiter">()</span> <span class="Delimiter">{</span>
   <span class="Identifier">return</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-&gt;</span>running_recipe<span class="Delimiter">).</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>running_step_index<span class="Delimiter">);</span>
 <span class="Delimiter">}</span>
diff --git a/html/026call.cc.html b/html/026call.cc.html
index ca151665..687ffbd3 100644
--- a/html/026call.cc.html
+++ b/html/026call.cc.html
@@ -119,6 +119,11 @@ call&amp; current_call<span class="Delimiter">()</span> <span class="Delimiter">
   assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>empty<span class="Delimiter">());</span>
   <span class="Identifier">return</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> current_call<span class="Delimiter">().</span>running_recipe<span class="Delimiter">).</span>name<span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
+<span class="Delimiter">:(replace{} &quot;const recipe&amp; current_recipe()&quot;)</span>
+<span class="Normal">const</span> recipe&amp; current_recipe<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>empty<span class="Delimiter">());</span>
+  <span class="Identifier">return</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> current_call<span class="Delimiter">().</span>running_recipe<span class="Delimiter">);</span>
+<span class="Delimiter">}</span>
 <span class="Delimiter">:(replace{} &quot;const instruction&amp; current_instruction()&quot;)</span>
 <span class="Normal">const</span> instruction&amp; current_instruction<span class="Delimiter">()</span> <span class="Delimiter">{</span>
   assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>empty<span class="Delimiter">());</span>
diff --git a/html/032array.cc.html b/html/032array.cc.html
index d78f29ab..1a733068 100644
--- a/html/032array.cc.html
+++ b/html/032array.cc.html
@@ -209,7 +209,7 @@ def main [
 container card [
   <span class="Normal">rank</span>:number<span class="Special"> &lt;- </span>next-ingredient
 ]
-recipe foo [
+def foo [
   <span class="Constant">1</span>:card<span class="Special"> &lt;- </span>merge <span class="Constant">3</span>
   <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get <span class="Constant">1</span>:card rank:offset
 ]
diff --git a/html/050scenario.cc.html b/html/050scenario.cc.html
index 7554e95a..9dcedc44 100644
--- a/html/050scenario.cc.html
+++ b/html/050scenario.cc.html
@@ -447,7 +447,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span
   trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;checking string length at &quot;</span> &lt;&lt; address &lt;&lt; end<span class="Delimiter">();</span>
   <span class="Normal">if</span> <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">)</span> != SIZE<span class="Delimiter">(</span>literal<span class="Delimiter">))</span> <span class="Delimiter">{</span>
     <span class="Normal">if</span> <span class="Delimiter">(</span>Current_scenario &amp;&amp; !Scenario_testing_scenario<span class="Delimiter">)</span>
-      raise &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: expected location '&quot;</span> &lt;&lt; address &lt;&lt; <span class="Constant">&quot;' to contain length &quot;</span> &lt;&lt; SIZE<span class="Delimiter">(</span>literal<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; of string [&quot;</span> &lt;&lt; literal &lt;&lt; <span class="Constant">&quot;] but saw &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">))</span> &lt;&lt; <span class="Constant">&quot; (&quot;</span> &lt;&lt; read_mu_string<span class="Delimiter">(</span>address<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;)</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
+      raise &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: expected location '&quot;</span> &lt;&lt; address &lt;&lt; <span class="Constant">&quot;' to contain length &quot;</span> &lt;&lt; SIZE<span class="Delimiter">(</span>literal<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; of string [&quot;</span> &lt;&lt; literal &lt;&lt; <span class="Constant">&quot;] but saw &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">))</span> &lt;&lt; <span class="Constant">&quot; (&quot;</span> &lt;&lt; read_mu_string<span class="Delimiter">(</span>address-<span class="Comment">/*</span><span class="Comment">fake refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;)</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
     <span class="Normal">else</span>
       raise &lt;&lt; <span class="Constant">&quot;expected location '&quot;</span> &lt;&lt; address &lt;&lt; <span class="Constant">&quot;' to contain length &quot;</span> &lt;&lt; SIZE<span class="Delimiter">(</span>literal<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; of string [&quot;</span> &lt;&lt; literal &lt;&lt; <span class="Constant">&quot;] but saw &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span>
     <span class="Normal">if</span> <span class="Delimiter">(</span>!Scenario_testing_scenario<span class="Delimiter">)</span> Passed = <span class="Constant">false</span><span class="Delimiter">;</span>
diff --git a/html/059to_text.mu.html b/html/059to_text.mu.html
index deaacdf7..b050f5e9 100644
--- a/html/059to_text.mu.html
+++ b/html/059to_text.mu.html
@@ -60,6 +60,23 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   x:text<span class="Special"> &lt;- </span>array-to-text-line n
   <span class="Comment"># just ensure there were no errors</span>
 ]
+
+<span class="Comment"># finally, a specialization for single characters</span>
+<span class="muRecipe">def</span> to-text c:character<span class="muRecipe"> -&gt; </span>y:text [
+  <span class="Constant">local-scope</span>
+  <span class="Constant">load-ingredients</span>
+  y<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, <span class="Constant">1/capacity</span>
+  *y<span class="Special"> &lt;- </span>put-index *y, <span class="Constant">0</span>, c
+]
+
+<span class="muScenario">scenario</span> character-to-text [
+  <span class="Constant">1</span>:character<span class="Special"> &lt;- </span>copy <span class="Constant">111/o</span>
+  <span class="Constant">2</span>:text<span class="Special"> &lt;- </span>to-text <span class="Constant">1</span>:character
+  <span class="Constant">3</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">2</span>:text
+  memory-should-contain [
+    <span class="Constant">3</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[o]</span>
+  ]
+]
 </pre>
 </body>
 </html>
diff --git a/html/061text.mu.html b/html/061text.mu.html
index e1a99fc8..0a0e41bf 100644
--- a/html/061text.mu.html
+++ b/html/061text.mu.html
@@ -151,15 +151,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <span class="muControl">return</span> result
 ]
 
-<span class="muRecipe">def</span> grow-buffer in:address:buffer<span class="muRecipe"> -&gt; </span>in:address:buffer [
+<span class="muRecipe">def</span> grow-buffer buf:address:buffer<span class="muRecipe"> -&gt; </span>buf:address:buffer [
   <span class="Constant">local-scope</span>
   <span class="Constant">load-ingredients</span>
   <span class="Comment"># double buffer size</span>
-  olddata:text<span class="Special"> &lt;- </span>get *in, <span class="Constant">data:offset</span>
+  olddata:text<span class="Special"> &lt;- </span>get *buf, <span class="Constant">data:offset</span>
   oldlen:number<span class="Special"> &lt;- </span>length *olddata
   newlen:number<span class="Special"> &lt;- </span>multiply oldlen, <span class="Constant">2</span>
   newdata:text<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, newlen
-  *in<span class="Special"> &lt;- </span>put *in, <span class="Constant">data:offset</span>, newdata
+  *buf<span class="Special"> &lt;- </span>put *buf, <span class="Constant">data:offset</span>, newdata
   <span class="Comment"># copy old contents</span>
   i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
   <span class="Delimiter">{</span>
@@ -198,10 +198,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <span class="Delimiter">}</span>
 ]
 
-<span class="muRecipe">def</span> append in:address:buffer, c:character<span class="muRecipe"> -&gt; </span>in:address:buffer [
+<span class="muRecipe">def</span> append buf:address:buffer, c:character<span class="muRecipe"> -&gt; </span>buf:address:buffer [
   <span class="Constant">local-scope</span>
   <span class="Constant">load-ingredients</span>
-  len:number<span class="Special"> &lt;- </span>get *in, <span class="Constant">length:offset</span>
+  len:number<span class="Special"> &lt;- </span>get *buf, <span class="Constant">length:offset</span>
   <span class="Delimiter">{</span>
     <span class="Comment"># backspace? just drop last character if it exists and return</span>
     backspace?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">8/backspace</span>
@@ -209,19 +209,34 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     empty?:boolean<span class="Special"> &lt;- </span>lesser-or-equal len, <span class="Constant">0</span>
     <span class="muControl">return-if</span> empty?
     len<span class="Special"> &lt;- </span>subtract len, <span class="Constant">1</span>
-    *in<span class="Special"> &lt;- </span>put *in, <span class="Constant">length:offset</span>, len
+    *buf<span class="Special"> &lt;- </span>put *buf, <span class="Constant">length:offset</span>, len
     <span class="muControl">return</span>
   <span class="Delimiter">}</span>
   <span class="Delimiter">{</span>
     <span class="Comment"># grow buffer if necessary</span>
-    full?:boolean<span class="Special"> &lt;- </span>buffer-full? in
+    full?:boolean<span class="Special"> &lt;- </span>buffer-full? buf
     <span class="muControl">break-unless</span> full?
-    in<span class="Special"> &lt;- </span>grow-buffer in
+    buf<span class="Special"> &lt;- </span>grow-buffer buf
   <span class="Delimiter">}</span>
-  s:text<span class="Special"> &lt;- </span>get *in, <span class="Constant">data:offset</span>
+  s:text<span class="Special"> &lt;- </span>get *buf, <span class="Constant">data:offset</span>
   *s<span class="Special"> &lt;- </span>put-index *s, len, c
   len<span class="Special"> &lt;- </span>add len, <span class="Constant">1</span>
-  *in<span class="Special"> &lt;- </span>put *in, <span class="Constant">length:offset</span>, len
+  *buf<span class="Special"> &lt;- </span>put *buf, <span class="Constant">length:offset</span>, len
+]
+
+<span class="muRecipe">def</span> append buf:address:buffer, t:text<span class="muRecipe"> -&gt; </span>buf:address:buffer [
+  <span class="Constant">local-scope</span>
+  <span class="Constant">load-ingredients</span>
+  len:number<span class="Special"> &lt;- </span>length *t
+  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
+    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, len
+    <span class="muControl">break-if</span> done?
+    c:character<span class="Special"> &lt;- </span>index *t, i
+    buf<span class="Special"> &lt;- </span>append buf, c
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
 ]
 
 <span class="muScenario">scenario</span> buffer-append-works [
@@ -318,44 +333,32 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <span class="Delimiter">}</span>
 ]
 
-<span class="muRecipe">def</span> append a:text, b:text<span class="muRecipe"> -&gt; </span>result:text [
+<span class="Comment"># Append any number of texts together.</span>
+<span class="Comment"># A later layer also translates calls to this to implicitly call to-text, so</span>
+<span class="Comment"># append to string becomes effectively dynamically typed.</span>
+<span class="Comment">#</span>
+<span class="Comment"># Beware though: this hack restricts how much 'append' can be overridden. Any</span>
+<span class="Comment"># new variants that match:</span>
+<span class="Comment">#   append _:text, ___</span>
+<span class="Comment"># will never ever get used.</span>
+<span class="muRecipe">def</span> append first:text<span class="muRecipe"> -&gt; </span>result:text [
   <span class="Constant">local-scope</span>
   <span class="Constant">load-ingredients</span>
-  <span class="Comment"># handle null addresses</span>
-  <span class="muControl">return-unless</span> a, b
-  <span class="muControl">return-unless</span> b, a
-  <span class="Comment"># result = new character[a.length + b.length]</span>
-  a-len:number<span class="Special"> &lt;- </span>length *a
-  b-len:number<span class="Special"> &lt;- </span>length *b
-  result-len:number<span class="Special"> &lt;- </span>add a-len, b-len
-  result<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, result-len
-  <span class="Comment"># copy a into result</span>
-  result-idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  buf:address:buffer<span class="Special"> &lt;- </span>new-buffer <span class="Constant">30</span>
+  <span class="Comment"># append first ingredient</span>
   <span class="Delimiter">{</span>
-    <span class="Comment"># while i &lt; a.length</span>
-    a-done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, a-len
-    <span class="muControl">break-if</span> a-done?
-    <span class="Comment"># result[result-idx] = a[i]</span>
-    in:character<span class="Special"> &lt;- </span>index *a, i
-    *result<span class="Special"> &lt;- </span>put-index *result, result-idx, in
-    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
-    result-idx<span class="Special"> &lt;- </span>add result-idx, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
+    <span class="muControl">break-unless</span> first
+    buf<span class="Special"> &lt;- </span>append buf, first
   <span class="Delimiter">}</span>
-  <span class="Comment"># copy b into result</span>
-  i<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Comment"># append remaining ingredients</span>
   <span class="Delimiter">{</span>
-    <span class="Comment"># while i &lt; b.length</span>
-    b-done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, b-len
-    <span class="muControl">break-if</span> b-done?
-    <span class="Comment"># result[result-idx] = a[i]</span>
-    in:character<span class="Special"> &lt;- </span>index *b, i
-    *result<span class="Special"> &lt;- </span>put-index *result, result-idx, in
-    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
-    result-idx<span class="Special"> &lt;- </span>add result-idx, <span class="Constant">1</span>
+    arg:text, arg-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+    <span class="muControl">break-unless</span> arg-found?
+    <span class="muControl">loop-unless</span> arg
+    buf<span class="Special"> &lt;- </span>append buf, arg
     <span class="muControl">loop</span>
   <span class="Delimiter">}</span>
+  result<span class="Special"> &lt;- </span>buffer-to-array buf
 ]
 
 <span class="muScenario">scenario</span> text-append-1 [
@@ -397,6 +400,20 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   ]
 ]
 
+<span class="muScenario">scenario</span> text-append-multiary [
+  run [
+    <span class="Constant">local-scope</span>
+    x:text<span class="Special"> &lt;- </span>new <span class="Constant">[hello, ]</span>
+    y:text<span class="Special"> &lt;- </span>new <span class="Constant">[world]</span>
+    z:text<span class="Special"> &lt;- </span>new <span class="Constant">[!]</span>
+    z:text<span class="Special"> &lt;- </span>append x, y, z
+    <span class="Constant">10</span>:array:character/<span class="Special">raw &lt;- </span>copy *z
+  ]
+  memory-should-contain [
+    <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[hello, world!]</span>
+  ]
+]
+
 <span class="muScenario">scenario</span> replace-character-in-text [
   run [
     <span class="Constant">local-scope</span>
diff --git a/html/062rewrite_stash.cc.html b/html/062convert_ingredients_to_text.cc.html
index 8ed4fa38..34ef34f0 100644
--- a/html/062rewrite_stash.cc.html
+++ b/html/062convert_ingredients_to_text.cc.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=UTF-8">
-<title>Mu - 062rewrite_stash.cc</title>
+<title>Mu - 062convert_ingredients_to_text.cc</title>
 <meta name="Generator" content="Vim/7.4">
 <meta name="plugin-version" content="vim7.4_v2">
 <meta name="syntax" content="cpp">
@@ -18,8 +18,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
 .Comment { color: #9090ff; }
 .Delimiter { color: #800080; }
 .Special { color: #c00000; }
-.Identifier { color: #fcb165; }
+.CommentedCode { color: #6c6c6c; }
 .Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; }
+.Identifier { color: #fcb165; }
 -->
 </style>
 
@@ -31,12 +32,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
 </head>
 <body>
 <pre id='vimCodeElement'>
-<span class="Comment">//: when encountering other types, try to convert them to strings using</span>
-<span class="Comment">//: 'to-text'</span>
+<span class="Comment">//: make some functions more friendly by trying to auto-convert their ingredients to text</span>
 
 <span class="Delimiter">:(scenarios transform)</span>
 <span class="Delimiter">:(scenario rewrite_stashes_to_text)</span>
-recipe main [
+def main [
   local-scope
   <span class="Normal">n</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
   stash n
@@ -45,7 +45,7 @@ recipe main [
 <span class="traceContains">+transform: stash {stash_2_0: (&quot;address&quot; &quot;array&quot; &quot;character&quot;)}</span>
 
 <span class="Delimiter">:(scenario rewrite_traces_to_text)</span>
-recipe main [
+def main [
   local-scope
   <span class="Normal">n</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
   trace <span class="Constant">2</span><span class="Delimiter">,</span> [app]<span class="Delimiter">,</span> n
@@ -57,7 +57,7 @@ recipe main [
 <span class="Comment">//: passing addresses around</span>
 
 <span class="Delimiter">:(scenario rewrite_stashes_of_arrays)</span>
-recipe main [
+def main [
   local-scope
   <span class="Normal">n</span>:address:array:number<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">3</span>
   stash *n
@@ -66,7 +66,7 @@ recipe main [
 <span class="traceContains">+transform: stash {stash_2_0: (&quot;address&quot; &quot;array&quot; &quot;character&quot;)}</span>
 
 <span class="Delimiter">:(scenario ignore_stashes_of_static_arrays)</span>
-recipe main [
+def main [
   local-scope
   <span class="Normal">n</span>:array:number:<span class="Constant">3</span><span class="Special"> &lt;- </span>create-array
   stash n
@@ -77,7 +77,7 @@ recipe main [
 container foo [
   <span class="Normal">x</span>:number
 ]
-recipe bar <span class="Delimiter">-&gt;</span> x:foo [
+def bar <span class="Delimiter">-&gt;</span> x:foo [
   local-scope
   load-ingredients
   x<span class="Special"> &lt;- </span>merge <span class="Constant">34</span>
@@ -88,33 +88,51 @@ recipe bar <span class="Delimiter">-&gt;</span> x:foo [
 <span class="Comment">//: misplaced; should be in instruction inserting/deleting transforms, but has</span>
 <span class="Comment">//: prerequisites: deduce_types_from_header and check_or_set_types_by_name</span>
 <span class="Delimiter">:(after &quot;Transform.push_back(deduce_types_from_header)&quot;)</span>
-Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>rewrite_stashes_to_text<span class="Delimiter">);</span>
+Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>convert_ingredients_to_text<span class="Delimiter">);</span>
 
 <span class="Delimiter">:(code)</span>
-<span class="Normal">void</span> rewrite_stashes_to_text<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+<span class="Normal">void</span> convert_ingredients_to_text<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   recipe&amp; caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span>
-  trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- rewrite 'stash' instructions in recipe &quot;</span> &lt;&lt; caller<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span>
+  trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- convert some ingredients to text in recipe &quot;</span> &lt;&lt; caller<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span>
+<span class="CommentedCode">//?   cerr &lt;&lt; &quot;--- convert some ingredients to text in recipe &quot; &lt;&lt; caller.name &lt;&lt; '\n';</span>
   <span class="Comment">// in recipes without named locations, 'stash' is still not extensible</span>
   <span class="Normal">if</span> <span class="Delimiter">(</span>contains_numeric_locations<span class="Delimiter">(</span>caller<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
-  rewrite_stashes_to_text<span class="Delimiter">(</span>caller<span class="Delimiter">);</span>
+  convert_ingredients_to_text<span class="Delimiter">(</span>caller<span class="Delimiter">);</span>
 <span class="Delimiter">}</span>
 
-<span class="Normal">void</span> rewrite_stashes_to_text<span class="Delimiter">(</span>recipe&amp; caller<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+<span class="Normal">void</span> convert_ingredients_to_text<span class="Delimiter">(</span>recipe&amp; caller<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   vector&lt;instruction&gt; new_instructions<span class="Delimiter">;</span>
   <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
     instruction&amp; inst = caller<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span>
+    <span class="Comment">// all these cases are getting hairy. how can we make this extensible?</span>
     <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;stash&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
       <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+        <span class="Normal">if</span> <span class="Delimiter">(</span>is_literal_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
         ostringstream ingredient_name<span class="Delimiter">;</span>
         ingredient_name &lt;&lt; <span class="Constant">&quot;stash_&quot;</span> &lt;&lt; i &lt;&lt; <span class="Constant">'_'</span> &lt;&lt; j &lt;&lt; <span class="Constant">&quot;:address:array:character&quot;</span><span class="Delimiter">;</span>
-        rewrite_stash_to_text<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">),</span> new_instructions<span class="Delimiter">,</span> ingredient_name<span class="Delimiter">.</span>str<span class="Delimiter">());</span>
+        convert_ingredient_to_text<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">),</span> new_instructions<span class="Delimiter">,</span> ingredient_name<span class="Delimiter">.</span>str<span class="Delimiter">());</span>
       <span class="Delimiter">}</span>
     <span class="Delimiter">}</span>
     <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">&quot;trace&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
       <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> j = <span class="Comment">/*</span><span class="Comment">skip</span><span class="Comment">*/</span><span class="Constant">2</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+        <span class="Normal">if</span> <span class="Delimiter">(</span>is_literal_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
         ostringstream ingredient_name<span class="Delimiter">;</span>
         ingredient_name &lt;&lt; <span class="Constant">&quot;trace_&quot;</span> &lt;&lt; i &lt;&lt; <span class="Constant">'_'</span> &lt;&lt; j &lt;&lt; <span class="Constant">&quot;:address:array:character&quot;</span><span class="Delimiter">;</span>
-        rewrite_stash_to_text<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">),</span> new_instructions<span class="Delimiter">,</span> ingredient_name<span class="Delimiter">.</span>str<span class="Delimiter">());</span>
+        convert_ingredient_to_text<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">),</span> new_instructions<span class="Delimiter">,</span> ingredient_name<span class="Delimiter">.</span>str<span class="Delimiter">());</span>
+      <span class="Delimiter">}</span>
+    <span class="Delimiter">}</span>
+    <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>old_name == <span class="Constant">&quot;append&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
+      <span class="Comment">// override only variants that try to append to a string</span>
+      <span class="Comment">// Beware: this hack restricts how much 'append' can be overridden. Any</span>
+      <span class="Comment">// new variants that match:</span>
+      <span class="Comment">//   append _:text, ___</span>
+      <span class="Comment">// will never ever get used.</span>
+      <span class="Normal">if</span> <span class="Delimiter">(</span>is_literal_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> || is_mu_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span>
+        <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+          ostringstream ingredient_name<span class="Delimiter">;</span>
+          ingredient_name &lt;&lt; <span class="Constant">&quot;append_&quot;</span> &lt;&lt; i &lt;&lt; <span class="Constant">'_'</span> &lt;&lt; j &lt;&lt; <span class="Constant">&quot;:address:array:character&quot;</span><span class="Delimiter">;</span>
+          convert_ingredient_to_text<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">),</span> new_instructions<span class="Delimiter">,</span> ingredient_name<span class="Delimiter">.</span>str<span class="Delimiter">());</span>
+        <span class="Delimiter">}</span>
       <span class="Delimiter">}</span>
     <span class="Delimiter">}</span>
     trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; to_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span>
@@ -125,9 +143,8 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa
 
 <span class="Comment">// add an instruction to convert reagent 'r' to text in list 'out', then</span>
 <span class="Comment">// replace r with converted text</span>
-<span class="Normal">void</span> rewrite_stash_to_text<span class="Delimiter">(</span>reagent&amp; r<span class="Delimiter">,</span> vector&lt;instruction&gt;&amp; out<span class="Delimiter">,</span> <span class="Normal">const</span> string&amp; tmp_var<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+<span class="Normal">void</span> convert_ingredient_to_text<span class="Delimiter">(</span>reagent&amp; r<span class="Delimiter">,</span> vector&lt;instruction&gt;&amp; out<span class="Delimiter">,</span> <span class="Normal">const</span> string&amp; tmp_var<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   <span class="Normal">if</span> <span class="Delimiter">(</span>!r<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span>  <span class="Comment">// error; will be handled elsewhere</span>
-  <span class="Normal">if</span> <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
   <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_string<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
   <span class="Comment">// don't try to extend static arrays</span>
   <span class="Normal">if</span> <span class="Delimiter">(</span>is_static_array<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
@@ -161,17 +178,27 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa
   <span class="Identifier">return</span> !x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>atom &amp;&amp; x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">-&gt;</span>atom &amp;&amp; x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">-&gt;</span>name == <span class="Constant">&quot;array&quot;</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
+<span class="Delimiter">:(scenarios run)</span>
+<span class="Delimiter">:(scenario append_other_types_to_text)</span>
+def main [
+  local-scope
+  <span class="Normal">n</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">11</span>
+  <span class="Normal">c</span>:character<span class="Special"> &lt;- </span>copy <span class="Constant">111</span>/o
+  <span class="Normal">a</span>:text<span class="Special"> &lt;- </span>append [abc]<span class="Delimiter">,</span> <span class="Constant">10</span><span class="Delimiter">,</span> n<span class="Delimiter">,</span> c
+  <span class="Normal">expected</span>:text<span class="Special"> &lt;- </span><span class="Normal">new</span> [abc1011o]
+  <span class="Constant">10</span>:boolean/<span class="Special">raw &lt;- </span>equal a<span class="Delimiter">,</span> expected
+]
+
 <span class="Comment">//: Make sure that the new system is strictly better than just the 'stash'</span>
 <span class="Comment">//: primitive by itself.</span>
 
-<span class="Delimiter">:(scenarios run)</span>
 <span class="Delimiter">:(scenario rewrite_stash_continues_to_fall_back_to_default_implementation)</span>
 <span class="Comment"># type without a to-text implementation</span>
 container foo [
   <span class="Normal">x</span>:number
   <span class="Normal">y</span>:number
 ]
-recipe main [
+def main [
   local-scope
   <span class="Normal">x</span>:foo<span class="Special"> &lt;- </span>merge <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">35</span>
   stash x
diff --git a/html/101run_sandboxed.cc.html b/html/101run_sandboxed.cc.html
index d43b68af..bf39a10e 100644
--- a/html/101run_sandboxed.cc.html
+++ b/html/101run_sandboxed.cc.html
@@ -21,6 +21,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
 .Special { color: #c00000; }
 .Identifier { color: #fcb165; }
 .Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; }
+.CommentedCode { color: #6c6c6c; }
 -->
 </style>
 
@@ -102,12 +103,21 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span
   <span class="Delimiter">}</span>
 <span class="Delimiter">}</span>
 
+<span class="Comment">//: To show results in the sandbox Mu uses a hack: it saves the products</span>
+<span class="Comment">//: returned by each instruction while Track_most_recent_products is true, and</span>
+<span class="Comment">//: keeps the most recent such result around so that it can be returned as the</span>
+<span class="Comment">//: result of a sandbox.</span>
+
 <span class="Delimiter">:(before &quot;End Globals&quot;)</span>
 <span class="Normal">bool</span> Track_most_recent_products = <span class="Constant">false</span><span class="Delimiter">;</span>
-trace_stream* Save_trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span>
-string Save_trace_file<span class="Delimiter">;</span>
+string Most_recent_products<span class="Delimiter">;</span>
 <span class="Delimiter">:(before &quot;End Setup&quot;)</span>
 Track_most_recent_products = <span class="Constant">false</span><span class="Delimiter">;</span>
+Most_recent_products = <span class="Constant">&quot;&quot;</span><span class="Delimiter">;</span>
+
+<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
+trace_stream* Save_trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span>
+string Save_trace_file<span class="Delimiter">;</span>
 <span class="Delimiter">:(code)</span>
 <span class="Comment">// reads a string, tries to call it as code (treating it as a test), saving</span>
 <span class="Comment">// all errors.</span>
@@ -175,6 +185,9 @@ map&lt;string<span class="Delimiter">,</span> vector&lt;recipe_ordinal&gt; &gt;
 <span class="Normal">void</span> run_code_end<span class="Delimiter">()</span> <span class="Delimiter">{</span>
   Hide_errors = <span class="Constant">false</span><span class="Delimiter">;</span>
   Disable_redefine_checks = <span class="Constant">false</span><span class="Delimiter">;</span>
+<span class="CommentedCode">//?   ofstream fout(&quot;sandbox.log&quot;);</span>
+<span class="CommentedCode">//?   fout &lt;&lt; Trace_stream-&gt;readable_contents(&quot;&quot;);</span>
+<span class="CommentedCode">//?   fout.close();</span>
   <span class="Normal">delete</span> Trace_stream<span class="Delimiter">;</span>
   Trace_stream = Save_trace_stream<span class="Delimiter">;</span>
   Save_trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span>
@@ -382,10 +395,6 @@ def main [
 <span class="Comment"># no errors</span>
 <span class="traceContains">+mem: storing 0 in location 3</span>
 
-<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
-string Most_recent_products<span class="Delimiter">;</span>
-<span class="Delimiter">:(before &quot;End Setup&quot;)</span>
-Most_recent_products = <span class="Constant">&quot;&quot;</span><span class="Delimiter">;</span>
 <span class="Delimiter">:(before &quot;End Running One Instruction&quot;)</span>
 <span class="Normal">if</span> <span class="Delimiter">(</span>Track_most_recent_products<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   track_most_recent_products<span class="Delimiter">(</span>current_instruction<span class="Delimiter">(),</span> products<span class="Delimiter">);</span>
@@ -394,14 +403,22 @@ Most_recent_products = <span class="Constant">&quot;&quot;</span><span class="De
 <span class="Normal">void</span> track_most_recent_products<span class="Delimiter">(</span><span class="Normal">const</span> instruction&amp; instruction<span class="Delimiter">,</span> <span class="Normal">const</span> vector&lt;vector&lt;<span class="Normal">double</span>&gt; &gt;&amp; products<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   ostringstream out<span class="Delimiter">;</span>
   <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    <span class="Comment">// string</span>
+    <span class="Comment">// A sandbox can print a string result, but only if it is actually saved</span>
+    <span class="Comment">// to a variable in the sandbox, because otherwise the results are</span>
+    <span class="Comment">// reclaimed before the sandbox sees them. So you get these interactions</span>
+    <span class="Comment">// in the sandbox:</span>
+    <span class="Comment">//</span>
+    <span class="Comment">//    new [abc]</span>
+    <span class="Comment">//    =&gt; &lt;address&gt;</span>
+    <span class="Comment">//</span>
+    <span class="Comment">//    x:text &lt;- new [abc]</span>
+    <span class="Comment">//    =&gt; abc</span>
     <span class="Normal">if</span> <span class="Delimiter">(</span>i &lt; SIZE<span class="Delimiter">(</span>instruction<span class="Delimiter">.</span>products<span class="Delimiter">))</span> <span class="Delimiter">{</span>
       <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_string<span class="Delimiter">(</span>instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span>
         <span class="Normal">if</span> <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>  <span class="Comment">// error handled elsewhere</span>
         out &lt;&lt; read_mu_string<span class="Delimiter">(</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
         <span class="Identifier">continue</span><span class="Delimiter">;</span>
       <span class="Delimiter">}</span>
-      <span class="Comment">// End Record Product Special-cases</span>
     <span class="Delimiter">}</span>
     <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> ++j<span class="Delimiter">)</span>
       out &lt;&lt; no_scientific<span class="Delimiter">(</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span>j<span class="Delimiter">))</span> &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span>
diff --git a/html/edit/010-sandbox-trace.mu.html b/html/edit/010-sandbox-trace.mu.html
index 3c4956b7..177fdee1 100644
--- a/html/edit/010-sandbox-trace.mu.html
+++ b/html/edit/010-sandbox-trace.mu.html
@@ -76,9 +76,6 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
    <span class="Constant"> .  stash [abc]                                     ┊0   edit          copy            delete         .</span>
    <span class="Constant"> .]                                                 ┊foo                                              .</span>
    <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊abc                                              .</span>
-   <span class="Constant"> .                                                  ┊8 instructions run                               .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
   ]
   screen-should-contain-in-color <span class="Constant">245/grey</span>, [
    <span class="Constant"> .                                                                                                    .</span>
@@ -87,9 +84,6 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
    <span class="Constant"> .                                                  ┊                                                 .</span>
    <span class="Constant"> .                                                  ┊                                                 .</span>
    <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊abc                                              .</span>
-   <span class="Constant"> .                                                  ┊8 instructions run                               .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
   ]
   <span class="Comment"># click again on the same region</span>
   assume-console [
@@ -178,9 +172,6 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
    <span class="Constant"> .                                                  ┊0   edit          copy            delete         .</span>
    <span class="Constant"> .                                                  ┊stash 123456789                                  .</span>
    <span class="Constant"> .                                                  ┊123456789                                        .</span>
-   <span class="Constant"> .                                                  ┊6 instructions run                               .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
   ]
   <span class="Comment"># click on the stash under the edit-button region (or any of the other buttons, really)</span>
   assume-console [
@@ -197,9 +188,6 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
    <span class="Constant"> .                                                  ┊0   edit          copy            delete         .</span>
    <span class="Constant"> .                                                  ┊stash 123456789                                  .</span>
    <span class="Constant"> .                                                  ┊123456789                                        .</span>
-   <span class="Constant"> .                                                  ┊6 instructions run                               .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
   ]
 ]