about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--html/003trace.cc.html7
-rw-r--r--html/010vm.cc.html6
-rw-r--r--html/020run.cc.html4
-rw-r--r--html/029debug.cc.html36
-rw-r--r--html/030container.cc.html55
-rw-r--r--html/032array.cc.html88
-rw-r--r--html/036call_reply.cc.html1
-rw-r--r--html/043new.cc.html104
-rw-r--r--html/044space.cc.html62
-rw-r--r--html/050scenario.cc.html2
-rw-r--r--html/060string.mu.html77
-rw-r--r--html/061channel.mu.html30
-rw-r--r--html/062array.mu.html2
-rw-r--r--html/063list.mu.html6
-rw-r--r--html/065duplex_list.mu.html12
-rw-r--r--html/066stream.mu.html8
-rw-r--r--html/071print.mu.html112
-rw-r--r--html/074console.mu.html12
-rw-r--r--html/081run_interactive.cc.html112
-rw-r--r--html/082persist.cc.html109
-rw-r--r--html/999spaces.cc.html6
-rw-r--r--html/channel.mu.html6
-rw-r--r--html/chessboard.mu.html102
-rw-r--r--html/counters.mu.html4
-rw-r--r--html/edit.mu.html1180
-rw-r--r--html/factorial.mu.html4
-rw-r--r--html/tangle.mu.html2
-rw-r--r--index.html18
28 files changed, 1785 insertions, 382 deletions
diff --git a/html/003trace.cc.html b/html/003trace.cc.html
index a94ed6b1..0143551b 100644
--- a/html/003trace.cc.html
+++ b/html/003trace.cc.html
@@ -136,14 +136,17 @@ struct trace_stream <span class="Delimiter">{</span>
   string curr_layer<span class="Delimiter">;</span>
   int curr_depth<span class="Delimiter">;</span>
   string dump_layer<span class="Delimiter">;</span>
+  string collect_layer<span class="Delimiter">;</span>  <span class="Comment">// if set, ignore all other layers</span>
+  ofstream null_stream<span class="Delimiter">;</span>  <span class="Comment">// never opens a file, so writes silently fail</span>
   trace_stream<span class="Delimiter">()</span> :curr_stream<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> curr_depth<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span>
   ~trace_stream<span class="Delimiter">()</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>curr_stream<span class="Delimiter">)</span> delete curr_stream<span class="Delimiter">;</span> <span class="Delimiter">}</span>
 
-  ostringstream&amp; stream<span class="Delimiter">(</span>string layer<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  ostream&amp; stream<span class="Delimiter">(</span>string layer<span class="Delimiter">)</span> <span class="Delimiter">{</span>
     <span class="Identifier">return</span> stream<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> layer<span class="Delimiter">);</span>
   <span class="Delimiter">}</span>
 
-  ostringstream&amp; stream<span class="Delimiter">(</span>int depth<span class="Delimiter">,</span> string layer<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  ostream&amp; stream<span class="Delimiter">(</span>int depth<span class="Delimiter">,</span> string layer<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    if <span class="Delimiter">(</span>!collect_layer<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; layer != collect_layer<span class="Delimiter">)</span> <span class="Identifier">return</span> null_stream<span class="Delimiter">;</span>
     newline<span class="Delimiter">();</span>
     curr_stream = new ostringstream<span class="Delimiter">;</span>
     curr_layer = layer<span class="Delimiter">;</span>
diff --git a/html/010vm.cc.html b/html/010vm.cc.html
index 6e76f36f..95a36dcf 100644
--- a/html/010vm.cc.html
+++ b/html/010vm.cc.html
@@ -192,8 +192,8 @@ void setup_recipes<span class="Delimiter">()</span> <span class="Delimiter">{</s
 <span class="Comment">//: itself.</span>
 <span class="Delimiter">:(before &quot;End One-time Setup&quot;)</span>
 setup_recipes<span class="Delimiter">();</span>
-assert<span class="Delimiter">(</span>MAX_PRIMITIVE_RECIPES &lt; <span class="Constant">100</span><span class="Delimiter">);</span>  <span class="Comment">// level 0 is primitives; until 99</span>
-Next_recipe_ordinal = <span class="Constant">100</span><span class="Delimiter">;</span>
+assert<span class="Delimiter">(</span>MAX_PRIMITIVE_RECIPES &lt; <span class="Constant">200</span><span class="Delimiter">);</span>  <span class="Comment">// level 0 is primitives; until 199</span>
+Next_recipe_ordinal = <span class="Constant">200</span><span class="Delimiter">;</span>
 <span class="Comment">// End Load Recipes</span>
 <span class="Delimiter">:(before &quot;End Test Run Initialization&quot;)</span>
 assert<span class="Delimiter">(</span>Next_recipe_ordinal &lt; <span class="Constant">1000</span><span class="Delimiter">);</span>  <span class="Comment">// recipes being tested didn't overflow into test space</span>
@@ -304,8 +304,6 @@ void dump_memory<span class="Delimiter">()</span> <span class="Delimiter">{</spa
   <span class="Delimiter">}</span>
 <span class="Delimiter">}</span>
 <span class="Delimiter">:(before &quot;End Includes&quot;)</span>
-<span class="PreProc">#include </span><span class="Constant">&lt;map&gt;</span>
-using std::map<span class="Delimiter">;</span>
 <span class="PreProc">#include</span><span class="Constant">&lt;utility&gt;</span>
 using std::pair<span class="Delimiter">;</span>
 </pre>
diff --git a/html/020run.cc.html b/html/020run.cc.html
index fc5fd15f..792703a1 100644
--- a/html/020run.cc.html
+++ b/html/020run.cc.html
@@ -122,7 +122,7 @@ void run_current_routine<span class="Delimiter">()</span>
       <span class="Delimiter">}</span>
     <span class="Delimiter">}</span>
     if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>products<span class="Delimiter">)</span> &lt; SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">))</span>
-      raise &lt;&lt; <span class="Constant">&quot;failed to write to all products! &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">();</span>
+      raise &lt;&lt; SIZE<span class="Delimiter">(</span>products<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; vs &quot;</span> &lt;&lt; SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;: failed to write to all products! &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">();</span>
     for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
       write_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span>
     <span class="Delimiter">}</span>
@@ -165,7 +165,7 @@ if <span class="Delimiter">(</span>argc &gt; <span class="Constant">1</span><spa
 if <span class="Delimiter">(</span>!Run_tests<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   setup<span class="Delimiter">();</span>
 <span class="CommentedCode">//?   Trace_file = &quot;interactive&quot;; //? 1</span>
-  START_TRACING_UNTIL_END_OF_SCOPE<span class="Delimiter">;</span>
+<span class="CommentedCode">//?   START_TRACING_UNTIL_END_OF_SCOPE;</span>
 <span class="CommentedCode">//?   Trace_stream-&gt;dump_layer = &quot;all&quot;; //? 2</span>
   transform_all<span class="Delimiter">();</span>
   recipe_ordinal r = Recipe_ordinal[string<span class="Delimiter">(</span><span class="Constant">&quot;main&quot;</span><span class="Delimiter">)</span>]<span class="Delimiter">;</span>
diff --git a/html/029debug.cc.html b/html/029debug.cc.html
index 85f82582..58adec43 100644
--- a/html/029debug.cc.html
+++ b/html/029debug.cc.html
@@ -13,6 +13,7 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
+.cSpecial { color: #008000; }
 .Constant { color: #00a0a0; }
 .Comment { color: #9090ff; }
 .Delimiter { color: #a04060; }
@@ -40,7 +41,10 @@ case _PRINT: <span class="Delimiter">{</span>
   for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
     if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span>
       trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;$print: &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">;</span>
-      cout &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">;</span>
+      if <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Constant">&quot;newline&quot;</span><span class="Delimiter">))</span>
+        cout &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+      else
+        cout &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">;</span>
     <span class="Delimiter">}</span>
     else <span class="Delimiter">{</span>
       for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span>
@@ -134,6 +138,36 @@ case _DUMP_MEMORY: <span class="Delimiter">{</span>
   dump_memory<span class="Delimiter">();</span>
   <span class="Identifier">break</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
+
+<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
+_DUMP<span class="Delimiter">,</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
+Recipe_ordinal[<span class="Constant">&quot;$dump&quot;</span>] = _DUMP<span class="Delimiter">;</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
+case _DUMP: <span class="Delimiter">{</span>
+  reagent after_canonize = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span>
+  cerr &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">' '</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>value &lt;&lt; <span class="Constant">&quot; =&gt; &quot;</span> &lt;&lt; after_canonize<span class="Delimiter">.</span>value &lt;&lt; <span class="Constant">&quot; =&gt; &quot;</span> &lt;&lt; Memory[after_canonize<span class="Delimiter">.</span>value] &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+  <span class="Identifier">break</span><span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
+<span class="Comment">//: Helper for debugging: grab an address and then dump its value.</span>
+<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
+long long int foo = -<span class="Constant">1</span><span class="Delimiter">;</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
+_FOO<span class="Delimiter">,</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
+Recipe_ordinal[<span class="Constant">&quot;$foo&quot;</span>] = _FOO<span class="Delimiter">;</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
+case _FOO: <span class="Delimiter">{</span>
+  if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span>
+    if <span class="Delimiter">(</span>foo != -<span class="Constant">1</span><span class="Delimiter">)</span> cerr &lt;&lt; foo &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; Memory[foo] &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+    else cerr &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
+  else <span class="Delimiter">{</span>
+    foo = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)).</span>value<span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
+  <span class="Identifier">break</span><span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
 </pre>
 </body>
 </html>
diff --git a/html/030container.cc.html b/html/030container.cc.html
index fb0e1cdc..d7666e33 100644
--- a/html/030container.cc.html
+++ b/html/030container.cc.html
@@ -148,15 +148,17 @@ case GET: <span class="Delimiter">{</span>
   assert<span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)));</span>
   assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)));</span>
   long long int offset = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
-  assert<span class="Delimiter">(</span>offset &gt;= <span class="Constant">0</span><span class="Delimiter">);</span>
-  assert<span class="Delimiter">(</span>offset &lt; size_of<span class="Delimiter">(</span>base<span class="Delimiter">));</span>
   long long int src = base_address<span class="Delimiter">;</span>
   for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; offset<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
     src += size_of<span class="Delimiter">(</span>Type[base_type]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span>
   <span class="Delimiter">}</span>
   trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;address to copy is &quot;</span> &lt;&lt; src<span class="Delimiter">;</span>
   assert<span class="Delimiter">(</span>Type[base_type]<span class="Delimiter">.</span>kind == container<span class="Delimiter">);</span>
-  assert<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Type[base_type]<span class="Delimiter">.</span>elements<span class="Delimiter">)</span> &gt; offset<span class="Delimiter">);</span>
+  if <span class="Delimiter">(</span>offset &lt; <span class="Constant">0</span> || offset &gt;= SIZE<span class="Delimiter">(</span>Type[base_type]<span class="Delimiter">.</span>elements<span class="Delimiter">))</span> <span class="Delimiter">{</span>
+    raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: invalid offset &quot;</span> &lt;&lt; offset &lt;&lt; <span class="Constant">&quot; for &quot;</span> &lt;&lt; Type[base_type]<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+    products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
+    <span class="Identifier">break</span><span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
   type_ordinal src_type = Type[base_type]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>offset<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
   trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;its type is &quot;</span> &lt;&lt; Type[src_type]<span class="Delimiter">.</span>name<span class="Delimiter">;</span>
   reagent tmp<span class="Delimiter">;</span>
@@ -185,6 +187,26 @@ recipe main [
 ]
 <span class="traceContains">+mem: storing 13 in location 15</span>
 
+<span class="Delimiter">:(scenario get_out_of_bounds)</span>
+<span class="Special">% Hide_warnings = true;</span>
+recipe main [
+  <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>:literal
+  <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>:literal
+  <span class="Constant">14</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>:literal
+  get <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2</span>:offset  <span class="Comment"># point-number occupies 3 locations but has only 2 fields; out of bounds</span>
+]
+<span class="traceContains">+warn: main: invalid offset 2 for point-number</span>
+
+<span class="Delimiter">:(scenario get_out_of_bounds2)</span>
+<span class="Special">% Hide_warnings = true;</span>
+recipe main [
+  <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>:literal
+  <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>:literal
+  <span class="Constant">14</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>:literal
+  get <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> -<span class="Constant">1</span>:offset
+]
+<span class="traceContains">+warn: main: invalid offset -1 for point-number</span>
+
 <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
 GET_ADDRESS<span class="Delimiter">,</span>
 <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
@@ -199,8 +221,11 @@ case GET_ADDRESS: <span class="Delimiter">{</span>
   assert<span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)));</span>
   assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)));</span>
   long long int offset = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
-  assert<span class="Delimiter">(</span>offset &gt;= <span class="Constant">0</span><span class="Delimiter">);</span>
-  assert<span class="Delimiter">(</span>offset &lt; size_of<span class="Delimiter">(</span>base<span class="Delimiter">));</span>
+  if <span class="Delimiter">(</span>offset &lt; <span class="Constant">0</span> || offset &gt;= SIZE<span class="Delimiter">(</span>Type[base_type]<span class="Delimiter">.</span>elements<span class="Delimiter">))</span> <span class="Delimiter">{</span>
+    raise &lt;&lt; <span class="Constant">&quot;invalid offset &quot;</span> &lt;&lt; offset &lt;&lt; <span class="Constant">&quot; for &quot;</span> &lt;&lt; Type[base_type]<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+    products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
+    <span class="Identifier">break</span><span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
   long long int result = base_address<span class="Delimiter">;</span>
   for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; offset<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
     result += size_of<span class="Delimiter">(</span>Type[base_type]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span>
@@ -211,6 +236,26 @@ case GET_ADDRESS: <span class="Delimiter">{</span>
   <span class="Identifier">break</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
+<span class="Delimiter">:(scenario get_address_out_of_bounds)</span>
+<span class="Special">% Hide_warnings = true;</span>
+recipe main [
+  <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>:literal
+  <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>:literal
+  <span class="Constant">14</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>:literal
+  get-address <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2</span>:offset  <span class="Comment"># point-number occupies 3 locations but has only 2 fields; out of bounds</span>
+]
+<span class="traceContains">+warn: invalid offset 2 for point-number</span>
+
+<span class="Delimiter">:(scenario get_address_out_of_bounds2)</span>
+<span class="Special">% Hide_warnings = true;</span>
+recipe main [
+  <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>:literal
+  <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>:literal
+  <span class="Constant">14</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>:literal
+  get-address <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> -<span class="Constant">1</span>:offset
+]
+<span class="traceContains">+warn: invalid offset -1 for point-number</span>
+
 <span class="SalientComment">//:: Allow containers to be defined in mu code.</span>
 
 <span class="Delimiter">:(scenarios load)</span>
diff --git a/html/032array.cc.html b/html/032array.cc.html
index 101bd958..fddb6a17 100644
--- a/html/032array.cc.html
+++ b/html/032array.cc.html
@@ -122,8 +122,11 @@ case INDEX: <span class="Delimiter">{</span>
   vector&lt;type_ordinal&gt; element_type = array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>types<span class="Delimiter">);</span>
 <span class="CommentedCode">//?   trace(Primitive_recipe_depth, &quot;run&quot;) &lt;&lt; &quot;offset: &quot; &lt;&lt; offset_val.at(0); //? 1</span>
 <span class="CommentedCode">//?   trace(Primitive_recipe_depth, &quot;run&quot;) &lt;&lt; &quot;size of elements: &quot; &lt;&lt; size_of(element_type); //? 1</span>
-  assert<span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &gt;= <span class="Constant">0</span><span class="Delimiter">);</span>
-  assert<span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &lt; Memory[base_address]*size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">)</span> + <span class="Constant">1</span><span class="Delimiter">);</span>
+  if <span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &lt; <span class="Constant">0</span> || offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &gt;= Memory[base_address]<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: invalid index &quot;</span> &lt;&lt; offset_val<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>
+    products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
+    <span class="Identifier">break</span><span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
   long long int src = base_address + <span class="Constant">1</span> + offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>*size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">);</span>
   trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;address to copy is &quot;</span> &lt;&lt; src<span class="Delimiter">;</span>
   trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;its type is &quot;</span> &lt;&lt; Type[element_type<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>]<span class="Delimiter">.</span>name<span class="Delimiter">;</span>
@@ -139,28 +142,58 @@ vector&lt;type_ordinal&gt; array_element<span class="Delimiter">(</span>const ve
   <span class="Identifier">return</span> vector&lt;type_ordinal&gt;<span class="Delimiter">(</span>++types<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> types<span class="Delimiter">.</span>end<span class="Delimiter">());</span>
 <span class="Delimiter">}</span>
 
-<span class="Delimiter">:(scenario index_address)</span>
+<span class="Delimiter">:(scenario index_indirect)</span>
 recipe main [
   <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>:literal  <span class="Comment"># length</span>
   <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span>:literal
   <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span>:literal
   <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span>:literal
-  <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>index-address <span class="Constant">1</span>:array:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">0</span>:literal  <span class="Comment"># unsafe</span>
+  <span class="Constant">5</span>:address:array:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:literal
+  <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>index <span class="Constant">5</span>:address:array:number/deref<span class="Delimiter">,</span> <span class="Constant">1</span>:literal
 ]
-<span class="traceContains">+mem: storing 2 in location 5</span>
+<span class="traceContains">+mem: storing 15 in location 6</span>
+
+<span class="Delimiter">:(scenario index_out_of_bounds)</span>
+<span class="Special">% Hide_warnings = true;</span>
+recipe main [
+  <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>:literal  <span class="Comment"># 3 points</span>
+  <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span>:literal
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span>:literal
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span>:literal
+  <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span>:literal
+  <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span>:literal
+  <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span>:literal
+  <span class="Constant">8</span>:address:array:point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:literal
+  index <span class="Constant">8</span>:address:array:point/deref<span class="Delimiter">,</span> <span class="Constant">4</span>:literal  <span class="Comment"># less than size of array in locations, but larger than its length in elements</span>
+]
+<span class="traceContains">+warn: main: invalid index 4</span>
+
+<span class="Delimiter">:(scenario index_out_of_bounds2)</span>
+<span class="Special">% Hide_warnings = true;</span>
+recipe main [
+  <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>:literal  <span class="Comment"># 3 points</span>
+  <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span>:literal
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span>:literal
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span>:literal
+  <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span>:literal
+  <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span>:literal
+  <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span>:literal
+  <span class="Constant">8</span>:address:array:point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:literal
+  index <span class="Constant">8</span>:address:array:point/deref<span class="Delimiter">,</span> -<span class="Constant">1</span>:literal
+]
+<span class="traceContains">+warn: main: invalid index -1</span>
 
 <span class="SalientComment">//:: To write to elements of containers, you need their address.</span>
 
-<span class="Delimiter">:(scenario index_indirect)</span>
+<span class="Delimiter">:(scenario index_address)</span>
 recipe main [
   <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>:literal  <span class="Comment"># length</span>
   <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span>:literal
   <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span>:literal
   <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span>:literal
-  <span class="Constant">5</span>:address:array:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:literal
-  <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>index <span class="Constant">5</span>:address:array:number/deref<span class="Delimiter">,</span> <span class="Constant">1</span>:literal
+  <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>index-address <span class="Constant">1</span>:array:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">0</span>:literal  <span class="Comment"># unsafe</span>
 ]
-<span class="traceContains">+mem: storing 15 in location 6</span>
+<span class="traceContains">+mem: storing 2 in location 5</span>
 
 <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
 INDEX_ADDRESS<span class="Delimiter">,</span>
@@ -174,14 +207,47 @@ case INDEX_ADDRESS: <span class="Delimiter">{</span>
   reagent offset = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">));</span>
   vector&lt;double&gt; offset_val<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>offset<span class="Delimiter">));</span>
   vector&lt;type_ordinal&gt; element_type = array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>types<span class="Delimiter">);</span>
-  assert<span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &gt;= <span class="Constant">0</span><span class="Delimiter">);</span>
-  assert<span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &lt; Memory[base_address]*size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">)</span> + <span class="Constant">1</span><span class="Delimiter">);</span>
+  if <span class="Delimiter">(</span>offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &lt; <span class="Constant">0</span> || offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &gt;= Memory[base_address]<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: invalid index &quot;</span> &lt;&lt; offset_val<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>
+    products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
+    <span class="Identifier">break</span><span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
   long long int result = base_address + <span class="Constant">1</span> + offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>*size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">);</span>
   products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
   products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span>
   <span class="Identifier">break</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
+<span class="Delimiter">:(scenario index_address_out_of_bounds)</span>
+<span class="Special">% Hide_warnings = true;</span>
+recipe main [
+  <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>:literal  <span class="Comment"># 3 points</span>
+  <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span>:literal
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span>:literal
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span>:literal
+  <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span>:literal
+  <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span>:literal
+  <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span>:literal
+  <span class="Constant">8</span>:address:array:point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:literal
+  index-address <span class="Constant">8</span>:address:array:point/deref<span class="Delimiter">,</span> <span class="Constant">4</span>:literal  <span class="Comment"># less than size of array in locations, but larger than its length in elements</span>
+]
+<span class="traceContains">+warn: main: invalid index 4</span>
+
+<span class="Delimiter">:(scenario index_address_out_of_bounds2)</span>
+<span class="Special">% Hide_warnings = true;</span>
+recipe main [
+  <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>:literal  <span class="Comment"># 3 points</span>
+  <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span>:literal
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span>:literal
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span>:literal
+  <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span>:literal
+  <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span>:literal
+  <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span>:literal
+  <span class="Constant">8</span>:address:array:point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:literal
+  index-address <span class="Constant">8</span>:address:array:point/deref<span class="Delimiter">,</span> -<span class="Constant">1</span>:literal
+]
+<span class="traceContains">+warn: main: invalid index -1</span>
+
 <span class="SalientComment">//:: compute the length of an array</span>
 
 <span class="Delimiter">:(scenario array_length)</span>
diff --git a/html/036call_reply.cc.html b/html/036call_reply.cc.html
index ab73fdb7..c32b06ae 100644
--- a/html/036call_reply.cc.html
+++ b/html/036call_reply.cc.html
@@ -85,6 +85,7 @@ case REPLY: <span class="Delimiter">{</span>
         raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: 'same-as-ingredient' result &quot;</span> &lt;&lt; caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>value &lt;&lt; <span class="Constant">&quot; from call to &quot;</span> &lt;&lt; callee &lt;&lt; <span class="Constant">&quot; must be location &quot;</span> &lt;&lt; caller_instruction<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">).</span>value &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
     <span class="Delimiter">}</span>
   <span class="Delimiter">}</span>
+  <span class="Comment">// End Reply</span>
   <span class="Identifier">break</span><span class="Delimiter">;</span>  <span class="Comment">// continue to process rest of *caller* instruction</span>
 <span class="Delimiter">}</span>
 
diff --git a/html/043new.cc.html b/html/043new.cc.html
index a34f46fc..60ebb332 100644
--- a/html/043new.cc.html
+++ b/html/043new.cc.html
@@ -110,6 +110,8 @@ case NEW: <span class="Delimiter">{</span>
       size = size_of<span class="Delimiter">(</span>type<span class="Delimiter">);</span>
     <span class="Delimiter">}</span>
   <span class="Delimiter">}</span>
+<span class="CommentedCode">//?   Total_alloc += size; //? 1</span>
+<span class="CommentedCode">//?   Num_alloc++; //? 1</span>
   <span class="Comment">// compute the region of memory to return</span>
   <span class="Comment">// really crappy at the moment</span>
   ensure_space<span class="Delimiter">(</span>size<span class="Delimiter">);</span>
@@ -133,6 +135,18 @@ case NEW: <span class="Delimiter">{</span>
   <span class="Identifier">break</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
+<span class="CommentedCode">//? :(before &quot;End Globals&quot;) //? 1</span>
+<span class="CommentedCode">//? long long int Total_alloc = 0; //? 1</span>
+<span class="CommentedCode">//? long long int Num_alloc = 0; //? 1</span>
+<span class="CommentedCode">//? long long int Total_free = 0; //? 1</span>
+<span class="CommentedCode">//? long long int Num_free = 0; //? 1</span>
+<span class="CommentedCode">//? :(before &quot;End Setup&quot;) //? 1</span>
+<span class="CommentedCode">//? Total_alloc = Num_alloc = Total_free = Num_free = 0; //? 1</span>
+<span class="CommentedCode">//? :(before &quot;End Teardown&quot;) //? 1</span>
+<span class="CommentedCode">//? cerr &lt;&lt; Total_alloc &lt;&lt; &quot;/&quot; &lt;&lt; Num_alloc //? 1</span>
+<span class="CommentedCode">//?      &lt;&lt; &quot; vs &quot; &lt;&lt; Total_free &lt;&lt; &quot;/&quot; &lt;&lt; Num_free &lt;&lt; '\n'; //? 1</span>
+<span class="CommentedCode">//? cerr &lt;&lt; Memory.size() &lt;&lt; '\n'; //? 1</span>
+
 <span class="Delimiter">:(code)</span>
 void ensure_space<span class="Delimiter">(</span>long long int size<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   assert<span class="Delimiter">(</span>size &lt;= Initial_memory_per_routine<span class="Delimiter">);</span>
@@ -205,6 +219,94 @@ recipe main [
 <span class="traceContains">+new: routine allocated memory from 1000 to 1002</span>
 <span class="traceContains">+new: routine allocated memory from 1002 to 1004</span>
 
+<span class="Comment">//: We also provide a way to return memory, and to reuse reclaimed memory.</span>
+<span class="Comment">//: todo: custodians, etc. Following malloc/free is a temporary hack.</span>
+
+<span class="Delimiter">:(scenario new_reclaim)</span>
+recipe main [
+  <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>new number:type
+  abandon <span class="Constant">1</span>:address:number
+  <span class="Constant">2</span>:address:number<span class="Special"> &lt;- </span>new number:type  <span class="Comment"># must be same size as abandoned memory to reuse</span>
+  <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:number<span class="Delimiter">,</span> <span class="Constant">2</span>:address:number
+]
+<span class="Comment"># both allocations should have returned the same address</span>
+<span class="traceContains">+mem: storing 1 in location 3</span>
+
+<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
+map&lt;long long int<span class="Delimiter">,</span> long long int&gt; Free_list<span class="Delimiter">;</span>
+<span class="Delimiter">:(before &quot;End Setup&quot;)</span>
+Free_list<span class="Delimiter">.</span>clear<span class="Delimiter">();</span>
+
+<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
+ABANDON<span class="Delimiter">,</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
+Recipe_ordinal[<span class="Constant">&quot;abandon&quot;</span>] = ABANDON<span class="Delimiter">;</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
+case ABANDON: <span class="Delimiter">{</span>
+  if <span class="Delimiter">(</span>!scalar<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>
+    raise &lt;&lt; <span class="Constant">&quot;abandon's ingredient should be scalar</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
+    <span class="Identifier">break</span><span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
+  long long int address = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
+  reagent types = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span>
+  if <span class="Delimiter">(</span>types<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> != Type_ordinal[<span class="Constant">&quot;address&quot;</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    raise &lt;&lt; <span class="Constant">&quot;abandon's ingredient should be an address</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
+    <span class="Identifier">break</span><span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
+  reagent target_type = deref<span class="Delimiter">(</span>types<span class="Delimiter">);</span>
+  abandon<span class="Delimiter">(</span>address<span class="Delimiter">,</span> size_of<span class="Delimiter">(</span>target_type<span class="Delimiter">));</span>
+  <span class="Identifier">break</span><span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
+<span class="Delimiter">:(code)</span>
+void abandon<span class="Delimiter">(</span>long long int address<span class="Delimiter">,</span> long long int size<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+<span class="CommentedCode">//?   Total_free += size; //? 1</span>
+<span class="CommentedCode">//?   Num_free++; //? 1</span>
+<span class="CommentedCode">//?   cerr &lt;&lt; &quot;abandon: &quot; &lt;&lt; size &lt;&lt; '\n'; //? 2</span>
+  <span class="Comment">// clear memory</span>
+  for <span class="Delimiter">(</span>long long int curr = address<span class="Delimiter">;</span> curr &lt; address+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span>
+    Memory[curr] = <span class="Constant">0</span><span class="Delimiter">;</span>
+  <span class="Comment">// append existing free list to address</span>
+  Memory[address] = Free_list[size]<span class="Delimiter">;</span>
+  Free_list[size] = address<span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
+<span class="Delimiter">:(before &quot;ensure_space(size)&quot; following &quot;case NEW&quot;)</span>
+if <span class="Delimiter">(</span>Free_list[size]<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  long long int result = Free_list[size]<span class="Delimiter">;</span>
+  Free_list[size] = Memory[result]<span class="Delimiter">;</span>
+  for <span class="Delimiter">(</span>long long int curr = result+<span class="Constant">1</span><span class="Delimiter">;</span> curr &lt; result+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span>
+    if <span class="Delimiter">(</span>Memory[curr] != <span class="Constant">0</span><span class="Delimiter">)</span>
+      raise &lt;&lt; current_recipe_name<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: memory in free list was not zeroed out: &quot;</span> &lt;&lt; curr &lt;&lt; <span class="Constant">'/'</span> &lt;&lt; result &lt;&lt; <span class="Constant">&quot;; somebody wrote to us after free!!!</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; die<span class="Delimiter">();</span>
+  if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span>
+    Memory[result] = array_length<span class="Delimiter">;</span>
+  else
+    Memory[result] = <span class="Constant">0</span><span class="Delimiter">;</span>
+  products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
+  products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span>
+  <span class="Identifier">break</span><span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
+<span class="Delimiter">:(scenario new_differing_size_no_reclaim)</span>
+recipe main [
+  <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>new number:type
+  abandon <span class="Constant">1</span>:address:number
+  <span class="Constant">2</span>:address:number<span class="Special"> &lt;- </span>new number:type<span class="Delimiter">,</span> <span class="Constant">2</span>:literal  <span class="Comment"># different size</span>
+  <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:number<span class="Delimiter">,</span> <span class="Constant">2</span>:address:number
+]
+<span class="Comment"># no reuse</span>
+<span class="traceContains">+mem: storing 0 in location 3</span>
+
+<span class="Delimiter">:(scenario new_reclaim_array)</span>
+recipe main [
+  <span class="Constant">1</span>:address:array:number<span class="Special"> &lt;- </span>new number:type<span class="Delimiter">,</span> <span class="Constant">2</span>:literal
+  abandon <span class="Constant">1</span>:address:array:number
+  <span class="Constant">2</span>:address:array:number<span class="Special"> &lt;- </span>new number:type<span class="Delimiter">,</span> <span class="Constant">2</span>:literal
+  <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:array:number<span class="Delimiter">,</span> <span class="Constant">2</span>:address:array:number
+]
+<span class="Comment"># reuse</span>
+<span class="traceContains">+mem: storing 1 in location 3</span>
+
 <span class="SalientComment">//:: Next, extend 'new' to handle a unicode string literal argument.</span>
 
 <span class="Delimiter">:(scenario new_string)</span>
@@ -248,6 +350,8 @@ long long int new_string<span class="Delimiter">(</span>const string&amp; conten
   <span class="Comment">// allocate an array just large enough for it</span>
   long long int string_length = unicode_length<span class="Delimiter">(</span>contents<span class="Delimiter">);</span>
 <span class="CommentedCode">//?   cout &lt;&lt; &quot;string_length is &quot; &lt;&lt; string_length &lt;&lt; '\n'; //? 1</span>
+<span class="CommentedCode">//?   Total_alloc += string_length+1; //? 1</span>
+<span class="CommentedCode">//?   Num_alloc++; //? 1</span>
   ensure_space<span class="Delimiter">(</span>string_length+<span class="Constant">1</span><span class="Delimiter">);</span>  <span class="Comment">// don't forget the extra location for array size</span>
   <span class="Comment">// initialize string</span>
 <span class="CommentedCode">//?   cout &lt;&lt; &quot;new string literal: &quot; &lt;&lt; current_instruction().ingredients.at(0).name &lt;&lt; '\n'; //? 1</span>
diff --git a/html/044space.cc.html b/html/044space.cc.html
index ca3a7bec..b0e25bf2 100644
--- a/html/044space.cc.html
+++ b/html/044space.cc.html
@@ -160,14 +160,7 @@ if <span class="Delimiter">(</span>s == <span class="Constant">&quot;number-of-l
 <span class="Comment">//   `default-space:address:array:location &lt;- new location:type, number-of-locals:literal`</span>
 <span class="Comment">// where N is Name[recipe][&quot;&quot;]</span>
 if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">&quot;new-default-space&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
-  curr<span class="Delimiter">.</span>operation = Recipe_ordinal[<span class="Constant">&quot;new&quot;</span>]<span class="Delimiter">;</span>
-  if <span class="Delimiter">(</span>!curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span>
-    raise &lt;&lt; <span class="Constant">&quot;new-default-space can't take any ingredients</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
-  curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;location:type&quot;</span><span class="Delimiter">));</span>
-  curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;number-of-locals:literal&quot;</span><span class="Delimiter">));</span>
-  if <span class="Delimiter">(</span>!curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span>
-    raise &lt;&lt; <span class="Constant">&quot;new-default-space can't take any results</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
-  curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;default-space:address:array:location&quot;</span><span class="Delimiter">));</span>
+  rewrite_default_space_instruction<span class="Delimiter">(</span>curr<span class="Delimiter">);</span>
 <span class="Delimiter">}</span>
 <span class="Delimiter">:(after &quot;vector&lt;double&gt; read_memory(reagent x)&quot;)</span>
   if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>name == <span class="Constant">&quot;number-of-locals&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
@@ -184,6 +177,59 @@ if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <
     <span class="Identifier">return</span><span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
 
+<span class="SalientComment">//:: a little hook to automatically reclaim the default-space when returning</span>
+<span class="SalientComment">//:: from a recipe</span>
+
+<span class="Delimiter">:(scenario local_scope)</span>
+recipe main [
+  <span class="Constant">1</span>:address<span class="Special"> &lt;- </span>foo
+  <span class="Constant">2</span>:address<span class="Special"> &lt;- </span>foo
+  <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address<span class="Delimiter">,</span> <span class="Constant">2</span>:address
+]
+recipe foo [
+  local-scope
+  x:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>:literal
+  reply default-space:address:array:location
+]
+<span class="Comment"># both calls to foo should have received the same default-space</span>
+<span class="traceContains">+mem: storing 1 in location 3</span>
+
+<span class="Delimiter">:(after &quot;Falling Through End Of Recipe&quot;)</span>
+try_reclaim_locals<span class="Delimiter">();</span>
+<span class="Delimiter">:(after &quot;Starting Reply&quot;)</span>
+try_reclaim_locals<span class="Delimiter">();</span>
+
+<span class="Comment">//: now 'local-scope' is identical to 'new-default-space' except that we'll</span>
+<span class="Comment">//: reclaim the default-space when the routine exits</span>
+<span class="Delimiter">:(before &quot;End Rewrite Instruction(curr)&quot;)</span>
+if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">&quot;local-scope&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  rewrite_default_space_instruction<span class="Delimiter">(</span>curr<span class="Delimiter">);</span>
+<span class="Delimiter">}</span>
+
+<span class="Delimiter">:(code)</span>
+void try_reclaim_locals<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  <span class="Comment">// only reclaim routines starting with 'local-scope'</span>
+  const recipe_ordinal r = Recipe_ordinal[current_recipe_name<span class="Delimiter">()</span>]<span class="Delimiter">;</span>
+  const instruction&amp; inst = Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
+  if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name != <span class="Constant">&quot;local-scope&quot;</span><span class="Delimiter">)</span>
+    <span class="Identifier">return</span><span class="Delimiter">;</span>
+<span class="CommentedCode">//?   cerr &lt;&lt; inst.to_string() &lt;&lt; '\n'; //? 1</span>
+<span class="CommentedCode">//?   cerr &lt;&lt; current_recipe_name() &lt;&lt; &quot;: abandon &quot; &lt;&lt; Current_routine-&gt;calls.front().default_space &lt;&lt; '\n'; //? 1</span>
+  abandon<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>default_space<span class="Delimiter">,</span>
+          <span class="Comment">/*</span><span class="Comment">array length</span><span class="Comment">*/</span><span class="Constant">1</span>+<span class="Comment">/*</span><span class="Comment">number-of-locals</span><span class="Comment">*/</span>Name[r][<span class="Constant">&quot;&quot;</span>]<span class="Delimiter">);</span>
+<span class="Delimiter">}</span>
+
+void rewrite_default_space_instruction<span class="Delimiter">(</span>instruction&amp; curr<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  curr<span class="Delimiter">.</span>operation = Recipe_ordinal[<span class="Constant">&quot;new&quot;</span>]<span class="Delimiter">;</span>
+  if <span class="Delimiter">(</span>!curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span>
+    raise &lt;&lt; <span class="Constant">&quot;new-default-space can't take any ingredients</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
+  curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;location:type&quot;</span><span class="Delimiter">));</span>
+  curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;number-of-locals:literal&quot;</span><span class="Delimiter">));</span>
+  if <span class="Delimiter">(</span>!curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span>
+    raise &lt;&lt; <span class="Constant">&quot;new-default-space can't take any results</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
+  curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;default-space:address:array:location&quot;</span><span class="Delimiter">));</span>
+<span class="Delimiter">}</span>
+
 <span class="SalientComment">//:: helpers</span>
 
 <span class="Delimiter">:(code)</span>
diff --git a/html/050scenario.cc.html b/html/050scenario.cc.html
index ca947e34..ae2d52b2 100644
--- a/html/050scenario.cc.html
+++ b/html/050scenario.cc.html
@@ -167,7 +167,7 @@ const scenario* Current_scenario = <span class="Constant">NULL</span><span class
 void run_mu_scenario<span class="Delimiter">(</span>const scenario&amp; s<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   Current_scenario = &amp;s<span class="Delimiter">;</span>
   bool not_already_inside_test = !Trace_stream<span class="Delimiter">;</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; s.name &lt;&lt; '\n'; //? 11</span>
+<span class="CommentedCode">//?   cerr &lt;&lt; s.name &lt;&lt; '\n'; //? 12</span>
   if <span class="Delimiter">(</span>not_already_inside_test<span class="Delimiter">)</span> <span class="Delimiter">{</span>
     Trace_file = s<span class="Delimiter">.</span>name<span class="Delimiter">;</span>
     Trace_stream = new trace_stream<span class="Delimiter">;</span>
diff --git a/html/060string.mu.html b/html/060string.mu.html
index eb98cd88..a78e7413 100644
--- a/html/060string.mu.html
+++ b/html/060string.mu.html
@@ -35,7 +35,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <span class="Comment"># Some useful helpers for dealing with strings.</span>
 
 <span class="muRecipe">recipe</span> string-equal [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   a:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   a-len:number<span class="Special"> &lt;- </span>length a:address:array:character/deref
   b:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -138,9 +138,8 @@ container buffer [
 ]
 
 <span class="muRecipe">recipe</span> new-buffer [
-  <span class="Constant">new-default-space</span>
-<span class="CommentedCode">#?   $print default-space:address:array:location, [</span>
-<span class="CommentedCode">#? ]</span>
+  <span class="Constant">local-scope</span>
+<span class="CommentedCode">#?   $print default-space:address:array:location, 10:literal/newline</span>
   result:address:buffer<span class="Special"> &lt;- </span>new buffer:type
   len:address:number<span class="Special"> &lt;- </span>get-address result:address:buffer/deref, length:offset
   len:address:number/deref<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
@@ -148,13 +147,12 @@ container buffer [
   capacity:number, found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   assert found?:boolean, <span class="Constant">[new-buffer must get a capacity argument]</span>
   s:address:address:array:character/deref<span class="Special"> &lt;- </span>new character:type, capacity:number
-<span class="CommentedCode">#?   $print s:address:address:array:character/deref, [</span>
-<span class="CommentedCode">#? ]</span>
+<span class="CommentedCode">#?   $print s:address:address:array:character/deref, 10:literal/newline</span>
   <span class="muControl">reply</span> result:address:buffer
 ]
 
 <span class="muRecipe">recipe</span> grow-buffer [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   in:address:buffer<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># double buffer size</span>
   x:address:address:array:character<span class="Special"> &lt;- </span>get-address in:address:buffer/deref, data:offset
@@ -177,7 +175,7 @@ container buffer [
 ]
 
 <span class="muRecipe">recipe</span> buffer-full? [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   in:address:buffer<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   len:number<span class="Special"> &lt;- </span>get in:address:buffer/deref, length:offset
   s:address:array:character<span class="Special"> &lt;- </span>get in:address:buffer/deref, data:offset
@@ -188,7 +186,7 @@ container buffer [
 
 <span class="Comment"># in:address:buffer &lt;- buffer-append in:address:buffer, c:character</span>
 <span class="muRecipe">recipe</span> buffer-append [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   in:address:buffer<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   len:address:number<span class="Special"> &lt;- </span>get-address in:address:buffer/deref, length:offset
@@ -208,13 +206,10 @@ container buffer [
     in:address:buffer<span class="Special"> &lt;- </span>grow-buffer in:address:buffer
   <span class="Delimiter">}</span>
   s:address:array:character<span class="Special"> &lt;- </span>get in:address:buffer/deref, data:offset
-<span class="CommentedCode">#?   $print [array underlying buf: ], s:address:array:character, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
-<span class="CommentedCode">#?   $print [index: ], len:address:number/deref, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print [array underlying buf: ], s:address:array:character, 10:literal/newline</span>
+<span class="CommentedCode">#?   $print [index: ], len:address:number/deref, 10:literal/newline</span>
   dest:address:character<span class="Special"> &lt;- </span>index-address s:address:array:character/deref, len:address:number/deref
-<span class="CommentedCode">#?   $print [storing ], c:character, [ in ], dest:address:character, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print [storing ], c:character, [ in ], dest:address:character, 10:literal/newline</span>
   dest:address:character/deref<span class="Special"> &lt;- </span>copy c:character
   len:address:number/deref<span class="Special"> &lt;- </span>add len:address:number/deref, <span class="Constant">1:literal</span>
   <span class="muControl">reply</span> in:address:buffer/same-as-ingredient:0
@@ -222,7 +217,7 @@ container buffer [
 
 <span class="muScenario">scenario</span> buffer-append-works [
   run [
-    <span class="Constant">new-default-space</span>
+    <span class="Constant">local-scope</span>
     x:address:buffer<span class="Special"> &lt;- </span>new-buffer <span class="Constant">3:literal</span>
     s1:address:array:character<span class="Special"> &lt;- </span>get x:address:buffer/deref, data:offset
     x:address:buffer<span class="Special"> &lt;- </span>buffer-append x:address:buffer, <span class="Constant">97:literal</span>  <span class="Comment"># 'a'</span>
@@ -230,20 +225,6 @@ container buffer [
     x:address:buffer<span class="Special"> &lt;- </span>buffer-append x:address:buffer, <span class="Constant">99:literal</span>  <span class="Comment"># 'c'</span>
     s2:address:array:character<span class="Special"> &lt;- </span>get x:address:buffer/deref, data:offset
     1:boolean/<span class="Special">raw &lt;- </span>equal s1:address:array:character, s2:address:array:character
-<span class="CommentedCode">#?     $print s2:address:array:character, [</span>
-<span class="CommentedCode">#? ]</span>
-<span class="CommentedCode">#?     $print 1060:number/raw, [</span>
-<span class="CommentedCode">#? ]</span>
-<span class="CommentedCode">#?     $print 1061:number/raw, [</span>
-<span class="CommentedCode">#? ]</span>
-<span class="CommentedCode">#?     $print 1062:number/raw, [</span>
-<span class="CommentedCode">#? ]</span>
-<span class="CommentedCode">#?     $print 1063:number/raw, [</span>
-<span class="CommentedCode">#? ]</span>
-<span class="CommentedCode">#?     $print 1064:number/raw, [</span>
-<span class="CommentedCode">#? ]</span>
-<span class="CommentedCode">#?     $print 1065:number/raw, [</span>
-<span class="CommentedCode">#? ]</span>
     2:array:character/<span class="Special">raw &lt;- </span>copy s2:address:array:character/deref
 <span class="Constant">    +buffer-filled</span>
     x:address:buffer<span class="Special"> &lt;- </span>buffer-append x:address:buffer, <span class="Constant">100:literal</span>  <span class="Comment"># 'd'</span>
@@ -274,7 +255,7 @@ container buffer [
 
 <span class="muScenario">scenario</span> buffer-append-handles-backspace [
   run [
-    <span class="Constant">new-default-space</span>
+    <span class="Constant">local-scope</span>
     x:address:buffer<span class="Special"> &lt;- </span>new-buffer <span class="Constant">3:literal</span>
     x:address:buffer<span class="Special"> &lt;- </span>buffer-append x:address:buffer, <span class="Constant">97:literal</span>  <span class="Comment"># 'a'</span>
     x:address:buffer<span class="Special"> &lt;- </span>buffer-append x:address:buffer, <span class="Constant">98:literal</span>  <span class="Comment"># 'b'</span>
@@ -291,7 +272,7 @@ container buffer [
 
 <span class="Comment"># result:address:array:character &lt;- integer-to-decimal-string n:number</span>
 <span class="muRecipe">recipe</span> integer-to-decimal-string [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   n:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># is it zero?</span>
   <span class="Delimiter">{</span>
@@ -347,7 +328,7 @@ container buffer [
 ]
 
 <span class="muRecipe">recipe</span> buffer-to-array [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   in:address:buffer<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Delimiter">{</span>
     <span class="Comment"># propagate null buffer</span>
@@ -355,8 +336,7 @@ container buffer [
     <span class="muControl">reply</span> <span class="Constant">0:literal</span>
   <span class="Delimiter">}</span>
   len:number<span class="Special"> &lt;- </span>get in:address:buffer/deref, length:offset
-<span class="CommentedCode">#?   $print [size ], len:number, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print [size ], len:number, 10:literal/newline</span>
   s:address:array:character<span class="Special"> &lt;- </span>get in:address:buffer/deref, data:offset
   <span class="Comment"># we can't just return s because it is usually the wrong length</span>
   result:address:array:character<span class="Special"> &lt;- </span>new character:type, len:number
@@ -408,7 +388,7 @@ container buffer [
 
 <span class="Comment"># result:address:array:character &lt;- string-append a:address:array:character, b:address:array:character</span>
 <span class="muRecipe">recipe</span> string-append [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   <span class="Comment"># result = new character[a.length + b.length]</span>
   a:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   a-len:number<span class="Special"> &lt;- </span>length a:address:array:character/deref
@@ -467,7 +447,7 @@ container buffer [
 <span class="Comment"># replace underscores in first with remaining args</span>
 <span class="Comment"># result:address:array:character &lt;- interpolate template:address:array:character, ...</span>
 <span class="muRecipe">recipe</span> interpolate [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   template:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># compute result-len, space to allocate for result</span>
   tem-len:number<span class="Special"> &lt;- </span>length template:address:array:character/deref
@@ -482,8 +462,7 @@ container buffer [
     result-len:number<span class="Special"> &lt;- </span>subtract result-len:number, <span class="Constant">1:literal</span>
     <span class="muControl">loop</span>
   <span class="Delimiter">}</span>
-<span class="CommentedCode">#?   $print tem-len:number, [ ], $result-len:number, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print tem-len:number, [ ], $result-len:number, 10:literal/newline</span>
   rewind-ingredients
   _<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>  <span class="Comment"># skip template</span>
   <span class="Comment"># result = new array:character[result-len]</span>
@@ -592,7 +571,7 @@ container buffer [
 
 <span class="Comment"># result:boolean &lt;- space? c:character</span>
 <span class="muRecipe">recipe</span> space? [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># most common case first</span>
   result:boolean<span class="Special"> &lt;- </span>equal c:character, <span class="Constant">32:literal/space</span>
@@ -657,7 +636,7 @@ container buffer [
 
 <span class="Comment"># result:address:array:character &lt;- trim s:address:array:character</span>
 <span class="muRecipe">recipe</span> trim [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   len:number<span class="Special"> &lt;- </span>length s:address:array:character/deref
   <span class="Comment"># left trim: compute start</span>
@@ -766,7 +745,7 @@ container buffer [
 
 <span class="Comment"># next-index:number &lt;- find-next text:address:array:character, pattern:character</span>
 <span class="muRecipe">recipe</span> find-next [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   text:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   pattern:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   idx:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -866,7 +845,7 @@ container buffer [
 <span class="Comment"># like find-next, but searches for multiple characters</span>
 <span class="Comment"># fairly dumb algorithm</span>
 <span class="muRecipe">recipe</span> find-substring [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   text:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   pattern:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   idx:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -945,7 +924,7 @@ container buffer [
 <span class="Comment"># result:boolean &lt;- match-at text:address:array:character, pattern:address:array:character, idx:number</span>
 <span class="Comment"># checks if substring matches at index 'idx'</span>
 <span class="muRecipe">recipe</span> match-at [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   text:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   pattern:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   idx:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -1076,7 +1055,7 @@ container buffer [
 
 <span class="Comment"># result:address:array:address:array:character &lt;- split s:address:array:character, delim:character</span>
 <span class="muRecipe">recipe</span> split [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   delim:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># empty string? return empty array</span>
@@ -1206,7 +1185,7 @@ container buffer [
 
 <span class="Comment"># x:address:array:character, y:address:array:character &lt;- split-first text:address:array:character, delim:character</span>
 <span class="muRecipe">recipe</span> split-first [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   text:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   delim:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># empty string? return empty strings</span>
@@ -1241,7 +1220,7 @@ container buffer [
 <span class="Comment"># result:address:array:character &lt;- string-copy buf:address:array:character, start:number, end:number</span>
 <span class="Comment"># todo: make this generic</span>
 <span class="muRecipe">recipe</span> string-copy [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   buf:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   start:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   end:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -1301,7 +1280,7 @@ container buffer [
 ]
 
 <span class="muRecipe">recipe</span> min [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   y:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Delimiter">{</span>
@@ -1313,7 +1292,7 @@ container buffer [
 ]
 
 <span class="muRecipe">recipe</span> max [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   y:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Delimiter">{</span>
diff --git a/html/061channel.mu.html b/html/061channel.mu.html
index d1fc9b9b..73a39542 100644
--- a/html/061channel.mu.html
+++ b/html/061channel.mu.html
@@ -68,7 +68,7 @@ container channel [
 
 <span class="Comment"># result:address:channel &lt;- new-channel capacity:number</span>
 <span class="muRecipe">recipe</span> new-channel [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   <span class="Comment"># result = new channel</span>
   result:address:channel<span class="Special"> &lt;- </span>new channel:type
   <span class="Comment"># result.first-full = 0</span>
@@ -87,7 +87,7 @@ container channel [
 
 <span class="Comment"># chan:address:channel &lt;- write chan:address:channel, val:location</span>
 <span class="muRecipe">recipe</span> write [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   val:location<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Delimiter">{</span>
@@ -116,7 +116,7 @@ container channel [
 
 <span class="Comment"># result:location, chan:address:channel &lt;- read chan:address:channel</span>
 <span class="muRecipe">recipe</span> read [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Delimiter">{</span>
     <span class="Comment"># block if chan is empty</span>
@@ -142,7 +142,7 @@ container channel [
 ]
 
 <span class="muRecipe">recipe</span> clear-channel [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Delimiter">{</span>
     empty?:boolean<span class="Special"> &lt;- </span>channel-empty? chan:address:channel
@@ -220,7 +220,7 @@ container channel [
 
 <span class="Comment"># An empty channel has first-empty and first-full both at the same value.</span>
 <span class="muRecipe">recipe</span> channel-empty? [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># return chan.first-full == chan.first-free</span>
   full:number<span class="Special"> &lt;- </span>get chan:address:channel/deref, first-full:offset
@@ -232,7 +232,7 @@ container channel [
 <span class="Comment"># A full channel has first-empty just before first-full, wasting one slot.</span>
 <span class="Comment"># (Other alternatives: <a href="https://en.wikipedia.org/wiki/Circular_buffer#Full_.2F_Empty_Buffer_Distinction)">https://en.wikipedia.org/wiki/Circular_buffer#Full_.2F_Empty_Buffer_Distinction)</a></span>
 <span class="muRecipe">recipe</span> channel-full? [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># tmp = chan.first-free + 1</span>
   tmp:number<span class="Special"> &lt;- </span>get chan:address:channel/deref, first-free:offset
@@ -252,7 +252,7 @@ container channel [
 
 <span class="Comment"># result:number &lt;- channel-capacity chan:address:channel</span>
 <span class="muRecipe">recipe</span> channel-capacity [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   q:address:array:location<span class="Special"> &lt;- </span>get chan:address:channel/deref, data:offset
   result:number<span class="Special"> &lt;- </span>length q:address:array:location/deref
@@ -314,7 +314,7 @@ container channel [
 <span class="Comment"># helper for channels of characters in particular</span>
 <span class="Comment"># out:address:channel &lt;- buffer-lines in:address:channel, out:address:channel</span>
 <span class="muRecipe">recipe</span> buffer-lines [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
 <span class="CommentedCode">#?   $print [buffer-lines: aaa</span>
 <span class="CommentedCode">#? ]</span>
   in:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -333,25 +333,22 @@ container channel [
         <span class="muControl">break-unless</span> backspace?:boolean
         <span class="Comment"># drop previous character</span>
 <span class="CommentedCode">#?         close-console #? 2</span>
-<span class="CommentedCode">#?         $print [backspace! #? 1</span>
+<span class="CommentedCode">#?         $print [backspace!</span>
 <span class="CommentedCode">#? ] #? 1</span>
         <span class="Delimiter">{</span>
           buffer-length:address:number<span class="Special"> &lt;- </span>get-address line:address:buffer/deref, length:offset
           buffer-empty?:boolean<span class="Special"> &lt;- </span>equal buffer-length:address:number/deref, <span class="Constant">0:literal</span>
           <span class="muControl">break-if</span> buffer-empty?:boolean
-<span class="CommentedCode">#?           $print [before: ], buffer-length:address:number/deref, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?           $print [before: ], buffer-length:address:number/deref, 10:literal/newline</span>
           buffer-length:address:number/deref<span class="Special"> &lt;- </span>subtract buffer-length:address:number/deref, <span class="Constant">1:literal</span>
-<span class="CommentedCode">#?           $print [after: ], buffer-length:address:number/deref, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?           $print [after: ], buffer-length:address:number/deref, 10:literal/newline</span>
         <span class="Delimiter">}</span>
 <span class="CommentedCode">#?         $exit #? 2</span>
         <span class="Comment"># and don't append this one</span>
         <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
       <span class="Delimiter">}</span>
       <span class="Comment"># append anything else</span>
-<span class="CommentedCode">#?       $print [buffer-lines: appending ], c:character, [ </span>
-<span class="CommentedCode">#? ]</span>
+<span class="CommentedCode">#?       $print [buffer-lines: appending ], c:character, 10:literal/newline</span>
       line:address:buffer<span class="Special"> &lt;- </span>buffer-append line:address:buffer, c:character
       line-done?:boolean<span class="Special"> &lt;- </span>equal c:character, <span class="Constant">10:literal/newline</span>
       <span class="muControl">break-if</span> line-done?:boolean
@@ -372,8 +369,7 @@ container channel [
       <span class="muControl">break-if</span> done?:boolean
       c:character<span class="Special"> &lt;- </span>index line-contents:address:array:character/deref, i:number
       out:address:channel<span class="Special"> &lt;- </span>write out:address:channel, c:character
-<span class="CommentedCode">#?       $print [writing ], i:number, [: ], c:character, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?       $print [writing ], i:number, [: ], c:character, 10:literal/newline</span>
       i:number<span class="Special"> &lt;- </span>add i:number, <span class="Constant">1:literal</span>
       <span class="muControl">loop</span>
     <span class="Delimiter">}</span>
diff --git a/html/062array.mu.html b/html/062array.mu.html
index 0388b603..52c24343 100644
--- a/html/062array.mu.html
+++ b/html/062array.mu.html
@@ -46,7 +46,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 
 <span class="Comment"># create an array out of a list of scalar args</span>
 <span class="muRecipe">recipe</span> new-array [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   capacity:number<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
   <span class="Delimiter">{</span>
     <span class="Comment"># while read curr-value</span>
diff --git a/html/063list.mu.html b/html/063list.mu.html
index d805f6ed..0926bd94 100644
--- a/html/063list.mu.html
+++ b/html/063list.mu.html
@@ -43,7 +43,7 @@ container list [
 
 <span class="Comment"># result:address:list &lt;- push x:location, in:address:list</span>
 <span class="muRecipe">recipe</span> push [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:location<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   in:address:list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   result:address:list<span class="Special"> &lt;- </span>new list:type
@@ -56,7 +56,7 @@ container list [
 
 <span class="Comment"># result:location &lt;- first in:address:list</span>
 <span class="muRecipe">recipe</span> first [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   in:address:list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   result:location<span class="Special"> &lt;- </span>get in:address:list/deref, value:offset
   <span class="muControl">reply</span> result:location
@@ -64,7 +64,7 @@ container list [
 
 <span class="Comment"># result:address:list &lt;- rest in:address:list</span>
 <span class="muRecipe">recipe</span> rest [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   in:address:list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   result:address:list<span class="Special"> &lt;- </span>get in:address:list/deref, next:offset
   <span class="muControl">reply</span> result:address:list
diff --git a/html/065duplex_list.mu.html b/html/065duplex_list.mu.html
index 4f892745..cbf6492e 100644
--- a/html/065duplex_list.mu.html
+++ b/html/065duplex_list.mu.html
@@ -42,7 +42,7 @@ container duplex-list [
 
 <span class="Comment"># result:address:duplex-list &lt;- push-duplex x:location, in:address:duplex-list</span>
 <span class="muRecipe">recipe</span> push-duplex [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:location<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   result:address:duplex-list<span class="Special"> &lt;- </span>new duplex-list:type
@@ -58,7 +58,7 @@ container duplex-list [
 
 <span class="Comment"># result:location &lt;- first-duplex in:address:duplex-list</span>
 <span class="muRecipe">recipe</span> first-duplex [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="muControl">reply-unless</span> in:address:duplex-list, <span class="Constant">0:literal</span>
   result:location<span class="Special"> &lt;- </span>get in:address:duplex-list/deref, value:offset
@@ -67,7 +67,7 @@ container duplex-list [
 
 <span class="Comment"># result:address:duplex-list &lt;- next-duplex in:address:duplex-list</span>
 <span class="muRecipe">recipe</span> next-duplex [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="muControl">reply-unless</span> in:address:duplex-list, <span class="Constant">0:literal</span>
   result:address:duplex-list<span class="Special"> &lt;- </span>get in:address:duplex-list/deref, next:offset
@@ -76,7 +76,7 @@ container duplex-list [
 
 <span class="Comment"># result:address:duplex-list &lt;- prev-duplex in:address:duplex-list</span>
 <span class="muRecipe">recipe</span> prev-duplex [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="muControl">reply-unless</span> in:address:duplex-list, <span class="Constant">0:literal</span>
   result:address:duplex-list<span class="Special"> &lt;- </span>get in:address:duplex-list/deref, prev:offset
@@ -129,7 +129,7 @@ container duplex-list [
 <span class="Comment"># l:address:duplex-list &lt;- insert-duplex x:location, in:address:duplex-list</span>
 <span class="Comment"># Inserts 'x' after 'in'. Returns some pointer into the list.</span>
 <span class="muRecipe">recipe</span> insert-duplex [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:location<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   new-node:address:duplex-list<span class="Special"> &lt;- </span>new duplex-list:type
@@ -271,7 +271,7 @@ container duplex-list [
 <span class="Comment"># Returns null if and only if list is empty. Beware: in that case any pointers</span>
 <span class="Comment"># to the head are now invalid.</span>
 <span class="muRecipe">recipe</span> remove-duplex [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if 'in' is null, return</span>
   <span class="muControl">reply-unless</span> in:address:duplex-list, in:address:duplex-list
diff --git a/html/066stream.mu.html b/html/066stream.mu.html
index 2e899c6c..44a3b3ac 100644
--- a/html/066stream.mu.html
+++ b/html/066stream.mu.html
@@ -36,7 +36,7 @@ container stream [
 ]
 
 <span class="muRecipe">recipe</span> new-stream [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   result:address:stream<span class="Special"> &lt;- </span>new stream:type
   i:address:number<span class="Special"> &lt;- </span>get-address result:address:stream/deref, index:offset
   i:address:number/deref<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
@@ -46,7 +46,7 @@ container stream [
 ]
 
 <span class="muRecipe">recipe</span> rewind-stream [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   in:address:stream<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   x:address:number<span class="Special"> &lt;- </span>get-address in:address:stream/deref, index:offset
   x:address:number/deref<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
@@ -54,7 +54,7 @@ container stream [
 ]
 
 <span class="muRecipe">recipe</span> read-line [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   in:address:stream<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   idx:address:number<span class="Special"> &lt;- </span>get-address in:address:stream/deref, index:offset
   s:address:array:character<span class="Special"> &lt;- </span>get in:address:stream/deref, data:offset
@@ -65,7 +65,7 @@ container stream [
 ]
 
 <span class="muRecipe">recipe</span> end-of-stream? [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   in:address:stream<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   idx:number<span class="Special"> &lt;- </span>get in:address:stream/deref, index:offset
   s:address:array:character<span class="Special"> &lt;- </span>get in:address:stream/deref, data:offset
diff --git a/html/071print.mu.html b/html/071print.mu.html
index 43461cc5..b70e75c9 100644
--- a/html/071print.mu.html
+++ b/html/071print.mu.html
@@ -49,14 +49,13 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> new-fake-screen [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   result:address:screen<span class="Special"> &lt;- </span>new screen:type
   width:address:number<span class="Special"> &lt;- </span>get-address result:address:screen/deref, num-columns:offset
   width:address:number/deref<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   height:address:number<span class="Special"> &lt;- </span>get-address result:address:screen/deref, num-rows:offset
   height:address:number/deref<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-<span class="CommentedCode">#?   $print height:address:number/deref, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print height:address:number/deref, 10:literal/newline</span>
   row:address:number<span class="Special"> &lt;- </span>get-address result:address:screen/deref, cursor-row:offset
   row:address:number/deref<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
   column:address:number<span class="Special"> &lt;- </span>get-address result:address:screen/deref, cursor-column:offset
@@ -69,7 +68,7 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> clear-screen [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
 <span class="CommentedCode">#?   $print [clearing screen</span>
 <span class="CommentedCode">#? ] #? 1</span>
@@ -103,8 +102,28 @@ container screen-cell [
   <span class="muControl">reply</span> x:address:screen/same-as-ingredient:0
 ]
 
+<span class="muRecipe">recipe</span> fake-screen-is-clear? [
+  <span class="Constant">local-scope</span>
+  screen:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply-unless</span> screen:address:screen, <span class="Constant">1:literal/true</span>
+  buf:address:array:screen-cell<span class="Special"> &lt;- </span>get screen:address:screen/deref, data:offset
+  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
+  len:number<span class="Special"> &lt;- </span>length buf:address:array:screen-cell/deref
+  <span class="Delimiter">{</span>
+    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i:number, len:number
+    <span class="muControl">break-if</span> done?:boolean
+    curr:screen-cell<span class="Special"> &lt;- </span>index buf:address:array:screen-cell/deref, i:number
+    curr-contents:character<span class="Special"> &lt;- </span>get curr:screen-cell, contents:offset
+    i:number<span class="Special"> &lt;- </span>add i:number, <span class="Constant">1:literal</span>
+    <span class="muControl">loop-unless</span> curr-contents:character
+    <span class="Comment"># not 0</span>
+    <span class="muControl">reply</span> <span class="Constant">0:literal/false</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> <span class="Constant">1:literal/true</span>
+]
+
 <span class="muRecipe">recipe</span> print-character [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -124,15 +143,23 @@ container screen-cell [
     <span class="Comment"># if x exists</span>
     <span class="Comment"># (handle special cases exactly like in the real screen)</span>
     <span class="muControl">break-unless</span> x:address:screen
-    row:address:number<span class="Special"> &lt;- </span>get-address x:address:screen/deref, cursor-row:offset
-    column:address:number<span class="Special"> &lt;- </span>get-address x:address:screen/deref, cursor-column:offset
     width:number<span class="Special"> &lt;- </span>get x:address:screen/deref, num-columns:offset
     height:number<span class="Special"> &lt;- </span>get x:address:screen/deref, num-rows:offset
+    <span class="Comment"># if cursor is out of bounds, silently exit</span>
+    row:address:number<span class="Special"> &lt;- </span>get-address x:address:screen/deref, cursor-row:offset
+    legal?:boolean<span class="Special"> &lt;- </span>greater-or-equal row:address:number/deref, <span class="Constant">0:literal</span>
+    <span class="muControl">reply-unless</span> legal?:boolean, x:address:screen
+    legal?:boolean<span class="Special"> &lt;- </span>lesser-than row:address:number/deref, height:number
+    <span class="muControl">reply-unless</span> legal?:boolean, x:address:screen
+    column:address:number<span class="Special"> &lt;- </span>get-address x:address:screen/deref, cursor-column:offset
+    legal?:boolean<span class="Special"> &lt;- </span>greater-or-equal column:address:number/deref, <span class="Constant">0:literal</span>
+    <span class="muControl">reply-unless</span> legal?:boolean, x:address:screen
+    legal?:boolean<span class="Special"> &lt;- </span>lesser-than column:address:number/deref, width:number
+    <span class="muControl">reply-unless</span> legal?:boolean, x:address:screen
     <span class="Comment"># special-case: newline</span>
     <span class="Delimiter">{</span>
       newline?:boolean<span class="Special"> &lt;- </span>equal c:character, <span class="Constant">10:literal/newline</span>
-<span class="CommentedCode">#?       $print c:character, [ ], newline?:boolean, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?       $print c:character, [ ], newline?:boolean, 10:literal/newline</span>
       <span class="muControl">break-unless</span> newline?:boolean
       <span class="Delimiter">{</span>
         <span class="Comment"># unless cursor is already at bottom</span>
@@ -146,11 +173,10 @@ container screen-cell [
       <span class="muControl">reply</span> x:address:screen/same-as-ingredient:0
     <span class="Delimiter">}</span>
     <span class="Comment"># save character in fake screen</span>
-<span class="CommentedCode">#?     $print row:address:number/deref, [, ], column:address:number/deref, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
     index:number<span class="Special"> &lt;- </span>multiply row:address:number/deref, width:number
     index:number<span class="Special"> &lt;- </span>add index:number, column:address:number/deref
     buf:address:array:screen-cell<span class="Special"> &lt;- </span>get x:address:screen/deref, data:offset
+    len:number<span class="Special"> &lt;- </span>length buf:address:array:screen-cell/deref
     <span class="Comment"># special-case: backspace</span>
     <span class="Delimiter">{</span>
       backspace?:boolean<span class="Special"> &lt;- </span>equal c:character, <span class="Constant">8:literal</span>
@@ -170,8 +196,7 @@ container screen-cell [
       <span class="Delimiter">}</span>
       <span class="muControl">reply</span> x:address:screen/same-as-ingredient:0
     <span class="Delimiter">}</span>
-<span class="CommentedCode">#?     $print [saving character ], c:character, [ to fake screen ], cursor:address/screen, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?     $print [saving character ], c:character, [ to fake screen ], cursor:address/screen, 10:literal/newline</span>
     cursor:address:screen-cell<span class="Special"> &lt;- </span>index-address buf:address:array:screen-cell/deref, index:number
     cursor-contents:address:character<span class="Special"> &lt;- </span>get-address cursor:address:screen-cell/deref, contents:offset
     cursor-color:address:number<span class="Special"> &lt;- </span>get-address cursor:address:screen-cell/deref, color:offset
@@ -348,7 +373,7 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> clear-line [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, clear line in fake screen</span>
   <span class="Delimiter">{</span>
@@ -359,8 +384,7 @@ container screen-cell [
     <span class="Comment"># space over the entire line</span>
 <span class="CommentedCode">#?     $start-tracing #? 1</span>
     <span class="Delimiter">{</span>
-<span class="CommentedCode">#?       $print column:address:number/deref, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?       $print column:address:number/deref, 10:literal/newline</span>
       right:number<span class="Special"> &lt;- </span>subtract width:number, <span class="Constant">1:literal</span>
       done?:boolean<span class="Special"> &lt;- </span>greater-or-equal column:address:number/deref, right:number
       <span class="muControl">break-if</span> done?:boolean
@@ -377,7 +401,7 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> cursor-position [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, lookup cursor in fake screen</span>
   <span class="Delimiter">{</span>
@@ -391,7 +415,7 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> move-cursor [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   new-row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   new-column:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -441,23 +465,22 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> cursor-down [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, move cursor in fake screen</span>
   <span class="Delimiter">{</span>
     <span class="muControl">break-unless</span> x:address:screen
     <span class="Delimiter">{</span>
-      <span class="Comment"># if row &lt; height</span>
+      <span class="Comment"># if row &lt; height-1</span>
       height:number<span class="Special"> &lt;- </span>get x:address:screen/deref, num-rows:offset
       row:address:number<span class="Special"> &lt;- </span>get-address x:address:screen/deref, cursor-row:offset
-      at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal row:address:number/deref, height:number
+      max:number<span class="Special"> &lt;- </span>subtract height:number, <span class="Constant">1:literal</span>
+      at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal row:address:number/deref, max:number
       <span class="muControl">break-if</span> at-bottom?:boolean
       <span class="Comment"># row = row+1</span>
-<span class="CommentedCode">#?       $print [AAA: ], row:address:number, [ -&gt; ], row:address:number/deref, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?       $print [AAA: ], row:address:number, [ -&gt; ], row:address:number/deref, 10:literal/newline</span>
       row:address:number/deref<span class="Special"> &lt;- </span>add row:address:number/deref, <span class="Constant">1:literal</span>
-<span class="CommentedCode">#?       $print [BBB: ], row:address:number, [ -&gt; ], row:address:number/deref, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?       $print [BBB: ], row:address:number, [ -&gt; ], row:address:number/deref, 10:literal/newline</span>
 <span class="CommentedCode">#?       $start-tracing #? 1</span>
     <span class="Delimiter">}</span>
     <span class="muControl">reply</span> x:address:screen/same-as-ingredient:0
@@ -468,15 +491,15 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> cursor-up [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, move cursor in fake screen</span>
   <span class="Delimiter">{</span>
     <span class="muControl">break-unless</span> x:address:screen
     <span class="Delimiter">{</span>
-      <span class="Comment"># if row &gt;= 0</span>
+      <span class="Comment"># if row &gt; 0</span>
       row:address:number<span class="Special"> &lt;- </span>get-address x:address:screen/deref, cursor-row:offset
-      at-top?:boolean<span class="Special"> &lt;- </span>lesser-than row:address:number/deref, <span class="Constant">0:literal</span>
+      at-top?:boolean<span class="Special"> &lt;- </span>lesser-or-equal row:address:number/deref, <span class="Constant">0:literal</span>
       <span class="muControl">break-if</span> at-top?:boolean
       <span class="Comment"># row = row-1</span>
       row:address:number/deref<span class="Special"> &lt;- </span>subtract row:address:number/deref, <span class="Constant">1:literal</span>
@@ -489,16 +512,17 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> cursor-right [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, move cursor in fake screen</span>
   <span class="Delimiter">{</span>
     <span class="muControl">break-unless</span> x:address:screen
     <span class="Delimiter">{</span>
-      <span class="Comment"># if column &lt; width</span>
+      <span class="Comment"># if column &lt; width-1</span>
       width:number<span class="Special"> &lt;- </span>get x:address:screen/deref, num-columns:offset
       column:address:number<span class="Special"> &lt;- </span>get-address x:address:screen/deref, cursor-column:offset
-      at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal column:address:number/deref, width:number
+      max:number<span class="Special"> &lt;- </span>subtract width:number, <span class="Constant">1:literal</span>
+      at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal column:address:number/deref, max:number
       <span class="muControl">break-if</span> at-bottom?:boolean
       <span class="Comment"># column = column+1</span>
       column:address:number/deref<span class="Special"> &lt;- </span>add column:address:number/deref, <span class="Constant">1:literal</span>
@@ -511,15 +535,15 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> cursor-left [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, move cursor in fake screen</span>
   <span class="Delimiter">{</span>
     <span class="muControl">break-unless</span> x:address:screen
     <span class="Delimiter">{</span>
-      <span class="Comment"># if column &gt;= 0</span>
+      <span class="Comment"># if column &gt; 0</span>
       column:address:number<span class="Special"> &lt;- </span>get-address x:address:screen/deref, cursor-column:offset
-      at-top?:boolean<span class="Special"> &lt;- </span>lesser-than column:address:number/deref, <span class="Constant">0:literal</span>
+      at-top?:boolean<span class="Special"> &lt;- </span>lesser-or-equal column:address:number/deref, <span class="Constant">0:literal</span>
       <span class="muControl">break-if</span> at-top?:boolean
       <span class="Comment"># column = column-1</span>
       column:address:number/deref<span class="Special"> &lt;- </span>subtract column:address:number/deref, <span class="Constant">1:literal</span>
@@ -532,7 +556,7 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> cursor-to-start-of-line [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   row:number, _, x:address:screen<span class="Special"> &lt;- </span>cursor-position x:address:screen
   column:number<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
@@ -541,7 +565,7 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> cursor-to-next-line [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   x:address:screen<span class="Special"> &lt;- </span>cursor-down x:address:screen
   x:address:screen<span class="Special"> &lt;- </span>cursor-to-start-of-line x:address:screen
@@ -549,7 +573,7 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> screen-width [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, move cursor in fake screen</span>
   <span class="Delimiter">{</span>
@@ -563,7 +587,7 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> screen-height [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, move cursor in fake screen</span>
   <span class="Delimiter">{</span>
@@ -577,7 +601,7 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> hide-cursor [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists (not real display), do nothing</span>
   <span class="Delimiter">{</span>
@@ -590,7 +614,7 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> show-cursor [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists (not real display), do nothing</span>
   <span class="Delimiter">{</span>
@@ -603,7 +627,7 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> hide-screen [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists (not real display), do nothing</span>
   <span class="Delimiter">{</span>
@@ -616,7 +640,7 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> show-screen [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists (not real display), do nothing</span>
   <span class="Delimiter">{</span>
@@ -629,7 +653,7 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> print-string [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -678,7 +702,7 @@ container screen-cell [
 ]
 
 <span class="muRecipe">recipe</span> print-integer [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   n:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
diff --git a/html/074console.mu.html b/html/074console.mu.html
index 594f28c2..2b60d6f6 100644
--- a/html/074console.mu.html
+++ b/html/074console.mu.html
@@ -53,7 +53,7 @@ container console [
 ]
 
 <span class="muRecipe">recipe</span> new-fake-console [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   result:address:console<span class="Special"> &lt;- </span>new console:type
   buf:address:address:array:character<span class="Special"> &lt;- </span>get-address result:address:console/deref, data:offset
 <span class="CommentedCode">#?   $start-tracing #? 1</span>
@@ -65,7 +65,7 @@ container console [
 ]
 
 <span class="muRecipe">recipe</span> read-event [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:console<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Delimiter">{</span>
     <span class="muControl">break-unless</span> x:address:console
@@ -92,7 +92,7 @@ container console [
 <span class="Comment"># isn't unicode, so no arrow keys, page-up/page-down, etc. But you still get</span>
 <span class="Comment"># newlines, tabs, ctrl-d..</span>
 <span class="muRecipe">recipe</span> read-key [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
 <span class="CommentedCode">#?   $print default-space:address:array:location #? 1</span>
 <span class="CommentedCode">#?   $exit #? 1</span>
 <span class="CommentedCode">#?   $start-tracing #? 1</span>
@@ -110,7 +110,7 @@ container console [
 ]
 
 <span class="muRecipe">recipe</span> send-keys-to-channel [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -126,7 +126,7 @@ container console [
 ]
 
 <span class="muRecipe">recipe</span> wait-for-event [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Delimiter">{</span>
     _, console:address, found?:boolean<span class="Special"> &lt;- </span>read-event console:address
@@ -136,7 +136,7 @@ container console [
 
 <span class="Comment"># use this helper to skip rendering if there's lots of other events queued up</span>
 <span class="muRecipe">recipe</span> has-more-events? [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Delimiter">{</span>
     <span class="muControl">break-unless</span> console:address
diff --git a/html/081run_interactive.cc.html b/html/081run_interactive.cc.html
index 5183cee6..54b1456c 100644
--- a/html/081run_interactive.cc.html
+++ b/html/081run_interactive.cc.html
@@ -49,8 +49,10 @@ recipe main [
 <span class="Comment"># result is null</span>
 <span class="traceContains">+mem: storing 0 in location 1</span>
 
-<span class="Comment">//: run code in 'interactive mode', i.e. with warnings off, and recording</span>
-<span class="Comment">//: output in case we want to print it to screen</span>
+<span class="Comment">//: run code in 'interactive mode', i.e. with warnings off and return:</span>
+<span class="Comment">//:   stringified output in case we want to print it to screen</span>
+<span class="Comment">//:   any warnings encountered</span>
+<span class="Comment">//:   simulated screen any prints went to</span>
 <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
 RUN_INTERACTIVE<span class="Delimiter">,</span>
 <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
@@ -59,11 +61,13 @@ Recipe_ordinal[<span class="Constant">&quot;run-interactive&quot;</span>] = RUN_
 <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
 case RUN_INTERACTIVE: <span class="Delimiter">{</span>
   assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)));</span>
-  products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span>
+  products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">3</span><span class="Delimiter">);</span>
   bool new_code_pushed_to_stack = run_interactive<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span>
   if <span class="Delimiter">(</span>!new_code_pushed_to_stack<span class="Delimiter">)</span> <span class="Delimiter">{</span>
     products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
     products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>warnings_from_trace<span class="Delimiter">());</span>
+    products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
+    clean_up_interactive<span class="Delimiter">();</span>
     <span class="Identifier">break</span><span class="Delimiter">;</span>  <span class="Comment">// done with this instruction</span>
   <span class="Delimiter">}</span>
   else <span class="Delimiter">{</span>
@@ -73,49 +77,53 @@ case RUN_INTERACTIVE: <span class="Delimiter">{</span>
 
 <span class="Delimiter">:(before &quot;End Globals&quot;)</span>
 bool Running_interactive = <span class="Constant">false</span><span class="Delimiter">;</span>
+long long int Old_screen = <span class="Constant">0</span><span class="Delimiter">;</span>  <span class="Comment">// we can support one iteration of screen inside screen</span>
 <span class="Delimiter">:(before &quot;End Setup&quot;)</span>
 Running_interactive = <span class="Constant">false</span><span class="Delimiter">;</span>
+Old_screen = <span class="Constant">0</span><span class="Delimiter">;</span>
 <span class="Delimiter">:(code)</span>
-<span class="Comment">// reads a string, tries to call it as code, saving all warnings.</span>
+<span class="Comment">// reads a string, tries to call it as code (treating it as a test), saving</span>
+<span class="Comment">// all warnings.</span>
 <span class="Comment">// returns true if successfully called (no errors found during load and transform)</span>
 bool run_interactive<span class="Delimiter">(</span>long long int address<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   if <span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;interactive&quot;</span><span class="Delimiter">)</span> == Recipe_ordinal<span class="Delimiter">.</span>end<span class="Delimiter">())</span>
     Recipe_ordinal[<span class="Constant">&quot;interactive&quot;</span>] = Next_recipe_ordinal++<span class="Delimiter">;</span>
+  Old_screen = Memory[SCREEN]<span class="Delimiter">;</span>
+<span class="CommentedCode">//?   cerr &lt;&lt; &quot;save screen: &quot; &lt;&lt; Old_screen &lt;&lt; '\n'; //? 2</span>
+  <span class="Comment">// try to sandbox the run as best you can</span>
+  <span class="Comment">// todo: test this</span>
+  if <span class="Delimiter">(</span>!Current_scenario<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    <span class="Comment">// not already sandboxed</span>
+    for <span class="Delimiter">(</span>long long int i = <span class="Constant">1</span><span class="Delimiter">;</span> i &lt; Reserved_for_tests<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span>
+      Memory<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>i<span class="Delimiter">);</span>
+    Name[Recipe_ordinal[<span class="Constant">&quot;interactive&quot;</span>]]<span class="Delimiter">.</span>clear<span class="Delimiter">();</span>
+  <span class="Delimiter">}</span>
+<span class="CommentedCode">//?   cerr &lt;&lt; &quot;screen was at &quot; &lt;&lt; Name[Recipe_ordinal[&quot;interactive&quot;]][&quot;screen&quot;] &lt;&lt; '\n'; //? 1</span>
+  Name[Recipe_ordinal[<span class="Constant">&quot;interactive&quot;</span>]][<span class="Constant">&quot;screen&quot;</span>] = SCREEN<span class="Delimiter">;</span>
+<span class="CommentedCode">//?   cerr &lt;&lt; &quot;screen now at &quot; &lt;&lt; Name[Recipe_ordinal[&quot;interactive&quot;]][&quot;screen&quot;] &lt;&lt; '\n'; //? 1</span>
   string command = trim<span class="Delimiter">(</span>strip_comments<span class="Delimiter">(</span>to_string<span class="Delimiter">(</span>address<span class="Delimiter">)));</span>
   if <span class="Delimiter">(</span>command<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
-<span class="CommentedCode">//?   tb_shutdown(); //? 1</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; command &lt;&lt; '\n'; //? 2</span>
   Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Recipe_ordinal[<span class="Constant">&quot;interactive&quot;</span>]<span class="Delimiter">);</span>
   Hide_warnings = <span class="Constant">true</span><span class="Delimiter">;</span>
   if <span class="Delimiter">(</span>!Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span>
     Trace_file = <span class="Constant">&quot;&quot;</span><span class="Delimiter">;</span>  <span class="Comment">// if there wasn't already a stream we don't want to save it</span>
     Trace_stream = new trace_stream<span class="Delimiter">;</span>
+    Trace_stream<span class="Delimiter">-&gt;</span>collect_layer = <span class="Constant">&quot;warn&quot;</span><span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
   <span class="Comment">// call run(string) but without the scheduling</span>
-  load<span class="Delimiter">(</span><span class="Constant">&quot;recipe interactive [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span>+command+<span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span>
+  <span class="Comment">// we won't create a local scope so that we can get to the new screen after</span>
+  <span class="Comment">// we return from 'interactive'.</span>
+  load<span class="Delimiter">(</span>string<span class="Delimiter">(</span><span class="Constant">&quot;recipe interactive [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">)</span> +
+          <span class="Constant">&quot;screen:address &lt;- new-fake-screen 5, 5</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> +
+          command + <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> +
+       <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span>
   transform_all<span class="Delimiter">();</span>
-  if <span class="Delimiter">(</span>trace_count<span class="Delimiter">(</span><span class="Constant">&quot;warn&quot;</span><span class="Delimiter">)</span> &gt; <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    Hide_warnings = <span class="Constant">false</span><span class="Delimiter">;</span>
-    <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
-  <span class="Delimiter">}</span>
+  if <span class="Delimiter">(</span>trace_count<span class="Delimiter">(</span><span class="Constant">&quot;warn&quot;</span><span class="Delimiter">)</span> &gt; <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
   Running_interactive = <span class="Constant">true</span><span class="Delimiter">;</span>
   Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>push_front<span class="Delimiter">(</span>call<span class="Delimiter">(</span>Recipe_ordinal[<span class="Constant">&quot;interactive&quot;</span>]<span class="Delimiter">));</span>
   <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
-<span class="Delimiter">:(after &quot;Starting Reply&quot;)</span>
-if <span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">()</span> == <span class="Constant">&quot;interactive&quot;</span><span class="Delimiter">)</span> clean_up_interactive<span class="Delimiter">();</span>
-<span class="Delimiter">:(after &quot;Falling Through End Of Recipe&quot;)</span>
-if <span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">()</span> == <span class="Constant">&quot;interactive&quot;</span><span class="Delimiter">)</span> clean_up_interactive<span class="Delimiter">();</span>
-<span class="Delimiter">:(code)</span>
-void clean_up_interactive<span class="Delimiter">()</span> <span class="Delimiter">{</span>
-<span class="CommentedCode">//?   static int foo = 0; //? 1</span>
-  Hide_warnings = <span class="Constant">false</span><span class="Delimiter">;</span>
-  Running_interactive = <span class="Constant">false</span><span class="Delimiter">;</span>
-<span class="CommentedCode">//?   ++foo; //? 1</span>
-<span class="CommentedCode">//?   if (foo == 1) tb_init(); //? 1</span>
-<span class="Delimiter">}</span>
-
 <span class="Delimiter">:(scenario &quot;run_interactive_returns_stringified_result&quot;)</span>
 recipe main [
   <span class="Comment"># try to interactively add 2 and 2</span>
@@ -165,42 +173,65 @@ if <span class="Delimiter">(</span>Running_interactive<span class="Delimiter">)<
 <span class="Delimiter">:(code)</span>
 void record_products<span class="Delimiter">(</span>const instruction&amp; instruction<span class="Delimiter">,</span> const vector&lt;vector&lt;double&gt; &gt;&amp; products<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   ostringstream out<span class="Delimiter">;</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; current_instruction().to_string() &lt;&lt; '\n'; //? 1</span>
   for <span class="Delimiter">(</span>long long int 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>
     if <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="CommentedCode">//?       cerr &lt;&lt; &quot;AA\n&quot;; //? 1</span>
-<span class="CommentedCode">//?       cerr &lt;&lt; instruction.products.size() &lt;&lt; &quot; vs &quot; &lt;&lt; i &lt;&lt; '\n'; //? 1</span>
       if <span class="Delimiter">(</span>is_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="CommentedCode">//?         cerr &lt;&lt; &quot;BB\n&quot;; //? 1</span>
         assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)));</span>
         out &lt;&lt; to_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>
-    for <span class="Delimiter">(</span>long long int 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> <span class="Delimiter">{</span>
-<span class="CommentedCode">//?       cerr &lt;&lt; &quot;aa: &quot; &lt;&lt; i &lt;&lt; &quot;, &quot; &lt;&lt; j &lt;&lt; &quot;: &quot; &lt;&lt; products.at(i).at(j) &lt;&lt; '\n'; //? 1</span>
-        out &lt;&lt; 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>
-    <span class="Delimiter">}</span>
+    for <span class="Delimiter">(</span>long long int 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; 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>
     out &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; &quot;aa: {\n&quot; &lt;&lt; out.str() &lt;&lt; &quot;}\n&quot;; //? 2</span>
   Most_recent_results = out<span class="Delimiter">.</span>str<span class="Delimiter">();</span>
 <span class="Delimiter">}</span>
 <span class="Delimiter">:(before &quot;Complete Call Fallthrough&quot;)</span>
 if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>operation == RUN_INTERACTIVE &amp;&amp; !current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span>
-  assert<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">)</span> &lt;= <span class="Constant">2</span><span class="Delimiter">);</span>
+  assert<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">)</span> &lt;= <span class="Constant">3</span><span class="Delimiter">);</span>
   <span class="Comment">// Send the results of the most recently executed instruction, regardless of</span>
   <span class="Comment">// call depth, to be converted to string and potentially printed to string.</span>
   vector&lt;double&gt; result<span class="Delimiter">;</span>
   result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_string<span class="Delimiter">(</span>Most_recent_results<span class="Delimiter">));</span>
   write_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">),</span> result<span class="Delimiter">);</span>
-  if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">)</span> == <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">)</span> &gt;= <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
     vector&lt;double&gt; warnings<span class="Delimiter">;</span>
     warnings<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>warnings_from_trace<span class="Delimiter">());</span>
     write_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">),</span> warnings<span class="Delimiter">);</span>
   <span class="Delimiter">}</span>
+  if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">)</span> &gt;= <span class="Constant">3</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    vector&lt;double&gt; screen<span class="Delimiter">;</span>
+<span class="CommentedCode">//?     cerr &lt;&lt; &quot;returning screen &quot; &lt;&lt; Memory[SCREEN] &lt;&lt; &quot; to &quot; &lt;&lt; current_instruction().products.at(2).to_string() &lt;&lt; &quot; value &quot; &lt;&lt; current_instruction().products.at(2).value &lt;&lt; '\n'; //? 1</span>
+    screen<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Memory[SCREEN]<span class="Delimiter">);</span>
+    write_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">),</span> screen<span class="Delimiter">);</span>
+  <span class="Delimiter">}</span>
+<span class="Delimiter">}</span>
+
+<span class="Comment">//: clean up reply after we've popped it off the call-stack</span>
+<span class="Comment">//: however, we need what was on the stack to decide whether to clean up</span>
+<span class="Delimiter">:(after &quot;Starting Reply&quot;)</span>
+bool must_clean_up_interactive = <span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">()</span> == <span class="Constant">&quot;interactive&quot;</span><span class="Delimiter">);</span>
+<span class="Delimiter">:(after &quot;Falling Through End Of Recipe&quot;)</span>
+bool must_clean_up_interactive = <span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">()</span> == <span class="Constant">&quot;interactive&quot;</span><span class="Delimiter">);</span>
+<span class="Delimiter">:(before &quot;End Reply&quot;)</span>
+if <span class="Delimiter">(</span>must_clean_up_interactive<span class="Delimiter">)</span> clean_up_interactive<span class="Delimiter">();</span>
+<span class="Delimiter">:(before &quot;Complete Call Fallthrough&quot;)</span>
+if <span class="Delimiter">(</span>must_clean_up_interactive<span class="Delimiter">)</span> clean_up_interactive<span class="Delimiter">();</span>
+<span class="Delimiter">:(code)</span>
+void clean_up_interactive<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  Hide_warnings = <span class="Constant">false</span><span class="Delimiter">;</span>
+  Running_interactive = <span class="Constant">false</span><span class="Delimiter">;</span>
+  <span class="Comment">// hack: assume collect_layer isn't set anywhere else</span>
+  if <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>collect_layer == <span class="Constant">&quot;warn&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    delete Trace_stream<span class="Delimiter">;</span>
+    Trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
+<span class="CommentedCode">//?   cerr &lt;&lt; &quot;restore screen: &quot; &lt;&lt; Memory[SCREEN] &lt;&lt; &quot; to &quot; &lt;&lt; Old_screen &lt;&lt; '\n'; //? 1</span>
+  Memory[SCREEN] = Old_screen<span class="Delimiter">;</span>
+  Old_screen = <span class="Constant">0</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
 <span class="Delimiter">:(code)</span>
@@ -227,17 +258,13 @@ string to_string<span class="Delimiter">(</span>long long int address<span class
     <span class="Comment">// todo: unicode</span>
     tmp &lt;&lt; <span class="Delimiter">(</span>char<span class="Delimiter">)(</span>int<span class="Delimiter">)</span>Memory[curr]<span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
-<span class="CommentedCode">//?   tb_shutdown(); //? 1</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; tmp.str() &lt;&lt; '\n'; //? 1</span>
   <span class="Identifier">return</span> tmp<span class="Delimiter">.</span>str<span class="Delimiter">();</span>
 <span class="Delimiter">}</span>
 
 long long int stringified_value_of_location<span class="Delimiter">(</span>long long int address<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   <span class="Comment">// convert to string</span>
   ostringstream out<span class="Delimiter">;</span>
-<span class="CommentedCode">//?   trace(1, &quot;foo&quot;) &lt;&lt; &quot;a: &quot; &lt;&lt; address; //? 1</span>
   out &lt;&lt; Memory[address]<span class="Delimiter">;</span>
-<span class="CommentedCode">//?   trace(1, &quot;foo&quot;) &lt;&lt; &quot;b: &quot; &lt;&lt; Memory[address]; //? 1</span>
   <span class="Identifier">return</span> new_string<span class="Delimiter">(</span>out<span class="Delimiter">.</span>str<span class="Delimiter">());</span>
 <span class="Delimiter">}</span>
 
@@ -277,13 +304,6 @@ case RELOAD: <span class="Delimiter">{</span>
   Loading_interactive = <span class="Constant">true</span><span class="Delimiter">;</span>
   Hide_warnings = <span class="Constant">true</span><span class="Delimiter">;</span>
   load<span class="Delimiter">(</span>to_string<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)));</span>
-<span class="CommentedCode">//?   static int foo = 0;</span>
-<span class="CommentedCode">//?   if (++foo == 2) {</span>
-<span class="CommentedCode">//?     tb_shutdown();</span>
-<span class="CommentedCode">//?     cerr &lt;&lt; Recipe_ordinal[&quot;new-add&quot;] &lt;&lt; '\n';</span>
-<span class="CommentedCode">//?     cerr &lt;&lt; Recipe[Recipe_ordinal[&quot;new-add&quot;]].steps[2].to_string() &lt;&lt; '\n';</span>
-<span class="CommentedCode">//?     exit(0);</span>
-<span class="CommentedCode">//?   }</span>
   transform_all<span class="Delimiter">();</span>
   Hide_warnings = <span class="Constant">false</span><span class="Delimiter">;</span>
   Loading_interactive = <span class="Constant">false</span><span class="Delimiter">;</span>
diff --git a/html/082persist.cc.html b/html/082persist.cc.html
new file mode 100644
index 00000000..cf056dba
--- /dev/null
+++ b/html/082persist.cc.html
@@ -0,0 +1,109 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Mu - 082persist.cc</title>
+<meta name="Generator" content="Vim/7.4">
+<meta name="plugin-version" content="vim7.4_v1">
+<meta name="syntax" content="cpp">
+<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
+<meta name="colorscheme" content="minimal">
+<style type="text/css">
+<!--
+pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
+body { font-family: monospace; color: #eeeeee; background-color: #080808; }
+* { font-size: 1.05em; }
+.cSpecial { color: #008000; }
+.Constant { color: #00a0a0; }
+.Comment { color: #9090ff; }
+.Delimiter { color: #a04060; }
+.Identifier { color: #804000; }
+.PreProc { color: #c000c0; }
+.CommentedCode { color: #6c6c6c; }
+-->
+</style>
+
+<script type='text/javascript'>
+<!--
+
+-->
+</script>
+</head>
+<body>
+<pre id='vimCodeElement'>
+<span class="Comment">//: Dead simple persistence.</span>
+<span class="Comment">//:   'restore' - reads string from a file</span>
+<span class="Comment">//:   'save' - writes string to a file</span>
+
+<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
+RESTORE<span class="Delimiter">,</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
+Recipe_ordinal[<span class="Constant">&quot;restore&quot;</span>] = RESTORE<span class="Delimiter">;</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
+case RESTORE: <span class="Delimiter">{</span>
+  if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span>
+    raise &lt;&lt; <span class="Constant">&quot;restore: illegal operand &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+  products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
+  products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>new_string<span class="Delimiter">(</span>slurp<span class="Delimiter">(</span><span class="Constant">&quot;lesson/&quot;</span>+current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name<span class="Delimiter">)));</span>
+  <span class="Identifier">break</span><span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
+<span class="Delimiter">:(code)</span>
+string slurp<span class="Delimiter">(</span>const string&amp; filename<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+<span class="CommentedCode">//?   cerr &lt;&lt; filename &lt;&lt; '\n'; //? 1</span>
+  ostringstream result<span class="Delimiter">;</span>
+  ifstream fin<span class="Delimiter">(</span>filename<span class="Delimiter">.</span>c_str<span class="Delimiter">());</span>
+  fin<span class="Delimiter">.</span>peek<span class="Delimiter">();</span>
+  if <span class="Delimiter">(</span>!fin<span class="Delimiter">)</span> <span class="Identifier">return</span> result<span class="Delimiter">.</span>str<span class="Delimiter">();</span>  <span class="Comment">// don't bother checking errno</span>
+  const int N = <span class="Constant">1024</span><span class="Delimiter">;</span>
+  char buf[N]<span class="Delimiter">;</span>
+  while <span class="Delimiter">(</span>!fin<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span>
+    bzero<span class="Delimiter">(</span>buf<span class="Delimiter">,</span> N<span class="Delimiter">);</span>
+    fin<span class="Delimiter">.</span>read<span class="Delimiter">(</span>buf<span class="Delimiter">,</span> N-<span class="Constant">1</span><span class="Delimiter">);</span>  <span class="Comment">// leave at least one null</span>
+    result &lt;&lt; buf<span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
+  fin<span class="Delimiter">.</span>close<span class="Delimiter">();</span>
+<span class="CommentedCode">//?   cerr &lt;&lt; &quot;=&gt; &quot; &lt;&lt; result.str(); //? 1</span>
+  <span class="Identifier">return</span> result<span class="Delimiter">.</span>str<span class="Delimiter">();</span>
+<span class="Delimiter">}</span>
+
+<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
+SAVE<span class="Delimiter">,</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
+Recipe_ordinal[<span class="Constant">&quot;save&quot;</span>] = SAVE<span class="Delimiter">;</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
+case SAVE: <span class="Delimiter">{</span>
+  if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span>
+    raise &lt;&lt; <span class="Constant">&quot;save: illegal operand 0 &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+  string filename = current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name<span class="Delimiter">;</span>
+  if <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>current_instruction<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>
+    ostringstream tmp<span class="Delimiter">;</span>
+    tmp &lt;&lt; ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
+    filename = tmp<span class="Delimiter">.</span>str<span class="Delimiter">();</span>
+  <span class="Delimiter">}</span>
+  ofstream fout<span class="Delimiter">((</span><span class="Constant">&quot;lesson/&quot;</span>+filename<span class="Delimiter">).</span>c_str<span class="Delimiter">());</span>
+  if <span class="Delimiter">(</span>!scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span>
+    raise &lt;&lt; <span class="Constant">&quot;save: illegal operand 1 &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+  string contents = to_string<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span>
+  fout &lt;&lt; contents<span class="Delimiter">;</span>
+  fout<span class="Delimiter">.</span>close<span class="Delimiter">();</span>
+  if <span class="Delimiter">(</span>!exists<span class="Delimiter">(</span><span class="Constant">&quot;lesson/.git&quot;</span><span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
+  <span class="Comment">// bug in git: git diff -q messes up --exit-code</span>
+  int status = system<span class="Delimiter">(</span><span class="Constant">&quot;cd lesson; git add .; git diff HEAD --exit-code &gt;/dev/null || git commit -a -m . &gt;/dev/null&quot;</span><span class="Delimiter">);</span>
+  if <span class="Delimiter">(</span>status != <span class="Constant">0</span><span class="Delimiter">)</span>
+    raise &lt;&lt; <span class="Constant">&quot;error in commit: contents &quot;</span> &lt;&lt; contents &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+  <span class="Identifier">break</span><span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
+<span class="Delimiter">:(code)</span>
+bool exists<span class="Delimiter">(</span>const string&amp; filename<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  struct stat dummy<span class="Delimiter">;</span>
+  <span class="Identifier">return</span> <span class="Constant">0</span> == stat<span class="Delimiter">(</span>filename<span class="Delimiter">.</span>c_str<span class="Delimiter">(),</span> &amp;dummy<span class="Delimiter">);</span>
+<span class="Delimiter">}</span>
+
+<span class="Delimiter">:(before &quot;End Includes&quot;)</span>
+<span class="PreProc">#include</span><span class="Constant">&lt;sys/stat.h&gt;</span>
+</pre>
+</body>
+</html>
+<!-- vim: set foldmethod=manual : -->
diff --git a/html/999spaces.cc.html b/html/999spaces.cc.html
index 784a5cd5..afc434e3 100644
--- a/html/999spaces.cc.html
+++ b/html/999spaces.cc.html
@@ -47,8 +47,10 @@ assert<span class="Delimiter">(</span>Reserved_for_tests == <span class="Constan
 <span class="SalientComment">//:: Recipes</span>
 <span class="Comment">//:</span>
 <span class="Comment">//: 0 - unused (IDLE; do nothing)</span>
-<span class="Comment">//: 1-99 - primitives</span>
-<span class="Comment">//: 100-999 - defined in .mu files as sequences of primitives</span>
+<span class="Comment">//: 1-199 - primitives</span>
+assert<span class="Delimiter">(</span>MAX_PRIMITIVE_RECIPES &lt; <span class="Constant">200</span><span class="Delimiter">);</span>
+<span class="Comment">//: 200-999 - defined in .mu files as sequences of primitives</span>
+assert<span class="Delimiter">(</span>Next_recipe_ordinal &lt; <span class="Constant">1000</span><span class="Delimiter">);</span>
 <span class="Comment">//: 1000 onwards - reserved for tests, cleared between tests</span>
 
 <span class="SalientComment">//:: Depths for tracing</span>
diff --git a/html/channel.mu.html b/html/channel.mu.html
index d77a5057..2bdeb7cc 100644
--- a/html/channel.mu.html
+++ b/html/channel.mu.html
@@ -34,7 +34,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 
 <span class="muRecipe">recipe</span> producer [
   <span class="Comment"># produce numbers 1 to 5 on a channel</span>
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># n = 0</span>
   n:number<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
@@ -52,7 +52,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 
 <span class="muRecipe">recipe</span> consumer [
   <span class="Comment"># consume and print integers from a channel</span>
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Delimiter">{</span>
     <span class="Comment"># read an integer from the channel</span>
@@ -65,7 +65,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 ]
 
 <span class="muRecipe">recipe</span> main [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   chan:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3:literal</span>
   <span class="Comment"># create two background 'routines' that communicate by a channel</span>
   routine1:number<span class="Special"> &lt;- </span>start-running producer:<span class="muRecipe">recipe</span>, chan:address:channel
diff --git a/html/chessboard.mu.html b/html/chessboard.mu.html
index 42e9f776..4e459564 100644
--- a/html/chessboard.mu.html
+++ b/html/chessboard.mu.html
@@ -101,27 +101,15 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
   ]
 ]
 
-<span class="CommentedCode">#? scenario foo [ #? 1</span>
-<span class="CommentedCode">#?   $print [aaa] #? 1</span>
-<span class="CommentedCode">#?   run [ #? 1</span>
-<span class="CommentedCode">#?     1:number &lt;- copy 34:literal #? 1</span>
-<span class="CommentedCode">#?   ] #? 1</span>
-<span class="CommentedCode">#?   memory-should-contain [ #? 1</span>
-<span class="CommentedCode">#?     1 &lt;- 34 #? 1</span>
-<span class="CommentedCode">#?   ] #? 1</span>
-<span class="CommentedCode">#?   $print [zzz] #? 1</span>
-<span class="CommentedCode">#? ] #? 1</span>
-
 <span class="SalientComment">## Here's how 'chessboard' is implemented.</span>
 
 <span class="muRecipe">recipe</span> chessboard [
 <span class="CommentedCode">#?   $start-tracing [schedule] #? 2</span>
 <span class="CommentedCode">#?   $start-tracing #? 1</span>
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-<span class="CommentedCode">#?   $print [screen: ], screen:address, [, console: ], console:address, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print [screen: ], screen:address, [, console: ], console:address, 10:literal/newline</span>
   board:address:array:address:array:character<span class="Special"> &lt;- </span>initial-position
   <span class="Comment"># hook up stdin</span>
   stdin:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">10:literal/capacity</span>
@@ -133,31 +121,21 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
     msg:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[Stupid text-mode chessboard. White pieces in uppercase; black pieces in lowercase. No checking for legal moves.</span>
 <span class="Constant">]</span>
     print-string screen:address, msg:address:array:character
-<span class="CommentedCode">#?     $print [aaa</span>
-<span class="CommentedCode">#? ] #? 1</span>
     cursor-to-next-line screen:address
     print-board screen:address, board:address:array:address:array:character
     cursor-to-next-line screen:address
     msg:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[Type in your move as &lt;from square&gt;-&lt;to square&gt;. For example: 'a2-a4'. Then press &lt;enter&gt;.</span>
 <span class="Constant">]</span>
     print-string screen:address, msg:address:array:character
-<span class="CommentedCode">#?     $print [bbb</span>
-<span class="CommentedCode">#? ] #? 1</span>
     cursor-to-next-line screen:address
     msg:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[Hit 'q' to exit.</span>
 <span class="Constant">]</span>
     print-string screen:address, msg:address:array:character
-<span class="CommentedCode">#?     $print [ccc</span>
-<span class="CommentedCode">#? ] #? 1</span>
     <span class="Delimiter">{</span>
       cursor-to-next-line screen:address
       msg:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[move: ]</span>
       print-string screen:address, msg:address:array:character
-<span class="CommentedCode">#?     $print [ddd</span>
-<span class="CommentedCode">#? ] #? 1</span>
       m:address:move, quit:boolean, error:boolean<span class="Special"> &lt;- </span>read-move buffered-stdin:address:channel, screen:address
-<span class="CommentedCode">#?     $print [eee</span>
-<span class="CommentedCode">#? ] #? 1</span>
       <span class="muControl">break-if</span> quit:boolean, +quit:offset
       buffered-stdin:address:channel<span class="Special"> &lt;- </span>clear-channel buffered-stdin:address:channel  <span class="Comment"># cleanup after error. todo: test this?</span>
       <span class="muControl">loop-if</span> error:boolean
@@ -167,13 +145,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
     <span class="muControl">loop</span>
   <span class="Delimiter">}</span>
 <span class="Constant">  +quit</span>
-<span class="CommentedCode">#?   $print [aaa] #? 1</span>
 ]
 
 <span class="SalientComment">## a board is an array of files, a file is an array of characters (squares)</span>
 
 <span class="muRecipe">recipe</span> new-board [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   initial-position:address:array:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># assert(length(initial-position) == 64)</span>
   len:number<span class="Special"> &lt;- </span>length initial-position:address:array:number/deref
@@ -194,7 +171,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 ]
 
 <span class="muRecipe">recipe</span> new-file [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   position:address:array:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   index:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   index:number<span class="Special"> &lt;- </span>multiply index:number, <span class="Constant">8:literal</span>
@@ -213,18 +190,16 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 ]
 
 <span class="muRecipe">recipe</span> print-board [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   board:address:array:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   row:number<span class="Special"> &lt;- </span>copy <span class="Constant">7:literal</span>  <span class="Comment"># start printing from the top of the board</span>
   <span class="Comment"># print each row</span>
-<span class="CommentedCode">#?   $print [printing board to screen ], screen:address, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print [printing board to screen ], screen:address, 10:literal/newline</span>
   <span class="Delimiter">{</span>
     done?:boolean<span class="Special"> &lt;- </span>lesser-than row:number, <span class="Constant">0:literal</span>
     <span class="muControl">break-if</span> done?:boolean
-<span class="CommentedCode">#?     $print [printing rank ], row:number, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?     $print [printing rank ], row:number, 10:literal/newline</span>
     <span class="Comment"># print rank number as a legend</span>
     rank:number<span class="Special"> &lt;- </span>add row:number, <span class="Constant">1:literal</span>
     print-integer screen:address, rank:number
@@ -262,7 +237,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 
 <span class="Comment"># board:address:array:address:array:character &lt;- initial-position</span>
 <span class="muRecipe">recipe</span> initial-position [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   <span class="Comment"># layout in memory (in raster order):</span>
   <span class="Comment">#   R P _ _ _ _ p r</span>
   <span class="Comment">#   N P _ _ _ _ p n</span>
@@ -322,7 +297,7 @@ container move [
 <span class="Comment"># result:address:move, quit?:boolean, error?:boolean &lt;- read-move stdin:address:channel, screen:address</span>
 <span class="Comment"># prints only error messages to screen</span>
 <span class="muRecipe">recipe</span> read-move [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   stdin:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
 <span class="CommentedCode">#?   $print screen:address #? 1</span>
@@ -357,7 +332,7 @@ container move [
 <span class="Comment"># file:number, quit:boolean, error:boolean &lt;- read-file stdin:address:channel, screen:address</span>
 <span class="Comment"># valid values for file: 0-7</span>
 <span class="muRecipe">recipe</span> read-file [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   stdin:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   c:character, stdin:address:channel<span class="Special"> &lt;- </span>read stdin:address:channel
@@ -384,8 +359,7 @@ container move [
     <span class="muControl">reply</span> <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/quit</span>, <span class="Constant">1:literal/error</span>
   <span class="Delimiter">}</span>
   file:number<span class="Special"> &lt;- </span>subtract c:character, <span class="Constant">97:literal</span>  <span class="Comment"># 'a'</span>
-<span class="CommentedCode">#?   $print file:number, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print file:number, 10:literal/newline</span>
   <span class="Comment"># 'a' &lt;= file &lt;= 'h'</span>
   <span class="Delimiter">{</span>
     above-min:boolean<span class="Special"> &lt;- </span>greater-or-equal file:number, <span class="Constant">0:literal</span>
@@ -410,7 +384,7 @@ container move [
 <span class="Comment"># rank:number &lt;- read-rank stdin:address:channel, screen:address</span>
 <span class="Comment"># valid values: 0-7, -1 (quit), -2 (error)</span>
 <span class="muRecipe">recipe</span> read-rank [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   stdin:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   c:character, stdin:address:channel<span class="Special"> &lt;- </span>read stdin:address:channel
@@ -432,8 +406,7 @@ container move [
     <span class="muControl">reply</span> <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/quit</span>, <span class="Constant">1:literal/error</span>
   <span class="Delimiter">}</span>
   rank:number<span class="Special"> &lt;- </span>subtract c:character, <span class="Constant">49:literal</span>  <span class="Comment"># '1'</span>
-<span class="CommentedCode">#?   $print rank:number, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print rank:number, 10:literal/newline</span>
   <span class="Comment"># assert'1' &lt;= rank &lt;= '8'</span>
   <span class="Delimiter">{</span>
     above-min:boolean<span class="Special"> &lt;- </span>greater-or-equal rank:number, <span class="Constant">0:literal</span>
@@ -457,7 +430,7 @@ container move [
 <span class="Comment"># read a character from the given channel and check that it's what we expect</span>
 <span class="Comment"># return true on error</span>
 <span class="muRecipe">recipe</span> expect-from-channel [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   stdin:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   expected:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -477,30 +450,25 @@ container move [
   run [
 <span class="CommentedCode">#?     $start-tracing #? 1</span>
     1:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">2:literal</span>
-<span class="CommentedCode">#?     $print [aaa channel address: ], 1:address:channel, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?     $print [aaa channel address: ], 1:address:channel, 10:literal/newline</span>
     2:number/routine<span class="Special"> &lt;- </span>start-running read-move:<span class="muRecipe">recipe</span>, 1:address:channel, screen:address
     <span class="Comment"># 'read-move' is waiting for input</span>
     wait-for-routine 2:number
-<span class="CommentedCode">#?     $print [bbb channel address: ], 1:address:channel, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?     $print [bbb channel address: ], 1:address:channel, 10:literal/newline</span>
     3:number<span class="Special"> &lt;- </span>routine-state 2:number/id
-<span class="CommentedCode">#?     $print [I: routine ], 2:number, [ state ], 3:number [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?     $print [I: routine ], 2:number, [ state ], 3:number 10:literal/newline</span>
     4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, <span class="Constant">2:literal/waiting</span>
     assert 4:boolean/waiting?, [
 F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> coming up (<span class="muRecipe">before</span> any keys were pressed)]
     <span class="Comment"># press 'a'</span>
-<span class="CommentedCode">#?     $print [ccc channel address: ], 1:address:channel, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?     $print [ccc channel address: ], 1:address:channel, 10:literal/newline</span>
 <span class="CommentedCode">#?     $exit #? 1</span>
     1:address:channel<span class="Special"> &lt;- </span>write 1:address:channel, <span class="Constant">97:literal</span>  <span class="Comment"># 'a'</span>
     restart 2:number/routine
     <span class="Comment"># 'read-move' still waiting for input</span>
     wait-for-routine 2:number
     3:number<span class="Special"> &lt;- </span>routine-state 2:number/id
-<span class="CommentedCode">#?     $print [II: routine ], 2:number, [ state ], 3:number [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?     $print [II: routine ], 2:number, [ state ], 3:number 10:literal/newline</span>
     4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, <span class="Constant">2:literal/waiting</span>
     assert 4:boolean/waiting?, [
 F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> rank 'a']
@@ -510,8 +478,7 @@ F read-move-blocking: routine failed to pause <span class="muRecipe">after</span
     <span class="Comment"># 'read-move' still waiting for input</span>
     wait-for-routine 2:number
     3:number<span class="Special"> &lt;- </span>routine-state 2:number/id
-<span class="CommentedCode">#?     $print [III: routine ], 2:number, [ state ], 3:number [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?     $print [III: routine ], 2:number, [ state ], 3:number 10:literal/newline</span>
     4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, <span class="Constant">2:literal/waiting</span>
     assert 4:boolean/waiting?, [
 F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> file 'a2']
@@ -521,8 +488,7 @@ F read-move-blocking: routine failed to pause <span class="muRecipe">after</span
     <span class="Comment"># 'read-move' still waiting for input</span>
     wait-for-routine 2:number
     3:number<span class="Special"> &lt;- </span>routine-state 2:number
-<span class="CommentedCode">#?     $print [IV: routine ], 2:number, [ state ], 3:number [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?     $print [IV: routine ], 2:number, [ state ], 3:number 10:literal/newline</span>
     4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, <span class="Constant">2:literal/waiting</span>
     assert 4:boolean/waiting?/routine-state, [
 F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> hyphen 'a2-']
@@ -532,8 +498,7 @@ F read-move-blocking: routine failed to pause <span class="muRecipe">after</span
     <span class="Comment"># 'read-move' still waiting for input</span>
     wait-for-routine 2:number
     3:number<span class="Special"> &lt;- </span>routine-state 2:number
-<span class="CommentedCode">#?     $print [V: routine ], 2:number, [ state ], 3:number [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?     $print [V: routine ], 2:number, [ state ], 3:number 10:literal/newline</span>
     4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, <span class="Constant">2:literal/waiting</span>
     assert 4:boolean/waiting?/routine-state, [
 F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> rank 'a2-a']
@@ -543,8 +508,7 @@ F read-move-blocking: routine failed to pause <span class="muRecipe">after</span
     <span class="Comment"># 'read-move' still waiting for input</span>
     wait-for-routine 2:number
     3:number<span class="Special"> &lt;- </span>routine-state 2:number
-<span class="CommentedCode">#?     $print [VI: routine ], 2:number, [ state ], 3:number [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?     $print [VI: routine ], 2:number, [ state ], 3:number 10:literal/newline</span>
     4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, <span class="Constant">2:literal/waiting</span>
     assert 4:boolean/waiting?, [
 F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> file 'a2-a4']
@@ -554,8 +518,7 @@ F read-move-blocking: routine failed to pause <span class="muRecipe">after</span
     <span class="Comment"># 'read-move' now completes</span>
     wait-for-routine 2:number
     3:number<span class="Special"> &lt;- </span>routine-state 2:number
-<span class="CommentedCode">#?     $print [VII: routine ], 2:number, [ state ], 3:number [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?     $print [VII: routine ], 2:number, [ state ], 3:number 10:literal/newline</span>
     4:boolean/completed?<span class="Special"> &lt;- </span>equal 3:number/routine-state, <span class="Constant">1:literal/completed</span>
     assert 4:boolean/completed?, [
 F read-move-blocking: routine failed to terminate on newline]
@@ -659,27 +622,22 @@ F read-move-file: routine failed to pause <span class="muRecipe">after</span> co
 ]
 
 <span class="muRecipe">recipe</span> make-move [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   b:address:array:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   m:address:move<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   from-file:number<span class="Special"> &lt;- </span>get m:address:move/deref, from-file:offset
-<span class="CommentedCode">#?   $print from-file:number, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print from-file:number, 10:literal/newline</span>
   from-rank:number<span class="Special"> &lt;- </span>get m:address:move/deref, from-rank:offset
-<span class="CommentedCode">#?   $print from-rank:number, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print from-rank:number, 10:literal/newline</span>
   to-file:number<span class="Special"> &lt;- </span>get m:address:move/deref, to-file:offset
-<span class="CommentedCode">#?   $print to-file:number, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print to-file:number, 10:literal/newline</span>
   to-rank:number<span class="Special"> &lt;- </span>get m:address:move/deref, to-rank:offset
-<span class="CommentedCode">#?   $print to-rank:number, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print to-rank:number, 10:literal/newline</span>
   f:address:array:character<span class="Special"> &lt;- </span>index b:address:array:address:array:character/deref, from-file:number
   src:address:character/square<span class="Special"> &lt;- </span>index-address f:address:array:character/deref, from-rank:number
   f:address:array:character<span class="Special"> &lt;- </span>index b:address:array:address:array:character/deref, to-file:number
   dest:address:character/square<span class="Special"> &lt;- </span>index-address f:address:array:character/deref, to-rank:number
-<span class="CommentedCode">#?   $print src:address:character/deref, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print src:address:character/deref, 10:literal/newline</span>
   dest:address:character/deref/square<span class="Special"> &lt;- </span>copy src:address:character/deref/square
   src:address:character/deref/square<span class="Special"> &lt;- </span>copy <span class="Constant">32:literal</span>  <span class="Comment"># ' '</span>
   <span class="muControl">reply</span> b:address:array:address:array:character/same-as-ingredient:0
diff --git a/html/counters.mu.html b/html/counters.mu.html
index 1e76afdf..7bba9ad8 100644
--- a/html/counters.mu.html
+++ b/html/counters.mu.html
@@ -39,7 +39,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 ]
 
 <span class="muRecipe">recipe</span> increment-counter [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   0:address:array:location/names:new-counter<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>  <span class="Comment"># setup outer space; it *must* come from 'new-counter'</span>
   x:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   n:number/space:1<span class="Special"> &lt;- </span>add n:number/space:1, x:number
@@ -47,7 +47,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 ]
 
 <span class="muRecipe">recipe</span> main [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   <span class="Comment"># counter A</span>
   a:address:array:location<span class="Special"> &lt;- </span>new-counter <span class="Constant">34:literal</span>
   <span class="Comment"># counter B</span>
diff --git a/html/edit.mu.html b/html/edit.mu.html
index 078fac53..fd76d06c 100644
--- a/html/edit.mu.html
+++ b/html/edit.mu.html
@@ -36,17 +36,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <span class="Comment"># Environment for learning programming using mu.</span>
 
 <span class="muRecipe">recipe</span> main [
-  <span class="Constant">new-default-space</span>
-  open-console
-  initial-recipe:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[recipe new-add [</span>
-<span class="Constant">  x:number &lt;- next-ingredient</span>
-<span class="Constant">  y:number &lt;- next-ingredient</span>
-<span class="Constant">  z:number &lt;- add x:number, y:number</span>
-<span class="Constant">  reply z:number</span>
-<span class="Constant">]</span>]
-  initial-sandbox:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[new-add 2:literal, 3:literal]</span>
+  <span class="Constant">local-scope</span>
+  open-console <span class="CommentedCode">#? 1</span>
+  initial-recipe:address:array:character<span class="Special"> &lt;- </span>restore <span class="Constant">[recipes.mu]</span>
+<span class="CommentedCode">#?   $exit #? 1</span>
+  initial-sandbox:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[test 2, 2]</span>
   env:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment <span class="Constant">0:literal/screen</span>, initial-recipe:address:array:character, initial-sandbox:address:array:character
-  render-all <span class="Constant">0:literal/address</span>, env:address:programming-environment-data
   event-loop <span class="Constant">0:literal/screen</span>, <span class="Constant">0:literal/console</span>, env:address:programming-environment-data
 ]
 
@@ -59,7 +54,7 @@ container programming-environment-data [
 ]
 
 <span class="muRecipe">recipe</span> new-programming-environment [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   initial-recipe-contents:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   initial-sandbox-contents:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -85,8 +80,7 @@ container programming-environment-data [
   new-right:number<span class="Special"> &lt;- </span>add new-left:number, <span class="Constant">5:literal</span>
   current-sandbox:address:address:editor-data<span class="Special"> &lt;- </span>get-address result:address:programming-environment-data/deref, current-sandbox:offset
   current-sandbox:address:address:editor-data/deref<span class="Special"> &lt;- </span>new-editor initial-sandbox-contents:address:array:character, screen:address, new-left:number, width:number
-  <span class="Comment"># initialize cursor</span>
-  update-cursor screen:address, recipes:address:address:editor-data/deref, current-sandbox:address:address:editor-data/deref, <span class="Constant">0:literal/focus-in-recipes</span>
+  screen:address<span class="Special"> &lt;- </span>render-all screen:address, result:address:programming-environment-data
   <span class="muControl">reply</span> result:address:programming-environment-data
 ]
 
@@ -126,7 +120,7 @@ container editor-data [
 <span class="Comment">#   top/left/right constrain the screen area available to the new editor.</span>
 <span class="Comment">#   right is exclusive.</span>
 <span class="muRecipe">recipe</span> new-editor [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># no clipping of bounds</span>
@@ -196,7 +190,7 @@ container editor-data [
 
 <span class="Comment"># bottom:number, screen:address &lt;- render screen:address, editor:address:editor-data</span>
 <span class="muRecipe">recipe</span> render [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="muControl">reply-unless</span> editor:address:editor-data, <span class="Constant">1:literal/top</span>, screen:address/same-as-ingredient:0
@@ -204,6 +198,9 @@ container editor-data [
   screen-height:number<span class="Special"> &lt;- </span>screen-height screen:address
   right:number<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, right:offset
   hide-screen screen:address
+  <span class="Comment"># highlight mu code with color</span>
+  color:number<span class="Special"> &lt;- </span>copy <span class="Constant">7:literal/white</span>
+  highlighting-state:number<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal/normal</span>
   <span class="Comment"># traversing editor</span>
   curr:address:duplex-list<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, data:offset
   prev:address:duplex-list<span class="Special"> &lt;- </span>copy curr:address:duplex-list
@@ -231,6 +228,7 @@ container editor-data [
       before-cursor:address:address:duplex-list/deref<span class="Special"> &lt;- </span>prev-duplex curr:address:duplex-list
     <span class="Delimiter">}</span>
     c:character<span class="Special"> &lt;- </span>get curr:address:duplex-list/deref, value:offset
+    color:number, highlighting-state:number<span class="Special"> &lt;- </span>get-color color:number, highlighting-state:number, c:character
     <span class="Delimiter">{</span>
       <span class="Comment"># newline? move to left rather than 0</span>
       newline?:boolean<span class="Special"> &lt;- </span>equal c:character, <span class="Constant">10:literal/newline</span>
@@ -267,7 +265,7 @@ container editor-data [
       <span class="Comment"># don't increment curr</span>
       <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
     <span class="Delimiter">}</span>
-    print-character screen:address, c:character
+    print-character screen:address, c:character, color:number
     curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex curr:address:duplex-list
     prev:address:duplex-list<span class="Special"> &lt;- </span>next-duplex prev:address:duplex-list
     column:number<span class="Special"> &lt;- </span>add column:number, <span class="Constant">1:literal</span>
@@ -300,10 +298,11 @@ container editor-data [
 ]
 
 <span class="Comment"># row:number, screen:address &lt;- render-string screen:address, s:address:array:character, left:number, right:number, color:number, row:number</span>
+<span class="Comment"># move cursor at start of next line</span>
 <span class="Comment"># print a string 's' to 'editor' in 'color' starting at 'row'</span>
-<span class="Comment"># leave cursor at start of next line</span>
+<span class="Comment"># clear rest of last line, but don't move cursor to next line</span>
 <span class="muRecipe">recipe</span> render-string [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -368,8 +367,77 @@ container editor-data [
   <span class="muControl">reply</span> row:number/same-as-ingredient:5, screen:address/same-as-ingredient:0
 ]
 
+<span class="Comment"># row:number, screen:address &lt;- render-screen screen:address, sandbox-screen:address, left:number, right:number, row:number</span>
+<span class="Comment"># print the fake sandbox screen to 'screen' with appropriate delimiters</span>
+<span class="Comment"># leave cursor at start of next line</span>
+<span class="muRecipe">recipe</span> render-screen [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  s:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  row:number<span class="Special"> &lt;- </span>add row:number, <span class="Constant">1:literal</span>
+  <span class="muControl">reply-unless</span> s:address:screen, row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0
+  <span class="Comment"># print 'screen:'</span>
+  header:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[screen:]</span>
+  row:number<span class="Special"> &lt;- </span>subtract row:number, <span class="Constant">1:literal</span>  <span class="Comment"># compensate for render-string below</span>
+  row:number<span class="Special"> &lt;- </span>render-string screen:address, header:address:array:character, left:number, right:number, <span class="Constant">245:literal/grey</span>, row:number
+  <span class="Comment"># newline</span>
+  row:number<span class="Special"> &lt;- </span>add row:number, <span class="Constant">1:literal</span>
+  move-cursor screen:address, row:number, left:number
+  <span class="Comment"># start printing s</span>
+  column:number<span class="Special"> &lt;- </span>copy left:number
+  s-width:number<span class="Special"> &lt;- </span>screen-width s:address:screen
+  s-height:number<span class="Special"> &lt;- </span>screen-height s:address:screen
+  buf:address:array:screen-cell<span class="Special"> &lt;- </span>get s:address:screen/deref, data:offset
+  stop-printing:number<span class="Special"> &lt;- </span>add left:number, s-width:number, <span class="Constant">3:literal</span>
+  max-column:number<span class="Special"> &lt;- </span>min stop-printing:number, right:number
+  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
+  len:number<span class="Special"> &lt;- </span>length buf:address:array:screen-cell/deref
+  screen-height:number<span class="Special"> &lt;- </span>screen-height screen:address
+  <span class="Delimiter">{</span>
+    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i:number, len:number
+    <span class="muControl">break-if</span> done?:boolean
+    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal row:number, screen-height:number
+    <span class="muControl">break-if</span> done?:boolean
+    column:number<span class="Special"> &lt;- </span>copy left:number
+    move-cursor screen:address, row:number, column:number
+    <span class="Comment"># initial leader for each row: two spaces and a '.'</span>
+    print-character screen:address, <span class="Constant">32:literal/space</span>, <span class="Constant">245:literal/grey</span>
+    print-character screen:address, <span class="Constant">32:literal/space</span>, <span class="Constant">245:literal/grey</span>
+    print-character screen:address, <span class="Constant">46:literal/full-stop</span>, <span class="Constant">245:literal/grey</span>
+    column:number<span class="Special"> &lt;- </span>add left:number, <span class="Constant">3:literal</span>
+    <span class="Delimiter">{</span>
+      <span class="Comment"># print row</span>
+      row-done?:boolean<span class="Special"> &lt;- </span>greater-or-equal column:number, max-column:number
+      <span class="muControl">break-if</span> row-done?:boolean
+      curr:screen-cell<span class="Special"> &lt;- </span>index buf:address:array:screen-cell/deref, i:number
+      c:character<span class="Special"> &lt;- </span>get curr:screen-cell, contents:offset
+      print-character screen:address, c:character, <span class="Constant">245:literal/grey</span>
+      column:number<span class="Special"> &lt;- </span>add column:number, <span class="Constant">1:literal</span>
+      i:number<span class="Special"> &lt;- </span>add i:number, <span class="Constant">1:literal</span>
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># print final '.'</span>
+    print-character screen:address, <span class="Constant">46:literal/full-stop</span>, <span class="Constant">245:literal/grey</span>
+    column:number<span class="Special"> &lt;- </span>add column:number, <span class="Constant">1:literal</span>
+    <span class="Delimiter">{</span>
+      <span class="Comment"># clear rest of current line</span>
+      line-done?:boolean<span class="Special"> &lt;- </span>greater-than column:number, right:number
+      <span class="muControl">break-if</span> line-done?:boolean
+      print-character screen:address, <span class="Constant">32:literal/space</span>
+      column:number<span class="Special"> &lt;- </span>add column:number, <span class="Constant">1:literal</span>
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
+    row:number<span class="Special"> &lt;- </span>add row:number, <span class="Constant">1:literal</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0
+]
+
 <span class="muRecipe">recipe</span> clear-line-delimited [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -438,7 +506,7 @@ container editor-data [
    <span class="Constant"> .def  .</span>
    <span class="Constant"> .     .</span>
   ]
-  screen-should-contain-in-color, <span class="Constant">245:literal/grey</span> [
+  screen-should-contain-in-color <span class="Constant">245:literal/grey</span> [
    <span class="Constant"> .     .</span>
    <span class="Constant"> .    ↩.</span>
    <span class="Constant"> .     .</span>
@@ -460,7 +528,7 @@ container editor-data [
    <span class="Constant"> .e    .</span>
    <span class="Constant"> .     .</span>
   ]
-  screen-should-contain-in-color, <span class="Constant">245:literal/grey</span> [
+  screen-should-contain-in-color <span class="Constant">245:literal/grey</span> [
    <span class="Constant"> .     .</span>
    <span class="Constant"> .    ↩.</span>
    <span class="Constant"> .     .</span>
@@ -487,10 +555,116 @@ container editor-data [
   ]
 ]
 
+<span class="SalientComment">## highlighting mu code</span>
+
+<span class="muScenario">scenario</span> render-colors-comments [
+  assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">5:literal/height</span>
+  run [
+    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant"># de</span>
+<span class="Constant">f]</span>
+    new-editor s:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .abc  .</span>
+   <span class="Constant"> .# de .</span>
+   <span class="Constant"> .f    .</span>
+   <span class="Constant"> .     .</span>
+  ]
+  screen-should-contain-in-color <span class="Constant">12:literal/lightblue</span>, [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .# de .</span>
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .     .</span>
+  ]
+  screen-should-contain-in-color <span class="Constant">7:literal/white</span>, [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .abc  .</span>
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .f    .</span>
+   <span class="Constant"> .     .</span>
+  ]
+]
+
+<span class="Comment"># color:number, highlighting-state:number &lt;- get-color color:number, highlighting-state:number, c:character</span>
+<span class="muRecipe">recipe</span> get-color [
+  <span class="Constant">local-scope</span>
+  color:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  highlighting-state:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  color-is-white?:boolean<span class="Special"> &lt;- </span>equal color:number, <span class="Constant">7:literal/white</span>
+<span class="CommentedCode">#?   $print [character: ], c:character, 10:literal/newline #? 1</span>
+  <span class="Comment"># if color is white and next character is '#', switch color to blue</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> color-is-white?:boolean
+    starting-comment?:boolean<span class="Special"> &lt;- </span>equal c:character, <span class="Constant">35:literal/#</span>
+    <span class="muControl">break-unless</span> starting-comment?:boolean
+<span class="CommentedCode">#?     $print [switch color back to blue], 10:literal/newline #? 1</span>
+    color:number<span class="Special"> &lt;- </span>copy <span class="Constant">12:literal/lightblue</span>
+    <span class="muControl">jump</span> <span class="Constant">+exit:label</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># if color is blue and next character is newline, switch color to white</span>
+  <span class="Delimiter">{</span>
+    color-is-blue?:boolean<span class="Special"> &lt;- </span>equal color:number, <span class="Constant">12:literal/lightblue</span>
+    <span class="muControl">break-unless</span> color-is-blue?:boolean
+    ending-comment?:boolean<span class="Special"> &lt;- </span>equal c:character, <span class="Constant">10:literal/newline</span>
+    <span class="muControl">break-unless</span> ending-comment?:boolean
+<span class="CommentedCode">#?     $print [switch color back to white], 10:literal/newline #? 1</span>
+    color:number<span class="Special"> &lt;- </span>copy <span class="Constant">7:literal/white</span>
+    <span class="muControl">jump</span> <span class="Constant">+exit:label</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># if color is white (no comments) and next character is '&lt;', switch color to red</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> color-is-white?:boolean
+    starting-assignment?:boolean<span class="Special"> &lt;- </span>equal c:character, <span class="Constant">60:literal/&lt;</span>
+    <span class="muControl">break-unless</span> starting-assignment?:boolean
+    color:number<span class="Special"> &lt;- </span>copy <span class="Constant">1:literal/red</span>
+    <span class="muControl">jump</span> <span class="Constant">+exit:label</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># if color is red and next character is space, switch color to white</span>
+  <span class="Delimiter">{</span>
+    color-is-red?:boolean<span class="Special"> &lt;- </span>equal color:number, <span class="Constant">1:literal/red</span>
+    <span class="muControl">break-unless</span> color-is-red?:boolean
+    ending-assignment?:boolean<span class="Special"> &lt;- </span>equal c:character, <span class="Constant">32:literal/space</span>
+    <span class="muControl">break-unless</span> ending-assignment?:boolean
+    color:number<span class="Special"> &lt;- </span>copy <span class="Constant">7:literal/white</span>
+    <span class="muControl">jump</span> <span class="Constant">+exit:label</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># otherwise no change</span>
+<span class="Constant">  +exit</span>
+  <span class="muControl">reply</span> color:number, highlighting-state:number
+]
+
+<span class="muScenario">scenario</span> render-colors-assignment [
+  assume-screen <span class="Constant">8:literal/width</span>, <span class="Constant">5:literal/height</span>
+  run [
+    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">d &lt;- e</span>
+<span class="Constant">f]</span>
+    new-editor s:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">8:literal/right</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .        .</span>
+   <span class="Constant"> .abc     .</span>
+   <span class="Constant"> .d &lt;- e  .</span>
+   <span class="Constant"> .f       .</span>
+   <span class="Constant"> .        .</span>
+  ]
+  screen-should-contain-in-color <span class="Constant">1:literal/red</span>, [
+   <span class="Constant"> .        .</span>
+   <span class="Constant"> .        .</span>
+   <span class="Constant"> .  &lt;-    .</span>
+   <span class="Constant"> .        .</span>
+   <span class="Constant"> .        .</span>
+  ]
+]
+
 <span class="SalientComment">## handling events from the keyboard, mouse, touch screen, ...</span>
 
 <span class="muRecipe">recipe</span> event-loop [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -513,13 +687,26 @@ container editor-data [
         do-run?:boolean<span class="Special"> &lt;- </span>equal k:address:number/deref, <span class="Constant">65526:literal/F10</span>
         <span class="muControl">break-unless</span> do-run?:boolean
         run-sandboxes env:address:programming-environment-data
-        <span class="muControl">jump</span> <span class="Constant">+continue:label</span>
+        screen:address<span class="Special"> &lt;- </span>render-sandbox-side screen:address, env:address:programming-environment-data
+        <span class="Comment"># F10 doesn't mess with the recipe side</span>
+        update-cursor screen:address, recipes:address:editor-data, current-sandbox:address:editor-data, sandbox-in-focus?:address:boolean/deref
+        show-screen screen:address
+        <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
       <span class="Delimiter">}</span>
     <span class="Delimiter">}</span>
-    <span class="Comment"># 'touch' event - send to both editors</span>
+    <span class="Comment"># 'touch' event</span>
     <span class="Delimiter">{</span>
       t:address:touch-event<span class="Special"> &lt;- </span>maybe-convert e:event, touch:variant
       <span class="muControl">break-unless</span> t:address:touch-event
+      <span class="Comment"># on a sandbox delete icon? process delete</span>
+      <span class="Delimiter">{</span>
+        was-delete?:boolean<span class="Special"> &lt;- </span>delete-sandbox t:address:touch-event/deref, env:address:programming-environment-data
+        <span class="muControl">break-unless</span> was-delete?:boolean
+        screen:address<span class="Special"> &lt;- </span>render-sandbox-side screen:address, env:address:programming-environment-data, <span class="Constant">1:literal/clear</span>
+        update-cursor screen:address, recipes:address:editor-data, current-sandbox:address:editor-data, sandbox-in-focus?:address:boolean/deref
+        <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+      <span class="Delimiter">}</span>
+      <span class="Comment"># if not, send to both editors</span>
       _<span class="Special"> &lt;- </span>move-cursor-in-editor screen:address, recipes:address:editor-data, t:address:touch-event/deref
       sandbox-in-focus?:address:boolean/deref<span class="Special"> &lt;- </span>move-cursor-in-editor screen:address, current-sandbox:address:editor-data, t:address:touch-event/deref
       <span class="muControl">jump</span> <span class="Constant">+continue:label</span>
@@ -536,12 +723,14 @@ container editor-data [
       <span class="Delimiter">}</span>
     <span class="Delimiter">}</span>
 <span class="Constant">    +continue</span>
-    <span class="Comment"># if no more events currently left to process, render</span>
+    <span class="Comment"># if no more events currently left to process, render.</span>
+    <span class="Comment"># we rely on 'render' to update 'before-cursor' on pointer events, but</span>
+    <span class="Comment"># they won't usually come fast enough to trigger this.</span>
     <span class="Comment"># todo: test this</span>
     <span class="Delimiter">{</span>
       more-events?:boolean<span class="Special"> &lt;- </span>has-more-events? console:address
       <span class="muControl">break-if</span> more-events?:boolean
-      render-all screen:address, env:address:programming-environment-data
+      render-minimal screen:address, env:address:programming-environment-data
     <span class="Delimiter">}</span>
     <span class="muControl">loop</span>
   <span class="Delimiter">}</span>
@@ -549,7 +738,7 @@ container editor-data [
 
 <span class="Comment"># helper for testing a single editor</span>
 <span class="muRecipe">recipe</span> editor-event-loop [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -582,16 +771,17 @@ container editor-data [
 ]
 
 <span class="muRecipe">recipe</span> handle-event [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   e:event<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="muControl">reply-unless</span> editor:address:editor-data
-  <span class="Comment"># typing a character</span>
+  <span class="Comment"># character</span>
   <span class="Delimiter">{</span>
     c:address:character<span class="Special"> &lt;- </span>maybe-convert e:event, text:variant
     <span class="muControl">break-unless</span> c:address:character
+    <span class="Comment"># check for special characters</span>
     <span class="Comment"># unless it's a backspace</span>
     <span class="Delimiter">{</span>
       backspace?:boolean<span class="Special"> &lt;- </span>equal c:address:character/deref, <span class="Constant">8:literal/backspace</span>
@@ -599,10 +789,39 @@ container editor-data [
       delete-before-cursor editor:address:editor-data
       <span class="muControl">reply</span>
     <span class="Delimiter">}</span>
+    <span class="Comment"># ctrl-a</span>
+    <span class="Delimiter">{</span>
+      ctrl-a?:boolean<span class="Special"> &lt;- </span>equal c:address:character/deref, <span class="Constant">1:literal/ctrl-a</span>
+      <span class="muControl">break-unless</span> ctrl-a?:boolean
+      move-to-start-of-line editor:address:editor-data
+      <span class="muControl">reply</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># ctrl-e</span>
+    <span class="Delimiter">{</span>
+      ctrl-e?:boolean<span class="Special"> &lt;- </span>equal c:address:character/deref, <span class="Constant">5:literal/ctrl-e</span>
+      <span class="muControl">break-unless</span> ctrl-e?:boolean
+      move-to-end-of-line editor:address:editor-data
+      <span class="muControl">reply</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># ctrl-u</span>
+    <span class="Delimiter">{</span>
+      ctrl-u?:boolean<span class="Special"> &lt;- </span>equal c:address:character/deref, <span class="Constant">21:literal/ctrl-u</span>
+      <span class="muControl">break-unless</span> ctrl-u?:boolean
+      delete-to-start-of-line editor:address:editor-data
+      <span class="muControl">reply</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># ctrl-k</span>
+    <span class="Delimiter">{</span>
+      ctrl-k?:boolean<span class="Special"> &lt;- </span>equal c:address:character/deref, <span class="Constant">11:literal/ctrl-k</span>
+      <span class="muControl">break-unless</span> ctrl-k?:boolean
+      delete-to-end-of-line editor:address:editor-data
+      <span class="muControl">reply</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># otherwise type it in</span>
     insert-at-cursor editor:address:editor-data, c:address:character/deref, screen:address
     <span class="muControl">reply</span>
   <span class="Delimiter">}</span>
-  <span class="Comment"># otherwise it's a special key to control the editor</span>
+  <span class="Comment"># otherwise it's a special key</span>
   k:address:number<span class="Special"> &lt;- </span>maybe-convert e:event, keycode:variant
   assert k:address:number, <span class="Constant">[event was of unknown type; neither keyboard nor mouse]</span>
   d:address:duplex-list<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, data:offset
@@ -716,12 +935,26 @@ container editor-data [
     cursor-row:address:number/deref<span class="Special"> &lt;- </span>subtract cursor-row:address:number/deref, <span class="Constant">1:literal</span>
     <span class="Comment"># that's it; render will adjust cursor-column as necessary</span>
   <span class="Delimiter">}</span>
+  <span class="Comment"># home</span>
+  <span class="Delimiter">{</span>
+    home?:boolean<span class="Special"> &lt;- </span>equal k:address:number/deref, <span class="Constant">65521:literal/home</span>
+    <span class="muControl">break-unless</span> home?:boolean
+    move-to-start-of-line editor:address:editor-data
+    <span class="muControl">reply</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># end</span>
+  <span class="Delimiter">{</span>
+    end?:boolean<span class="Special"> &lt;- </span>equal k:address:number/deref, <span class="Constant">65520:literal/end</span>
+    <span class="muControl">break-unless</span> end?:boolean
+    move-to-end-of-line editor:address:editor-data
+    <span class="muControl">reply</span>
+  <span class="Delimiter">}</span>
 ]
 
 <span class="Comment"># process click, return if it was on current editor</span>
 <span class="Comment"># todo: ignores menu bar (for now just displays shortcuts)</span>
 <span class="muRecipe">recipe</span> move-cursor-in-editor [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   t:touch-event<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -738,18 +971,16 @@ container editor-data [
   cursor-row:address:number/deref<span class="Special"> &lt;- </span>get t:touch-event, row:offset
   cursor-column:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-column:offset
   cursor-column:address:number/deref<span class="Special"> &lt;- </span>get t:touch-event, column:offset
-  render screen:address, editor:address:editor-data
   <span class="Comment"># gain focus</span>
   <span class="muControl">reply</span> <span class="Constant">1:literal/true</span>
 ]
 
 <span class="muRecipe">recipe</span> insert-at-cursor [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-<span class="CommentedCode">#?   $print [insert ], c:character, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print [insert ], c:character, 10:literal/newline</span>
   before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, before-cursor:offset
   d:address:duplex-list<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, data:offset
   insert-duplex c:character, before-cursor:address:address:duplex-list/deref
@@ -771,8 +1002,7 @@ container editor-data [
   <span class="Delimiter">{</span>
     <span class="Comment"># if we're at the column just before the wrap indicator</span>
     wrap-column:number<span class="Special"> &lt;- </span>subtract right:number, <span class="Constant">1:literal</span>
-<span class="CommentedCode">#?     $print [wrap? ], cursor-column:address:number/deref, [ vs ], wrap-column:number, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?     $print [wrap? ], cursor-column:address:number/deref, [ vs ], wrap-column:number, 10:literal/newline</span>
     at-wrap?:boolean<span class="Special"> &lt;- </span>greater-or-equal cursor-column:address:number/deref, wrap-column:number
     <span class="muControl">break-unless</span> at-wrap?:boolean
 <span class="CommentedCode">#?     $print [wrap!</span>
@@ -792,7 +1022,7 @@ container editor-data [
 ]
 
 <span class="muRecipe">recipe</span> delete-before-cursor [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, before-cursor:offset
   d:address:duplex-list<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, data:offset
@@ -806,14 +1036,13 @@ container editor-data [
   before-cursor:address:address:duplex-list/deref<span class="Special"> &lt;- </span>copy prev:address:duplex-list
   cursor-column:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-column:offset
   cursor-column:address:number/deref<span class="Special"> &lt;- </span>subtract cursor-column:address:number/deref, <span class="Constant">1:literal</span>
-<span class="CommentedCode">#?   $print [delete-before-cursor: ], cursor-column:address:number/deref, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   $print [delete-before-cursor: ], cursor-column:address:number/deref, 10:literal/newline</span>
 ]
 
 <span class="Comment"># takes a pointer 'curr' into the doubly-linked list and its sentinel, counts</span>
 <span class="Comment"># the length of the previous line before the 'curr' pointer.</span>
 <span class="muRecipe">recipe</span> previous-line-length [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   curr:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   start:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   result:number<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
@@ -834,24 +1063,159 @@ container editor-data [
   <span class="muControl">reply</span> result:number
 ]
 
+<span class="muRecipe">recipe</span> move-to-start-of-line [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># update cursor column</span>
+  left:number<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, left:offset
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-column:offset
+  cursor-column:address:number/deref<span class="Special"> &lt;- </span>copy left:number
+  <span class="Comment"># update before-cursor</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, before-cursor:offset
+  init:address:duplex-list<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, data:offset
+  <span class="Comment"># while not at start of line, move </span>
+  <span class="Delimiter">{</span>
+    at-start-of-text?:boolean<span class="Special"> &lt;- </span>equal before-cursor:address:address:duplex-list/deref, init:address:duplex-list
+    <span class="muControl">break-if</span> at-start-of-text?:boolean
+    prev:character<span class="Special"> &lt;- </span>get before-cursor:address:address:duplex-list/deref/deref, value:offset
+    at-start-of-line?:boolean<span class="Special"> &lt;- </span>equal prev:character, <span class="Constant">10:literal/newline</span>
+    <span class="muControl">break-if</span> at-start-of-line?:boolean
+    before-cursor:address:address:duplex-list/deref<span class="Special"> &lt;- </span>prev-duplex before-cursor:address:address:duplex-list/deref
+    assert before-cursor:address:address:duplex-list/deref, <span class="Constant">[move-to-start-of-line tried to move before start of text]</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> move-to-end-of-line [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, before-cursor:offset
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-column:offset
+  <span class="Comment"># while not at start of line, move </span>
+  <span class="Delimiter">{</span>
+    next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex before-cursor:address:address:duplex-list/deref
+    <span class="muControl">break-unless</span> next:address:duplex-list  <span class="Comment"># end of text</span>
+    nextc:character<span class="Special"> &lt;- </span>get next:address:duplex-list/deref, value:offset
+    at-end-of-line?:boolean<span class="Special"> &lt;- </span>equal nextc:character, <span class="Constant">10:literal/newline</span>
+    <span class="muControl">break-if</span> at-end-of-line?:boolean
+    before-cursor:address:address:duplex-list/deref<span class="Special"> &lt;- </span>copy next:address:duplex-list
+    cursor-column:address:number/deref<span class="Special"> &lt;- </span>add cursor-column:address:number/deref, <span class="Constant">1:literal</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># move one past end of line</span>
+  cursor-column:address:number/deref<span class="Special"> &lt;- </span>add cursor-column:address:number/deref, <span class="Constant">1:literal</span>
+]
+
+<span class="muRecipe">recipe</span> delete-to-start-of-line [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># compute range to delete</span>
+  init:address:duplex-list<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, data:offset
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, before-cursor:offset
+  start:address:duplex-list<span class="Special"> &lt;- </span>copy before-cursor:address:address:duplex-list/deref
+  end:address:duplex-list<span class="Special"> &lt;- </span>next-duplex before-cursor:address:address:duplex-list/deref
+  <span class="Delimiter">{</span>
+    at-start-of-text?:boolean<span class="Special"> &lt;- </span>equal start:address:duplex-list, init:address:duplex-list
+    <span class="muControl">break-if</span> at-start-of-text?:boolean
+    curr:character<span class="Special"> &lt;- </span>get start:address:duplex-list/deref, value:offset
+    at-start-of-line?:boolean<span class="Special"> &lt;- </span>equal curr:character, <span class="Constant">10:literal/newline</span>
+    <span class="muControl">break-if</span> at-start-of-line?:boolean
+    start:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex start:address:duplex-list
+    assert start:address:duplex-list, <span class="Constant">[delete-to-start-of-line tried to move before start of text]</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># snip it out</span>
+  start-next:address:address:duplex-list<span class="Special"> &lt;- </span>get-address start:address:duplex-list/deref, next:offset
+  start-next:address:address:duplex-list/deref<span class="Special"> &lt;- </span>copy end:address:duplex-list
+  end-prev:address:address:duplex-list<span class="Special"> &lt;- </span>get-address end:address:duplex-list/deref, prev:offset
+  end-prev:address:address:duplex-list/deref<span class="Special"> &lt;- </span>copy start:address:duplex-list
+  <span class="Comment"># adjust cursor</span>
+  before-cursor:address:address:duplex-list/deref<span class="Special"> &lt;- </span>prev-duplex end:address:duplex-list
+  left:number<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, left:offset
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-column:offset
+  cursor-column:address:number/deref<span class="Special"> &lt;- </span>copy left:number
+]
+
+<span class="muRecipe">recipe</span> delete-to-end-of-line [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># compute range to delete</span>
+  start:address:duplex-list<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, before-cursor:offset
+  end:address:duplex-list<span class="Special"> &lt;- </span>next-duplex start:address:duplex-list
+  <span class="Delimiter">{</span>
+    at-end-of-text?:boolean<span class="Special"> &lt;- </span>equal end:address:duplex-list, <span class="Constant">0:literal/null</span>
+    <span class="muControl">break-if</span> at-end-of-text?:boolean
+    curr:character<span class="Special"> &lt;- </span>get end:address:duplex-list/deref, value:offset
+    at-end-of-line?:boolean<span class="Special"> &lt;- </span>equal curr:character, <span class="Constant">10:literal/newline</span>
+    <span class="muControl">break-if</span> at-end-of-line?:boolean
+    end:address:duplex-list<span class="Special"> &lt;- </span>next-duplex end:address:duplex-list
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># snip it out</span>
+  start-next:address:address:duplex-list<span class="Special"> &lt;- </span>get-address start:address:duplex-list/deref, next:offset
+  start-next:address:address:duplex-list/deref<span class="Special"> &lt;- </span>copy end:address:duplex-list
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> end:address:duplex-list
+    end-prev:address:address:duplex-list<span class="Special"> &lt;- </span>get-address end:address:duplex-list/deref, prev:offset
+    end-prev:address:address:duplex-list/deref<span class="Special"> &lt;- </span>copy start:address:duplex-list
+  <span class="Delimiter">}</span>
+]
+
 <span class="muRecipe">recipe</span> render-all [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen:address<span class="Special"> &lt;- </span>render-recipes screen:address, env:address:programming-environment-data
+  screen:address<span class="Special"> &lt;- </span>render-sandbox-side screen:address, env:address:programming-environment-data
+  recipes:address:editor-data<span class="Special"> &lt;- </span>get env:address:programming-environment-data/deref, recipes:offset
+  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get env:address:programming-environment-data/deref, current-sandbox:offset
+  sandbox-in-focus?:boolean<span class="Special"> &lt;- </span>get env:address:programming-environment-data/deref, sandbox-in-focus?:offset
+  update-cursor screen:address, recipes:address:editor-data, current-sandbox:address:editor-data, sandbox-in-focus?:boolean
+  show-screen screen:address
+  <span class="muControl">reply</span> screen:address/same-as-ingredient:0
+]
+
+<span class="muRecipe">recipe</span> render-minimal [
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   recipes:address:editor-data<span class="Special"> &lt;- </span>get env:address:programming-environment-data/deref, recipes:offset
   current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get env:address:programming-environment-data/deref, current-sandbox:offset
   sandbox-in-focus?:boolean<span class="Special"> &lt;- </span>get env:address:programming-environment-data/deref, sandbox-in-focus?:offset
-  <span class="Comment"># render recipes, along with any warnings</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> sandbox-in-focus?:boolean
+    screen:address<span class="Special"> &lt;- </span>render-recipes screen:address, env:address:programming-environment-data
+    cursor-row:number<span class="Special"> &lt;- </span>get recipes:address:editor-data/deref, cursor-row:offset
+    cursor-column:number<span class="Special"> &lt;- </span>get recipes:address:editor-data/deref, cursor-column:offset
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> sandbox-in-focus?:boolean
+    screen:address<span class="Special"> &lt;- </span>render-sandbox-side screen:address, env:address:programming-environment-data
+    cursor-row:number<span class="Special"> &lt;- </span>get current-sandbox:address:editor-data/deref, cursor-row:offset
+    cursor-column:number<span class="Special"> &lt;- </span>get current-sandbox:address:editor-data/deref, cursor-column:offset
+  <span class="Delimiter">}</span>
+  move-cursor screen:address, cursor-row:number, cursor-column:number
+  show-screen screen:address
+  <span class="muControl">reply</span> screen:address/same-as-ingredient:0
+]
+
+<span class="muRecipe">recipe</span> render-recipes [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  recipes:address:editor-data<span class="Special"> &lt;- </span>get env:address:programming-environment-data/deref, recipes:offset
+  <span class="Comment"># render recipes</span>
   left:number<span class="Special"> &lt;- </span>get recipes:address:editor-data/deref, left:offset
   right:number<span class="Special"> &lt;- </span>get recipes:address:editor-data/deref, right:offset
   row:number, screen:address<span class="Special"> &lt;- </span>render screen:address, recipes:address:editor-data
   recipe-warnings:address:array:character<span class="Special"> &lt;- </span>get env:address:programming-environment-data/deref, recipe-warnings:offset
   <span class="Delimiter">{</span>
+    <span class="Comment"># print any warnings</span>
     <span class="muControl">break-unless</span> recipe-warnings:address:array:character
     row:number, screen:address<span class="Special"> &lt;- </span>render-string screen:address, recipe-warnings:address:array:character, left:number, right:number, <span class="Constant">1:literal/red</span>, row:number
   <span class="Delimiter">}</span>
   <span class="Delimiter">{</span>
-    <span class="Comment"># no warnings? move to next lin</span>
+    <span class="Comment"># no warnings? move to next line</span>
     <span class="muControl">break-if</span> recipe-warnings:address:array:character
     row:number<span class="Special"> &lt;- </span>add row:number, <span class="Constant">1:literal</span>
   <span class="Delimiter">}</span>
@@ -861,7 +1225,15 @@ container editor-data [
   row:number<span class="Special"> &lt;- </span>add row:number, <span class="Constant">1:literal</span>
   move-cursor screen:address, row:number, left:number
   clear-line-delimited screen:address, left:number, right:number
-  <span class="Comment"># render sandboxes along with warnings for each</span>
+  <span class="muControl">reply</span> screen:address/same-as-ingredient:0
+]
+
+<span class="muRecipe">recipe</span> render-sandbox-side [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  clear:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get env:address:programming-environment-data/deref, current-sandbox:offset
   left:number<span class="Special"> &lt;- </span>get current-sandbox:address:editor-data/deref, left:offset
   right:number<span class="Special"> &lt;- </span>get current-sandbox:address:editor-data/deref, right:offset
   row:number, screen:address<span class="Special"> &lt;- </span>render screen:address, current-sandbox:address:editor-data
@@ -873,36 +1245,63 @@ container editor-data [
   row:number<span class="Special"> &lt;- </span>add row:number, <span class="Constant">1:literal</span>
   move-cursor screen:address, row:number, left:number
   clear-line-delimited screen:address, left:number, right:number
-  update-cursor screen:address, recipes:address:editor-data, current-sandbox:address:editor-data, sandbox-in-focus?:boolean
-  show-screen screen:address
+  <span class="muControl">reply-unless</span> clear:boolean, screen:address/same-as-ingredient:0
+  screen-height:number<span class="Special"> &lt;- </span>screen-height screen:address
+  <span class="Delimiter">{</span>
+    at-bottom-of-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal row:number, screen-height:number
+    <span class="muControl">break-if</span> at-bottom-of-screen?:boolean
+    move-cursor screen:address, row:number, left:number
+    clear-line-delimited screen:address, left:number, right:number
+    row:number<span class="Special"> &lt;- </span>add row:number, <span class="Constant">1:literal</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
   <span class="muControl">reply</span> screen:address/same-as-ingredient:0
 ]
 
 <span class="muRecipe">recipe</span> render-sandboxes [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   sandbox:address:sandbox-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="muControl">reply-unless</span> sandbox:address:sandbox-data, row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0
-  screen-height:number<span class="Special"> &lt;- </span>screen-width screen:address
+  screen-height:number<span class="Special"> &lt;- </span>screen-height screen:address
   at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal row:number screen-height:number
   <span class="muControl">reply-if</span> at-bottom?:boolean, row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0
+<span class="CommentedCode">#?   $print [rendering sandbox ], sandbox:address:sandbox-data, 10:literal/newline</span>
+  <span class="Comment"># render sandbox menu</span>
+  row:number<span class="Special"> &lt;- </span>add row:number, <span class="Constant">1:literal</span>
+  move-cursor screen:address, row:number, left:number
+  clear-line-delimited screen:address, left:number, right:number
+  print-character screen:address, <span class="Constant">120:literal/x</span>, <span class="Constant">245:literal/grey</span>
+  <span class="Comment"># save menu row so we can detect clicks to it later</span>
+  starting-row:address:number<span class="Special"> &lt;- </span>get-address sandbox:address:sandbox-data/deref, starting-row-on-screen:offset
+  starting-row:address:number/deref<span class="Special"> &lt;- </span>copy row:number
   <span class="Comment"># render sandbox contents</span>
   sandbox-data:address:array:character<span class="Special"> &lt;- </span>get sandbox:address:sandbox-data/deref, data:offset
   row:number, screen:address<span class="Special"> &lt;- </span>render-string screen:address, sandbox-data:address:array:character, left:number, right:number, <span class="Constant">7:literal/white</span>, row:number
-  <span class="Comment"># render sandbox warnings or response, in that order</span>
+  <span class="Comment"># render sandbox warnings, screen or response, in that order</span>
   sandbox-response:address:array:character<span class="Special"> &lt;- </span>get sandbox:address:sandbox-data/deref, response:offset
   sandbox-warnings:address:array:character<span class="Special"> &lt;- </span>get sandbox:address:sandbox-data/deref, warnings:offset
+  sandbox-screen:address<span class="Special"> &lt;- </span>get sandbox:address:sandbox-data/deref, screen:offset
   <span class="Delimiter">{</span>
     <span class="muControl">break-unless</span> sandbox-warnings:address:array:character
     row:number, screen:address<span class="Special"> &lt;- </span>render-string screen:address, sandbox-warnings:address:array:character, left:number, right:number, <span class="Constant">1:literal/red</span>, row:number
   <span class="Delimiter">}</span>
   <span class="Delimiter">{</span>
     <span class="muControl">break-if</span> sandbox-warnings:address:array:character
+    empty-screen?:boolean<span class="Special"> &lt;- </span>fake-screen-is-clear? sandbox-screen:address
+    <span class="muControl">break-if</span> empty-screen?:boolean
+    row:number, screen:address<span class="Special"> &lt;- </span>render-screen screen:address, sandbox-screen:address, left:number, right:number, row:number
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> sandbox-warnings:address:array:character
+    <span class="muControl">break-unless</span> empty-screen?:boolean
     row:number, screen:address<span class="Special"> &lt;- </span>render-string screen:address, sandbox-response:address:array:character, left:number, right:number, <span class="Constant">245:literal/grey</span>, row:number
   <span class="Delimiter">}</span>
+  at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal row:number screen-height:number
+  <span class="muControl">reply-if</span> at-bottom?:boolean, row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0
   <span class="Comment"># draw solid line after sandbox</span>
   draw-horizontal screen:address, row:number, left:number, right:number, <span class="Constant">9473:literal/horizontal-double</span>
   <span class="Comment"># draw next sandbox</span>
@@ -912,7 +1311,7 @@ container editor-data [
 ]
 
 <span class="muRecipe">recipe</span> update-cursor [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   recipes:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   current-sandbox:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -1774,6 +2173,425 @@ d]
   ]
 ]
 
+<span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-ctrl-a [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start on second line, press ctrl-a</span>
+  assume-console [
+    left-click 2, 3
+    type <span class="Constant">[a]</span>  <span class="Comment"># ctrl-a</span>
+  ]
+  3:event/ctrl-a<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">1:literal/ctrl-a</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">97:literal/a</span>, 3:event/ctrl-a
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    5:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  <span class="Comment"># cursor moves to start of line</span>
+  memory-should-contain [
+    4<span class="Special"> &lt;- </span>2
+    5<span class="Special"> &lt;- </span>0
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-ctrl-a-2 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start on first line (no newline before), press ctrl-a</span>
+  assume-console [
+    left-click 1, 3
+    type <span class="Constant">[a]</span>  <span class="Comment"># ctrl-a</span>
+  ]
+  3:event/ctrl-a<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">1:literal/ctrl-a</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">97:literal/a</span>, 3:event/ctrl-a
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    5:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  <span class="Comment"># cursor moves to start of line</span>
+  memory-should-contain [
+    4<span class="Special"> &lt;- </span>1
+    5<span class="Special"> &lt;- </span>0
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-home [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start on second line, press 'home'</span>
+  assume-console [
+    left-click 2, 3
+    press 65521  <span class="Comment"># 'home'</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  <span class="Comment"># cursor moves to start of line</span>
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>2
+    4<span class="Special"> &lt;- </span>0
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-home-2 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start on first line (no newline before), press 'home'</span>
+  assume-console [
+    left-click 1, 3
+    press 65521  <span class="Comment"># 'home'</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  <span class="Comment"># cursor moves to start of line</span>
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>1
+    4<span class="Special"> &lt;- </span>0
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-ctrl-e [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start on first line, press ctrl-e</span>
+  assume-console [
+    left-click 1, 1
+    type <span class="Constant">[e]</span>  <span class="Comment"># ctrl-e</span>
+  ]
+  3:event/ctrl-e<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">5:literal/ctrl-e</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">101:literal/e</span>, 3:event/ctrl-e
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    5:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  <span class="Comment"># cursor moves to end of line</span>
+  memory-should-contain [
+    4<span class="Special"> &lt;- </span>1
+    5<span class="Special"> &lt;- </span>3
+  ]
+  <span class="Comment"># editor inserts future characters at cursor</span>
+  assume-console [
+    type <span class="Constant">[z]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    5:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  memory-should-contain [
+    4<span class="Special"> &lt;- </span>1
+    5<span class="Special"> &lt;- </span>4
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .123z      .</span>
+   <span class="Constant"> .456       .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-end-of-line-with-ctrl-e-2 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start on second line (no newline after), press ctrl-e</span>
+  assume-console [
+    left-click 2, 1
+    type <span class="Constant">[e]</span>  <span class="Comment"># ctrl-e</span>
+  ]
+  3:event/ctrl-e<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">5:literal/ctrl-e</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">101:literal/e</span>, 3:event/ctrl-e
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    5:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  <span class="Comment"># cursor moves to end of line</span>
+  memory-should-contain [
+    4<span class="Special"> &lt;- </span>2
+    5<span class="Special"> &lt;- </span>3
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-end-of-line-with-end [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start on first line, press 'end'</span>
+  assume-console [
+    left-click 1, 1
+    press 65520  <span class="Comment"># 'end'</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  <span class="Comment"># cursor moves to end of line</span>
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>1
+    4<span class="Special"> &lt;- </span>3
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-end-of-line-with-end-2 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start on second line (no newline after), press 'end'</span>
+  assume-console [
+    left-click 2, 1
+    press 65520  <span class="Comment"># 'end'</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  <span class="Comment"># cursor moves to end of line</span>
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>2
+    4<span class="Special"> &lt;- </span>3
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-start-of-line-with-ctrl-u [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start on second line, press ctrl-u</span>
+  assume-console [
+    left-click 2, 2
+    type <span class="Constant">[u]</span>  <span class="Comment"># ctrl-u</span>
+  ]
+  3:event/ctrl-a<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">21:literal/ctrl-u</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">117:literal/u</span>, 3:event/ctrl-u
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes to start of line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .123       .</span>
+   <span class="Constant"> .6         .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-start-of-line-with-ctrl-u-2 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start on first line (no newline before), press ctrl-u</span>
+  assume-console [
+    left-click 1, 2
+    type <span class="Constant">[u]</span>  <span class="Comment"># ctrl-u</span>
+  ]
+  3:event/ctrl-u<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">21:literal/ctrl-a</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">117:literal/a</span>, 3:event/ctrl-u
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes to start of line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .3         .</span>
+   <span class="Constant"> .456       .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-start-of-line-with-ctrl-u-3 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start past end of line, press ctrl-u</span>
+  assume-console [
+    left-click 1, 3
+    type <span class="Constant">[u]</span>  <span class="Comment"># ctrl-u</span>
+  ]
+  3:event/ctrl-u<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">21:literal/ctrl-a</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">117:literal/a</span>, 3:event/ctrl-u
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes to start of line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .456       .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start on first line, press ctrl-k</span>
+  assume-console [
+    left-click 1, 1
+    type <span class="Constant">[k]</span>  <span class="Comment"># ctrl-k</span>
+  ]
+  3:event/ctrl-k<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">11:literal/ctrl-k</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">107:literal/k</span>, 3:event/ctrl-k
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes to end of line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .1         .</span>
+   <span class="Constant"> .456       .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-2 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start on second line (no newline after), press ctrl-k</span>
+  assume-console [
+    left-click 2, 1
+    type <span class="Constant">[k]</span>  <span class="Comment"># ctrl-k</span>
+  ]
+  3:event/ctrl-k<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">11:literal/ctrl-k</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">107:literal/k</span>, 3:event/ctrl-k
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes to end of line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .123       .</span>
+   <span class="Constant"> .4         .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-3 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start at end of line</span>
+  assume-console [
+    left-click 1, 2
+    type <span class="Constant">[k]</span>  <span class="Comment"># ctrl-k</span>
+  ]
+  3:event/ctrl-k<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">11:literal/ctrl-k</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">107:literal/k</span>, 3:event/ctrl-k
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes to end of line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .12        .</span>
+   <span class="Constant"> .456       .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-4 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start past end of line</span>
+  assume-console [
+    left-click 1, 3
+    type <span class="Constant">[k]</span>  <span class="Comment"># ctrl-k</span>
+  ]
+  3:event/ctrl-k<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">11:literal/ctrl-k</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">107:literal/k</span>, 3:event/ctrl-k
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes to end of line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .123       .</span>
+   <span class="Constant"> .456       .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-5 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start at end of text</span>
+  assume-console [
+    left-click 2, 2
+    type <span class="Constant">[k]</span>  <span class="Comment"># ctrl-k</span>
+  ]
+  3:event/ctrl-k<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">11:literal/ctrl-k</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">107:literal/k</span>, 3:event/ctrl-k
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes to end of line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .123       .</span>
+   <span class="Constant"> .45        .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-6 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># start past end of text</span>
+  assume-console [
+    left-click 2, 3
+    type <span class="Constant">[k]</span>  <span class="Comment"># ctrl-k</span>
+  ]
+  3:event/ctrl-k<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">11:literal/ctrl-k</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">107:literal/k</span>, 3:event/ctrl-k
+  run [
+    editor-event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes to end of line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .123       .</span>
+   <span class="Constant"> .456       .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
 <span class="muScenario">scenario</span> point-at-multiple-editors [
   assume-screen <span class="Constant">30:literal/width</span>, <span class="Constant">5:literal/height</span>
   <span class="Comment"># initialize both halves of screen</span>
@@ -1852,7 +2670,7 @@ d]
   screen-should-contain [
    <span class="Constant"> .                                         run (F10)          .</span>
    <span class="Constant"> .abc                           ┊def                          .</span>
-   <span class="Constant"> .                              ┊                             .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
    <span class="Constant"> .                              ┊                             .</span>
    <span class="Constant"> .                              ┊                             .</span>
   ]
@@ -1873,8 +2691,7 @@ d]
   screen-should-contain [
    <span class="Constant"> .           run (F10)          .</span>
    <span class="Constant"> .␣bc            ┊def           .</span>
-<span class="Comment"># artifact of fake console: no events = no render</span>
-<span class="Comment">#   .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
    <span class="Constant"> .               ┊              .</span>
   ]
   <span class="Comment"># now try typing a letter</span>
@@ -1901,12 +2718,14 @@ container sandbox-data [
   data:address:array:character
   response:address:array:character
   warnings:address:array:character
+  starting-row-on-screen:number  <span class="Comment"># to track clicks on delete</span>
+  screen:address:screen  <span class="Comment"># prints in the sandbox go here</span>
   next-sandbox:address:sandbox-data
 ]
 
 <span class="muScenario">scenario</span> run-and-show-results [
   $close-trace  <span class="Comment"># trace too long for github</span>
-  assume-screen <span class="Constant">100:literal/width</span>, <span class="Constant">12:literal/height</span>
+  assume-screen <span class="Constant">100:literal/width</span>, <span class="Constant">15:literal/height</span>
   <span class="Comment"># recipe editor is empty</span>
   1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
   <span class="Comment"># sandbox editor contains an instruction without storing outputs</span>
@@ -1924,6 +2743,7 @@ container sandbox-data [
    <span class="Constant"> .                                                                                 run (F10)          .</span>
    <span class="Constant"> .                                                  ┊                                                 .</span>
 <span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
    <span class="Constant"> .                                                  ┊divide-with-remainder 11:literal, 3:literal      .</span>
    <span class="Constant"> .                                                  ┊3                                                .</span>
    <span class="Constant"> .                                                  ┊2                                                .</span>
@@ -1934,16 +2754,18 @@ container sandbox-data [
    <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                   divide-with-remainder 11:literal, 3:literal      .</span>
    <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                                                                    .</span>
   ]
-  screen-should-contain-in-color, <span class="Constant">245:literal/grey</span>, [
+  screen-should-contain-in-color <span class="Constant">245:literal/grey</span>, [
    <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                  ┊                                                 .</span>
 <span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
    <span class="Constant"> .                                                  ┊                                                 .</span>
    <span class="Constant"> .                                                  ┊3                                                .</span>
    <span class="Constant"> .                                                  ┊2                                                .</span>
@@ -1964,9 +2786,11 @@ container sandbox-data [
    <span class="Constant"> .                                                                                 run (F10)          .</span>
    <span class="Constant"> .                                                  ┊                                                 .</span>
 <span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
    <span class="Constant"> .                                                  ┊add 2:literal, 2:literal                         .</span>
    <span class="Constant"> .                                                  ┊4                                                .</span>
    <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
    <span class="Constant"> .                                                  ┊divide-with-remainder 11:literal, 3:literal      .</span>
    <span class="Constant"> .                                                  ┊3                                                .</span>
    <span class="Constant"> .                                                  ┊2                                                .</span>
@@ -1976,19 +2800,21 @@ container sandbox-data [
 ]
 
 <span class="muRecipe">recipe</span> run-sandboxes [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   recipes:address:editor-data<span class="Special"> &lt;- </span>get env:address:programming-environment-data/deref, recipes:offset
   current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get env:address:programming-environment-data/deref, current-sandbox:offset
-  <span class="Comment"># load code from recipe editor, save any warnings</span>
+  <span class="Comment"># copy code from recipe editor, persist, load into mu, save any warnings</span>
   in:address:array:character<span class="Special"> &lt;- </span>editor-contents recipes:address:editor-data
+  save <span class="Constant">[recipes.mu]</span>, in:address:array:character
   recipe-warnings:address:address:array:character<span class="Special"> &lt;- </span>get-address env:address:programming-environment-data/deref, recipe-warnings:offset
   recipe-warnings:address:address:array:character/deref<span class="Special"> &lt;- </span>reload in:address:array:character
   <span class="Comment"># check contents of right editor (sandbox)</span>
   <span class="Delimiter">{</span>
     sandbox-contents:address:array:character<span class="Special"> &lt;- </span>editor-contents current-sandbox:address:editor-data
     <span class="muControl">break-unless</span> sandbox-contents:address:array:character
-    <span class="Comment"># if contents exist, run them and turn them into a new sandbox-data</span>
+    <span class="Comment"># if contents exist, first save them</span>
+    <span class="Comment"># run them and turn them into a new sandbox-data</span>
     new-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>new sandbox-data:type
     data:address:address:array:character<span class="Special"> &lt;- </span>get-address new-sandbox:address:sandbox-data/deref, data:offset
     data:address:address:array:character/deref<span class="Special"> &lt;- </span>copy sandbox-contents:address:array:character
@@ -2001,17 +2827,74 @@ container sandbox-data [
     init:address:address:duplex-list<span class="Special"> &lt;- </span>get-address current-sandbox:address:editor-data/deref, data:offset
     init:address:address:duplex-list/deref<span class="Special"> &lt;- </span>push-duplex <span class="Constant">167:literal/§</span>, <span class="Constant">0:literal/tail</span>
   <span class="Delimiter">}</span>
-  <span class="Comment"># rerun other sandboxes</span>
+  <span class="Comment"># save all sandboxes before running, just in case we die when running</span>
+  curr:address:sandbox-data<span class="Special"> &lt;- </span>get env:address:programming-environment-data/deref, sandbox:offset
+  filename:number<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> curr:address:sandbox-data
+    data:address:address:array:character<span class="Special"> &lt;- </span>get-address curr:address:sandbox-data/deref, data:offset
+    save filename:number, data:address:address:array:character/deref
+    filename:number<span class="Special"> &lt;- </span>add filename:number, <span class="Constant">1:literal</span>
+    curr:address:sandbox-data<span class="Special"> &lt;- </span>get curr:address:sandbox-data/deref, next-sandbox:offset
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># run all sandboxes</span>
   curr:address:sandbox-data<span class="Special"> &lt;- </span>get env:address:programming-environment-data/deref, sandbox:offset
   <span class="Delimiter">{</span>
     <span class="muControl">break-unless</span> curr:address:sandbox-data
     data:address:address:array:character<span class="Special"> &lt;- </span>get-address curr:address:sandbox-data/deref, data:offset
     response:address:address:array:character<span class="Special"> &lt;- </span>get-address curr:address:sandbox-data/deref, response:offset
     warnings:address:address:array:character<span class="Special"> &lt;- </span>get-address curr:address:sandbox-data/deref, warnings:offset
-    response:address:address:array:character/deref, warnings:address:address:array:character/deref<span class="Special"> &lt;- </span>run-interactive data:address:address:array:character/deref
+    fake-screen:address:address:screen<span class="Special"> &lt;- </span>get-address curr:address:sandbox-data/deref, screen:offset
+    response:address:address:array:character/deref, warnings:address:address:array:character/deref, fake-screen:address:address:screen/deref<span class="Special"> &lt;- </span>run-interactive data:address:address:array:character/deref
+<span class="CommentedCode">#?     $print warnings:address:address:array:character/deref, [ ], warnings:address:address:array:character/deref/deref, 10:literal/newline</span>
+    curr:address:sandbox-data<span class="Special"> &lt;- </span>get curr:address:sandbox-data/deref, next-sandbox:offset
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="Comment"># was-deleted?:boolean &lt;- delete-sandbox t:touch-event, env:address:programming-environment-data</span>
+<span class="muRecipe">recipe</span> delete-sandbox [
+  <span class="Constant">local-scope</span>
+  t:touch-event<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  click-column:number<span class="Special"> &lt;- </span>get t:touch-event, column:offset
+  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get env:address:programming-environment-data/deref, current-sandbox:offset
+  right:number<span class="Special"> &lt;- </span>get current-sandbox:address:editor-data/deref, right:offset
+<span class="CommentedCode">#?   $print [comparing column ], click-column:number, [ vs ], right:number, 10:literal/newline</span>
+  at-right?:boolean<span class="Special"> &lt;- </span>equal click-column:number, right:number
+  <span class="muControl">reply-unless</span> at-right?:boolean, <span class="Constant">0:literal/false</span>
+<span class="CommentedCode">#?   $print [trying to delete</span>
+<span class="CommentedCode">#? ] #? 1</span>
+  click-row:number<span class="Special"> &lt;- </span>get t:touch-event, row:offset
+  prev:address:address:sandbox-data<span class="Special"> &lt;- </span>get-address env:address:programming-environment-data/deref, sandbox:offset
+<span class="CommentedCode">#?   $print [prev: ], prev:address:address:sandbox-data, [ -&gt; ], prev:address:address:sandbox-data/deref, 10:literal/newline</span>
+  curr:address:sandbox-data<span class="Special"> &lt;- </span>get env:address:programming-environment-data/deref, sandbox:offset
+  <span class="Delimiter">{</span>
+<span class="CommentedCode">#?     $print [next sandbox</span>
+<span class="CommentedCode">#? ] #? 1</span>
+    <span class="muControl">break-unless</span> curr:address:sandbox-data
+    <span class="Comment"># more sandboxes to check</span>
+    <span class="Delimiter">{</span>
+<span class="CommentedCode">#?       $print [checking</span>
+<span class="CommentedCode">#? ] #? 1</span>
+      target-row:number<span class="Special"> &lt;- </span>get curr:address:sandbox-data/deref, starting-row-on-screen:offset
+<span class="CommentedCode">#?       $print [comparing row ], target-row:number, [ vs ], click-row:number, 10:literal/newline</span>
+      delete-curr?:boolean<span class="Special"> &lt;- </span>equal target-row:number, click-row:number
+      <span class="muControl">break-unless</span> delete-curr?:boolean
+<span class="CommentedCode">#?       $print [found!</span>
+<span class="CommentedCode">#? ] #? 1</span>
+      <span class="Comment"># delete this sandbox, rerender and stop</span>
+      prev:address:address:sandbox-data/deref<span class="Special"> &lt;- </span>get curr:address:sandbox-data/deref, next-sandbox:offset
+<span class="CommentedCode">#?       $print [setting prev: ], prev:address:address:sandbox-data, [ -&gt; ], prev:address:address:sandbox-data/deref, 10:literal/newline</span>
+      <span class="muControl">reply</span> <span class="Constant">1:literal/true</span>
+    <span class="Delimiter">}</span>
+    prev:address:address:sandbox-data<span class="Special"> &lt;- </span>get-address curr:address:sandbox-data/deref, next-sandbox:offset
+<span class="CommentedCode">#?     $print [prev: ], prev:address:address:sandbox-data, [ -&gt; ], prev:address:address:sandbox-data/deref, 10:literal/newline</span>
     curr:address:sandbox-data<span class="Special"> &lt;- </span>get curr:address:sandbox-data/deref, next-sandbox:offset
     <span class="muControl">loop</span>
   <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> <span class="Constant">0:literal/false</span>
 ]
 
 <span class="muScenario">scenario</span> run-updates-results [
@@ -2037,9 +2920,10 @@ container sandbox-data [
    <span class="Constant"> .                                                                                 run (F10)          .</span>
    <span class="Constant"> .                                                  ┊                                                 .</span>
    <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .z:number &lt;- add 2:literal, 2:literal              ┊foo                                              .</span>
-   <span class="Constant"> .]                                                 ┊4                                                .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .z:number &lt;- add 2:literal, 2:literal              ┊                                                x.</span>
+   <span class="Constant"> .]                                                 ┊foo                                              .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4                                                .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
    <span class="Constant"> .                                                  ┊                                                 .</span>
   ]
   <span class="Comment"># make a change (incrementing one of the args to 'add'), then rerun</span>
@@ -2058,9 +2942,10 @@ container sandbox-data [
    <span class="Constant"> .                                                                                 run (F10)          .</span>
    <span class="Constant"> .                                                  ┊                                                 .</span>
    <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .z:number &lt;- add 2:literal, 3:literal              ┊foo                                              .</span>
-   <span class="Constant"> .]                                                 ┊5                                                .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .z:number &lt;- add 2:literal, 3:literal              ┊                                                x.</span>
+   <span class="Constant"> .]                                                 ┊foo                                              .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊5                                                .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
    <span class="Constant"> .                                                  ┊                                                 .</span>
   ]
 ]
@@ -2085,6 +2970,7 @@ container sandbox-data [
    <span class="Constant"> .                                                                                 run (F10)          .</span>
    <span class="Constant"> .                                                  ┊                                                 .</span>
 <span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
    <span class="Constant"> .                                                  ┊get 1234:number, foo:offset                      .</span>
    <span class="Constant"> .                                                  ┊unknown element foo in container number          .</span>
    <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
@@ -2094,12 +2980,14 @@ container sandbox-data [
    <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                   get 1234:number, foo:offset                      .</span>
    <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                                                                    .</span>
   ]
-  screen-should-contain-in-color, <span class="Constant">1:literal/red</span>, [
+  screen-should-contain-in-color <span class="Constant">1:literal/red</span>, [
+   <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                                                                    .</span>
@@ -2107,10 +2995,11 @@ container sandbox-data [
    <span class="Constant"> .                                                   unknown element foo in container number          .</span>
    <span class="Constant"> .                                                                                                    .</span>
   ]
-  screen-should-contain-in-color, <span class="Constant">245:literal/grey</span>, [
+  screen-should-contain-in-color <span class="Constant">245:literal/grey</span>, [
    <span class="Constant"> .                                                                                                    .</span>
    <span class="Constant"> .                                                  ┊                                                 .</span>
 <span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
    <span class="Constant"> .                                                  ┊                                                 .</span>
    <span class="Constant"> .                                                  ┊                                                 .</span>
    <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
@@ -2118,8 +3007,137 @@ container sandbox-data [
   ]
 ]
 
+<span class="muScenario">scenario</span> run-instruction-and-print-warnings-only-once [
+  $close-trace  <span class="Comment"># trace too long for github</span>
+  assume-screen <span class="Constant">100:literal/width</span>, <span class="Constant">10:literal/height</span>
+  <span class="Comment"># left editor is empty</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Comment"># right editor contains an illegal instruction</span>
+  2:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[get 1234:number, foo:offset]</span>
+  3:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, 1:address:array:character, 2:address:array:character
+  <span class="Comment"># run the code in the editors multiple times</span>
+  assume-console [
+    press 65526  <span class="Comment"># F10</span>
+    press 65526  <span class="Comment"># F10</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 3:address:programming-environment-data
+  ]
+  <span class="Comment"># check that screen prints error message just once</span>
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F10)          .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊get 1234:number, foo:offset                      .</span>
+   <span class="Constant"> .                                                  ┊unknown element foo in container number          .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> deleting-sandboxes [
+  $close-trace  <span class="Comment"># trace too long for github</span>
+  assume-screen <span class="Constant">100:literal/width</span>, <span class="Constant">15:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  2:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  3:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, 1:address:array:character, 2:address:array:character
+  <span class="Comment"># run a few commands</span>
+  assume-console [
+    left-click 1, 80
+    type <span class="Constant">[divide-with-remainder 11:literal, 3:literal]</span>
+    press 65526  <span class="Comment"># F10</span>
+    type <span class="Constant">[add 2:literal, 2:literal]</span>
+    press 65526  <span class="Comment"># F10</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 3:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F10)          .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊add 2:literal, 2:literal                         .</span>
+   <span class="Constant"> .                                                  ┊4                                                .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊divide-with-remainder 11:literal, 3:literal      .</span>
+   <span class="Constant"> .                                                  ┊3                                                .</span>
+   <span class="Constant"> .                                                  ┊2                                                .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+  <span class="Comment"># delete second sandbox</span>
+  assume-console [
+    left-click 7, 99
+  ]
+  run [
+    event-loop screen:address, console:address, 3:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F10)          .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊add 2:literal, 2:literal                         .</span>
+   <span class="Constant"> .                                                  ┊4                                                .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+  <span class="Comment"># delete first sandbox</span>
+  assume-console [
+    left-click 3, 99
+  ]
+  run [
+    event-loop screen:address, console:address, 3:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F10)          .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> run-instruction-manages-screen-per-sandbox [
+  $close-trace  <span class="Comment"># trace too long for github #? 1</span>
+  assume-screen <span class="Constant">100:literal/width</span>, <span class="Constant">20:literal/height</span>
+  <span class="Comment"># left editor is empty</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Comment"># right editor contains an illegal instruction</span>
+  2:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[print-integer screen:address, 4]</span>
+  3:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, 1:address:array:character, 2:address:array:character
+  <span class="Comment"># run the code in the editor</span>
+  assume-console [
+    press 65526  <span class="Comment"># F10</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 3:address:programming-environment-data
+  ]
+  <span class="Comment"># check that it prints a little 5x5 toy screen</span>
+  <span class="Comment"># hack: screen address is brittle</span>
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F10)          .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊print-integer screen:address, 4                  .</span>
+   <span class="Constant"> .                                                  ┊screen:                                          .</span>
+   <span class="Constant"> .                                                  ┊  .4    .                                        .</span>
+   <span class="Constant"> .                                                  ┊  .     .                                        .</span>
+   <span class="Constant"> .                                                  ┊  .     .                                        .</span>
+   <span class="Constant"> .                                                  ┊  .     .                                        .</span>
+   <span class="Constant"> .                                                  ┊  .     .                                        .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
 <span class="muRecipe">recipe</span> editor-contents [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   buf:address:buffer<span class="Special"> &lt;- </span>new-buffer <span class="Constant">80:literal</span>
   curr:address:duplex-list<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, data:offset
@@ -2159,7 +3177,7 @@ container sandbox-data [
 <span class="SalientComment">## helpers for drawing editor borders</span>
 
 <span class="muRecipe">recipe</span> draw-box [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   top:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -2187,7 +3205,7 @@ container sandbox-data [
 ]
 
 <span class="muRecipe">recipe</span> draw-horizontal [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   x:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -2219,7 +3237,7 @@ container sandbox-data [
 ]
 
 <span class="muRecipe">recipe</span> draw-vertical [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   col:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   x:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -2246,7 +3264,7 @@ container sandbox-data [
 ]
 
 <span class="muRecipe">recipe</span> draw-top-left [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   top:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -2261,7 +3279,7 @@ container sandbox-data [
 ]
 
 <span class="muRecipe">recipe</span> draw-top-right [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   top:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -2276,7 +3294,7 @@ container sandbox-data [
 ]
 
 <span class="muRecipe">recipe</span> draw-bottom-left [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   bottom:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -2291,7 +3309,7 @@ container sandbox-data [
 ]
 
 <span class="muRecipe">recipe</span> draw-bottom-right [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   bottom:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -2306,7 +3324,7 @@ container sandbox-data [
 ]
 
 <span class="muRecipe">recipe</span> print-string-with-gradient-background [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   color:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
@@ -2316,8 +3334,7 @@ container sandbox-data [
   color-range:number<span class="Special"> &lt;- </span>subtract bg-color2:number, bg-color1:number
   color-quantum:number<span class="Special"> &lt;- </span>divide color-range:number, len:number
 <span class="CommentedCode">#?   close-console #? 2</span>
-<span class="CommentedCode">#?   $print len:number, [, ], color-range:number, [, ], color-quantum:number, [ </span>
-<span class="CommentedCode">#? ] #? 2</span>
+<span class="CommentedCode">#?   $print len:number, [, ], color-range:number, [, ], color-quantum:number, 10:literal/newline</span>
 <span class="CommentedCode">#? #?   $exit #? 3</span>
   bg-color:number<span class="Special"> &lt;- </span>copy bg-color1:number
   i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
@@ -2328,8 +3345,7 @@ container sandbox-data [
     print-character x:address:screen, c:character, color:number, bg-color:number
     i:number<span class="Special"> &lt;- </span>add i:number, <span class="Constant">1:literal</span>
     bg-color:number<span class="Special"> &lt;- </span>add bg-color:number, color-quantum:number
-<span class="CommentedCode">#?     $print [=&gt; ], bg-color:number, [ </span>
-<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?     $print [=&gt; ], bg-color:number, 10:literal/newline</span>
     <span class="muControl">loop</span>
   <span class="Delimiter">}</span>
 <span class="CommentedCode">#?   $exit #? 1</span>
diff --git a/html/factorial.mu.html b/html/factorial.mu.html
index 41a725b6..5545f582 100644
--- a/html/factorial.mu.html
+++ b/html/factorial.mu.html
@@ -34,14 +34,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <span class="Comment"># example program: compute the factorial of 5</span>
 
 <span class="muRecipe">recipe</span> main [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   x:number<span class="Special"> &lt;- </span>factorial <span class="Constant">5:literal</span>
   $print <span class="Constant">[result: ]</span>, x:number, <span class="Constant">[ </span>
 <span class="Constant">]</span>
 ]
 
 <span class="muRecipe">recipe</span> factorial [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   n:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Delimiter">{</span>
     <span class="Comment"># if n=0 return 1</span>
diff --git a/html/tangle.mu.html b/html/tangle.mu.html
index f68a77f3..0e4ec070 100644
--- a/html/tangle.mu.html
+++ b/html/tangle.mu.html
@@ -39,7 +39,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <span class="Comment"># possibilities.</span>
 
 <span class="muRecipe">recipe</span> factorial [
-  <span class="Constant">new-default-space</span>
+  <span class="Constant">local-scope</span>
   n:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Delimiter">{</span>
 <span class="Constant">    +base-case</span>
diff --git a/index.html b/index.html
index 9926243c..40aea7b9 100644
--- a/index.html
+++ b/index.html
@@ -40,8 +40,10 @@ also supports first-class functions and delimited continuations.
 print primitives that inject a screen <em>dependency</em> which can be faked
 for testing.
 <li><a href='html/chessboard.mu.html'>chessboard.mu</a>: putting it all
-together, the big kahuna: a complete console program along with thorough tests
-of its behavior including both screen and keyboard handling.
+together, a little console program along with thorough tests of its behavior
+including both screen and keyboard handling.
+<li><a href='html/edit.mu.html'>edit.mu</a>: the programming environment I
+plan to use to teach programming.
 </ul>
 
 <p><b>Part I</b>: basic infrastructure
@@ -156,12 +158,12 @@ the real screen with fake ones for testing.
 <br/><a href='html/072scenario_screen.cc.html'>072scenario_screen.cc</a>:
 writing tests that check what is printed to screen.
 (<a href='html/073scenario_screen_test.mu.html'>examples</a>)
-<br/><a href='html/074keyboard.mu.html'>074keyboard.mu</a>: helpers that can
-swap the real keyboard with fake ones for testing.
-<br/><a href='html/075scenario_keyboard.cc.html'>075scenario_keyboard.cc</a>:
-writing tests using a fake keyboard.
-(<a href='html/076scenario_keyboard_test.mu.html'>examples</a>)
-<br/><a href='html/077trace_browser.cc.html'>077trace_browser.cc</a>: a
+<br/><a href='html/074console.mu.html'>074console.mu</a>: helpers that can
+swap the real keyboard and mouse with fake ones for testing.
+<br/><a href='html/075scenario_console.cc.html'>075scenario_console.cc</a>:
+writing tests for keyboard and mouse using the fakes.
+(<a href='html/076scenario_console_test.mu.html'>examples</a>)
+<br/><a href='html/080trace_browser.cc.html'>080trace_browser.cc</a>: a
 zoomable UI for inspecting traces generated by mu programs. Allows both
 scanning a high-level view and drilling down into selective details.