about summary refs log tree commit diff stats
path: root/html/061channel.mu.html
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-09-07 10:37:27 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-09-07 10:37:27 -0700
commitf5465e1220d73e237c51897b7d1211ec53b0dc04 (patch)
tree939ee8e57241b8515aede8106c6420e330ace75a /html/061channel.mu.html
parent5ccf2653fb7d31b013f77df4e92e964e45c54f8a (diff)
downloadmu-f5465e1220d73e237c51897b7d1211ec53b0dc04.tar.gz
2177
Diffstat (limited to 'html/061channel.mu.html')
-rw-r--r--html/061channel.mu.html448
1 files changed, 226 insertions, 222 deletions
diff --git a/html/061channel.mu.html b/html/061channel.mu.html
index 0823083a..a52d34f3 100644
--- a/html/061channel.mu.html
+++ b/html/061channel.mu.html
@@ -13,11 +13,15 @@
 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; }
+.muScenario { color: #00af00; }
+.muData { color: #ffff00; }
 .SalientComment { color: #00ffff; }
-.Underlined { color: #c000c0; text-decoration: underline; }
+.muRecipe { color: #ff8700; }
 .Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
 .Special { color: #ff6060; }
-.Identifier { color: #804000; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -30,27 +34,27 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <body>
 <pre id='vimCodeElement'>
 <span class="Comment"># Mu synchronizes using channels rather than locks, like Erlang and Go.</span>
-#
+<span class="Comment">#</span>
 <span class="Comment"># The two ends of a channel will usually belong to different routines, but</span>
 <span class="Comment"># each end should only be used by a single one. Don't try to read from or</span>
 <span class="Comment"># write to it from multiple routines at once.</span>
-#
+<span class="Comment">#</span>
 <span class="Comment"># The key property of channels is that writing to a full channel or reading</span>
 <span class="Comment"># from an empty one will put the current routine in 'waiting' state until the</span>
 <span class="Comment"># operation can be completed.</span>
 
-scenario channel [
+<span class="muScenario">scenario</span> channel [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 3/capacity
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    2:number, 1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">read</span> 1:address:channel
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3/capacity</span>
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    <span class="Constant">2</span>:number, <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>read <span class="Constant">1</span>:address:channel
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>34
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">34</span>
   ]
 ]
 
-container channel [
+<span class="muData">container</span> channel [
   <span class="Comment"># To avoid locking, writer and reader will never write to the same location.</span>
   <span class="Comment"># So channels will include fields in pairs, one for the writer and one for the</span>
   <span class="Comment"># reader.</span>
@@ -59,344 +63,344 @@ container channel [
   <span class="Comment"># A circular buffer contains values from index first-full up to (but not</span>
   <span class="Comment"># including) index first-empty. The reader always modifies it at first-full,</span>
   <span class="Comment"># while the writer always modifies it at first-empty.</span>
-  data:address:<span class="Identifier">array</span>:location
+  data:address:array:location
 ]
 
 <span class="Comment"># result:address:channel &lt;- new-channel capacity:number</span>
-recipe <span class="Identifier">new</span>-channel [
-  <span class="Underlined">local</span>-scope
+<span class="muRecipe">recipe</span> new-channel [
+  <span class="Constant">local-scope</span>
   <span class="Comment"># result = new channel</span>
-  result:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span> channel:<span class="Identifier">type</span>
+  result:address:channel<span class="Special"> &lt;- </span>new <span class="Constant">channel:type</span>
   <span class="Comment"># result.first-full = 0</span>
-  full:address:number<span class="Special"> &lt;- </span>get-address *result, first-full:offset
-  *full<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
+  full:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">first-full:offset</span>
+  *full<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
   <span class="Comment"># result.first-free = 0</span>
-  free:address:number<span class="Special"> &lt;- </span>get-address *result, first-free:offset
-  *free<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
+  free:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">first-free:offset</span>
+  *free<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
   <span class="Comment"># result.data = new location[ingredient+1]</span>
-  capacity:number<span class="Special"> &lt;- </span>next-ingredient
-  capacity<span class="Special"> &lt;- </span>add capacity, 1  <span class="Comment"># unused slot for 'full?' below</span>
-  dest:address:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span>get-address *result, data:offset
-  *dest<span class="Special"> &lt;- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, capacity
-  reply result
+  capacity:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  capacity<span class="Special"> &lt;- </span>add capacity, <span class="Constant">1</span>  <span class="Comment"># unused slot for 'full?' below</span>
+  dest:address:address:array:location<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">data:offset</span>
+  *dest<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, capacity
+  <span class="muControl">reply</span> result
 ]
 
 <span class="Comment"># chan &lt;- write chan:address:channel, val:location</span>
-recipe <span class="Identifier">write</span> [
-  <span class="Underlined">local</span>-scope
-  chan:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  <span class="Identifier">val</span>:location<span class="Special"> &lt;- </span>next-ingredient
-  {
+<span class="muRecipe">recipe</span> write [
+  <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>
     <span class="Comment"># block if chan is full</span>
     full:boolean<span class="Special"> &lt;- </span>channel-full? chan
-    break-unless full
-    full-address:address:number<span class="Special"> &lt;- </span>get-address *chan, first-full:offset
+    <span class="muControl">break-unless</span> full
+    full-address:address:number<span class="Special"> &lt;- </span>get-address *chan, <span class="Constant">first-full:offset</span>
     wait-for-location *full-address
-  }
+  <span class="Delimiter">}</span>
   <span class="Comment"># store val</span>
-  circular-buffer:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span>get *chan, data:offset
-  free:address:number<span class="Special"> &lt;- </span>get-address *chan, first-free:offset
+  circular-buffer:address:array:location<span class="Special"> &lt;- </span>get *chan, <span class="Constant">data:offset</span>
+  free:address:number<span class="Special"> &lt;- </span>get-address *chan, <span class="Constant">first-free:offset</span>
   dest:address:location<span class="Special"> &lt;- </span>index-address *circular-buffer, *free
-  *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">val</span>
+  *dest<span class="Special"> &lt;- </span>copy val
   <span class="Comment"># mark its slot as filled</span>
-  *free<span class="Special"> &lt;- </span>add *free, 1
-  {
+  *free<span class="Special"> &lt;- </span>add *free, <span class="Constant">1</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># wrap free around to 0 if necessary</span>
-    len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *circular-buffer
+    len:number<span class="Special"> &lt;- </span>length *circular-buffer
     at-end?:boolean<span class="Special"> &lt;- </span>greater-or-equal *free, len
-    break-unless at-end?
-    *free<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  }
-  reply chan/same-as-ingredient:0
+    <span class="muControl">break-unless</span> at-end?
+    *free<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> chan/same-as-ingredient:<span class="Constant">0</span>
 ]
 
 <span class="Comment"># result:location, chan &lt;- read chan:address:channel</span>
-recipe <span class="Identifier">read</span> [
-  <span class="Underlined">local</span>-scope
-  chan:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  {
+<span class="muRecipe">recipe</span> read [
+  <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>
     empty?:boolean<span class="Special"> &lt;- </span>channel-empty? chan
-    break-unless empty?
-    free-address:address:number<span class="Special"> &lt;- </span>get-address *chan, first-free:offset
+    <span class="muControl">break-unless</span> empty?
+    free-address:address:number<span class="Special"> &lt;- </span>get-address *chan, <span class="Constant">first-free:offset</span>
     wait-for-location *free-address
-  }
+  <span class="Delimiter">}</span>
   <span class="Comment"># read result</span>
-  full:address:number<span class="Special"> &lt;- </span>get-address *chan, first-full:offset
-  circular-buffer:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span>get *chan, data:offset
+  full:address:number<span class="Special"> &lt;- </span>get-address *chan, <span class="Constant">first-full:offset</span>
+  circular-buffer:address:array:location<span class="Special"> &lt;- </span>get *chan, <span class="Constant">data:offset</span>
   result:location<span class="Special"> &lt;- </span>index *circular-buffer, *full
   <span class="Comment"># mark its slot as empty</span>
-  *full<span class="Special"> &lt;- </span>add *full, 1
-  {
+  *full<span class="Special"> &lt;- </span>add *full, <span class="Constant">1</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># wrap full around to 0 if necessary</span>
-    len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *circular-buffer
+    len:number<span class="Special"> &lt;- </span>length *circular-buffer
     at-end?:boolean<span class="Special"> &lt;- </span>greater-or-equal *full, len
-    break-unless at-end?
-    *full<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  }
-  reply result, chan/same-as-ingredient:0
+    <span class="muControl">break-unless</span> at-end?
+    *full<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> result, chan/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-recipe clear-channel [
-  <span class="Underlined">local</span>-scope
-  chan:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  {
+<span class="muRecipe">recipe</span> clear-channel [
+  <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
-    break-if empty?
-    _, chan<span class="Special"> &lt;- </span><span class="Identifier">read</span> chan
-  }
-  reply chan/same-as-ingredient:0
+    <span class="muControl">break-if</span> empty?
+    _, chan<span class="Special"> &lt;- </span>read chan
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> chan/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-scenario channel-initialization [
+<span class="muScenario">scenario</span> channel-initialization [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 3/capacity
-    2:number<span class="Special"> &lt;- </span>get *1:address:channel, first-full:offset
-    3:number<span class="Special"> &lt;- </span>get *1:address:channel, first-free:offset
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3/capacity</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-full:offset</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>0  <span class="Comment"># first-full</span>
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># first-free</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># first-full</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># first-free</span>
   ]
 ]
 
-scenario channel-<span class="Identifier">write</span>-increments-free [
+<span class="muScenario">scenario</span> channel-write-increments-free [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 3/capacity
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    2:number<span class="Special"> &lt;- </span>get *1:address:channel, first-full:offset
-    3:number<span class="Special"> &lt;- </span>get *1:address:channel, first-free:offset
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3/capacity</span>
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-full:offset</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>0  <span class="Comment"># first-full</span>
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># first-free</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># first-full</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># first-free</span>
   ]
 ]
 
-scenario channel-<span class="Identifier">read</span>-increments-full [
+<span class="muScenario">scenario</span> channel-read-increments-full [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 3/capacity
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    _, 1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">read</span> 1:address:channel
-    2:number<span class="Special"> &lt;- </span>get *1:address:channel, first-full:offset
-    3:number<span class="Special"> &lt;- </span>get *1:address:channel, first-free:offset
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3/capacity</span>
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    _, <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>read <span class="Constant">1</span>:address:channel
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-full:offset</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>1  <span class="Comment"># first-full</span>
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># first-free</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># first-full</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># first-free</span>
   ]
 ]
 
-scenario channel-wrap [
+<span class="muScenario">scenario</span> channel-wrap [
   run [
     <span class="Comment"># channel with just 1 slot</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 1/capacity
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">1/capacity</span>
     <span class="Comment"># write and read a value</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    _, 1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">read</span> 1:address:channel
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    _, <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>read <span class="Constant">1</span>:address:channel
     <span class="Comment"># first-free will now be 1</span>
-    2:number<span class="Special"> &lt;- </span>get *1:address:channel, first-free:offset
-    3:number<span class="Special"> &lt;- </span>get *1:address:channel, first-free:offset
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span>
     <span class="Comment"># write second value, verify that first-free wraps</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    4:number<span class="Special"> &lt;- </span>get *1:address:channel, first-free:offset
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span>
     <span class="Comment"># read second value, verify that first-full wraps</span>
-    _, 1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">read</span> 1:address:channel
-    5:number<span class="Special"> &lt;- </span>get *1:address:channel, first-full:offset
+    _, <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>read <span class="Constant">1</span>:address:channel
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-full:offset</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>1  <span class="Comment"># first-free after first write</span>
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># first-full after first read</span>
-    4<span class="Special"> &lt;- </span>0  <span class="Comment"># first-free after second write, wrapped</span>
-    5<span class="Special"> &lt;- </span>0  <span class="Comment"># first-full after second read, wrapped</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># first-free after first write</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># first-full after first read</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># first-free after second write, wrapped</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># first-full after second read, wrapped</span>
   ]
 ]
 
 <span class="SalientComment">## helpers</span>
 
 <span class="Comment"># An empty channel has first-empty and first-full both at the same value.</span>
-recipe channel-empty? [
-  <span class="Underlined">local</span>-scope
-  chan:address:channel<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> channel-empty? [
+  <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, first-full:offset
-  free:number<span class="Special"> &lt;- </span>get *chan, first-free:offset
+  full:number<span class="Special"> &lt;- </span>get *chan, <span class="Constant">first-full:offset</span>
+  free:number<span class="Special"> &lt;- </span>get *chan, <span class="Constant">first-free:offset</span>
   result:boolean<span class="Special"> &lt;- </span>equal full, free
-  reply result
+  <span class="muControl">reply</span> result
 ]
 
 <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>
-recipe channel-full? [
-  <span class="Underlined">local</span>-scope
-  chan:address:channel<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> channel-full? [
+  <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, first-free:offset
-  tmp<span class="Special"> &lt;- </span>add tmp, 1
-  {
+  tmp:number<span class="Special"> &lt;- </span>get *chan, <span class="Constant">first-free:offset</span>
+  tmp<span class="Special"> &lt;- </span>add tmp, <span class="Constant">1</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># if tmp == chan.capacity, tmp = 0</span>
     len:number<span class="Special"> &lt;- </span>channel-capacity chan
     at-end?:boolean<span class="Special"> &lt;- </span>greater-or-equal tmp, len
-    break-unless at-end?
-    tmp<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  }
+    <span class="muControl">break-unless</span> at-end?
+    tmp<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># return chan.first-full == tmp</span>
-  full:number<span class="Special"> &lt;- </span>get *chan, first-full:offset
+  full:number<span class="Special"> &lt;- </span>get *chan, <span class="Constant">first-full:offset</span>
   result:boolean<span class="Special"> &lt;- </span>equal full, tmp
-  reply result
+  <span class="muControl">reply</span> result
 ]
 
 <span class="Comment"># result:number &lt;- channel-capacity chan:address:channel</span>
-recipe channel-capacity [
-  <span class="Underlined">local</span>-scope
-  chan:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  q:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span>get *chan, data:offset
-  result:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *q
-  reply result
+<span class="muRecipe">recipe</span> channel-capacity [
+  <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, <span class="Constant">data:offset</span>
+  result:number<span class="Special"> &lt;- </span>length *q
+  <span class="muControl">reply</span> result
 ]
 
-scenario channel-<span class="Identifier">new</span>-empty-not-full [
+<span class="muScenario">scenario</span> channel-new-empty-not-full [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 3/capacity
-    2:boolean<span class="Special"> &lt;- </span>channel-empty? 1:address:channel
-    3:boolean<span class="Special"> &lt;- </span>channel-full? 1:address:channel
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3/capacity</span>
+    <span class="Constant">2</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">1</span>:address:channel
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>channel-full? <span class="Constant">1</span>:address:channel
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>1  <span class="Comment"># empty?</span>
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># full?</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># empty?</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># full?</span>
   ]
 ]
 
-scenario channel-<span class="Identifier">write</span>-not-empty [
+<span class="muScenario">scenario</span> channel-write-not-empty [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 3/capacity
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    2:boolean<span class="Special"> &lt;- </span>channel-empty? 1:address:channel
-    3:boolean<span class="Special"> &lt;- </span>channel-full? 1:address:channel
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3/capacity</span>
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    <span class="Constant">2</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">1</span>:address:channel
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>channel-full? <span class="Constant">1</span>:address:channel
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>0  <span class="Comment"># empty?</span>
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># full?</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># empty?</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># full?</span>
   ]
 ]
 
-scenario channel-<span class="Identifier">write</span>-full [
+<span class="muScenario">scenario</span> channel-write-full [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 1/capacity
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    2:boolean<span class="Special"> &lt;- </span>channel-empty? 1:address:channel
-    3:boolean<span class="Special"> &lt;- </span>channel-full? 1:address:channel
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">1/capacity</span>
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    <span class="Constant">2</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">1</span>:address:channel
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>channel-full? <span class="Constant">1</span>:address:channel
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>0  <span class="Comment"># empty?</span>
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># full?</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># empty?</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># full?</span>
   ]
 ]
 
-scenario channel-<span class="Identifier">read</span>-not-full [
+<span class="muScenario">scenario</span> channel-read-not-full [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 1/capacity
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    _, 1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">read</span> 1:address:channel
-    2:boolean<span class="Special"> &lt;- </span>channel-empty? 1:address:channel
-    3:boolean<span class="Special"> &lt;- </span>channel-full? 1:address:channel
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">1/capacity</span>
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    _, <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>read <span class="Constant">1</span>:address:channel
+    <span class="Constant">2</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">1</span>:address:channel
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>channel-full? <span class="Constant">1</span>:address:channel
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>1  <span class="Comment"># empty?</span>
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># full?</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># empty?</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># full?</span>
   ]
 ]
 
 <span class="Comment"># helper for channels of characters in particular</span>
 <span class="Comment"># out &lt;- buffer-lines in:address:channel, out:address:channel</span>
-recipe buffer-lines [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  out:address:channel<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> buffer-lines [
+  <span class="Constant">local-scope</span>
+  in:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  out:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># repeat forever</span>
-  {
-    line:address:buffer<span class="Special"> &lt;- </span><span class="Identifier">new</span>-buffer, 30
+  <span class="Delimiter">{</span>
+    line:address:buffer<span class="Special"> &lt;- </span>new-buffer, <span class="Constant">30</span>
     <span class="Comment"># read characters from 'in' until newline, copy into line</span>
-    {
-      +next-character
-      c:character, <span class="Identifier">in</span><span class="Special"> &lt;- </span><span class="Identifier">read</span> <span class="Identifier">in</span>
+    <span class="Delimiter">{</span>
+<span class="Constant">      +next-character</span>
+      c:character, in<span class="Special"> &lt;- </span>read in
       <span class="Comment"># drop a character on backspace</span>
-      {
+      <span class="Delimiter">{</span>
         <span class="Comment"># special-case: if it's a backspace</span>
-        backspace?:boolean<span class="Special"> &lt;- </span>equal c, 8
-        break-unless backspace?
+        backspace?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">8</span>
+        <span class="muControl">break-unless</span> backspace?
         <span class="Comment"># drop previous character</span>
-        {
-          buffer-<span class="Identifier">length</span>:address:number<span class="Special"> &lt;- </span>get-address *line, <span class="Identifier">length</span>:offset
-          buffer-empty?:boolean<span class="Special"> &lt;- </span>equal *buffer-<span class="Identifier">length</span>, 0
-          break-if buffer-empty?
-          *buffer-<span class="Identifier">length</span><span class="Special"> &lt;- </span>subtract *buffer-<span class="Identifier">length</span>, 1
-        }
+        <span class="Delimiter">{</span>
+          buffer-length:address:number<span class="Special"> &lt;- </span>get-address *line, <span class="Constant">length:offset</span>
+          buffer-empty?:boolean<span class="Special"> &lt;- </span>equal *buffer-length, <span class="Constant">0</span>
+          <span class="muControl">break-if</span> buffer-empty?
+          *buffer-length<span class="Special"> &lt;- </span>subtract *buffer-length, <span class="Constant">1</span>
+        <span class="Delimiter">}</span>
         <span class="Comment"># and don't append this one</span>
-        loop +next-character:label
-      }
+        <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
+      <span class="Delimiter">}</span>
       <span class="Comment"># append anything else</span>
-      line<span class="Special"> &lt;- </span>buffer-<span class="Identifier">append</span> line, c
-      line-done?:boolean<span class="Special"> &lt;- </span>equal c, 10/newline
-      break-if line-done?
+      line<span class="Special"> &lt;- </span>buffer-append line, c
+      line-done?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
+      <span class="muControl">break-if</span> line-done?
       <span class="Comment"># stop buffering on eof (currently only generated by fake console)</span>
-      eof?:boolean<span class="Special"> &lt;- </span>equal c, 0/eof
-      break-if eof?
-      loop
-    }
+      eof?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">0/eof</span>
+      <span class="muControl">break-if</span> eof?
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
     <span class="Comment"># copy line into 'out'</span>
-    i:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-    line-contents:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>get *line, data:offset
-    <span class="Identifier">max</span>:number<span class="Special"> &lt;- </span>get *line, <span class="Identifier">length</span>:offset
-    {
-      done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, <span class="Identifier">max</span>
-      break-if done?
+    i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+    line-contents:address:array:character<span class="Special"> &lt;- </span>get *line, <span class="Constant">data:offset</span>
+    max:number<span class="Special"> &lt;- </span>get *line, <span class="Constant">length:offset</span>
+    <span class="Delimiter">{</span>
+      done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, max
+      <span class="muControl">break-if</span> done?
       c:character<span class="Special"> &lt;- </span>index *line-contents, i
-      out<span class="Special"> &lt;- </span><span class="Identifier">write</span> out, c
-      i<span class="Special"> &lt;- </span>add i, 1
-      loop
-    }
-    loop
-  }
-  reply out/same-as-ingredient:1
+      out<span class="Special"> &lt;- </span>write out, c
+      i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> out/same-as-ingredient:<span class="Constant">1</span>
 ]
 
-scenario buffer-lines-blocks-until-newline [
+<span class="muScenario">scenario</span> buffer-lines-blocks-until-newline [
   run [
-    1:address:channel/stdin<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 10/capacity
-    2:address:channel/buffered-stdin<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 10/capacity
-    3:boolean<span class="Special"> &lt;- </span>channel-empty? 2:address:channel/buffered-stdin
-    <span class="Identifier">assert</span> 3:boolean, [
-F buffer-lines-blocks-until-newline: channel should be empty after init]
+    <span class="Constant">1</span>:address:channel/stdin<span class="Special"> &lt;- </span>new-channel <span class="Constant">10/capacity</span>
+    <span class="Constant">2</span>:address:channel/buffered-stdin<span class="Special"> &lt;- </span>new-channel <span class="Constant">10/capacity</span>
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">2</span>:address:channel/buffered-stdin
+    assert <span class="Constant">3</span>:boolean, [
+F buffer-lines-blocks-until-newline: channel should be empty <span class="muRecipe">after</span> init]
     <span class="Comment"># buffer stdin into buffered-stdin, try to read from buffered-stdin</span>
-    4:number/buffer-routine<span class="Special"> &lt;- </span>start-running buffer-lines:recipe, 1:address:channel/stdin, 2:address:channel/buffered-stdin
-    wait-for-routine 4:number/buffer-routine
-    5:boolean<span class="Special"> &lt;- </span>channel-empty? 2:address:channel/buffered-stdin
-    <span class="Identifier">assert</span> 5:boolean, [
-F buffer-lines-blocks-until-newline: channel should be empty after buffer-lines bring-up]
+    <span class="Constant">4</span>:number/buffer-routine<span class="Special"> &lt;- </span>start-running <span class="Constant">buffer-lines:recipe</span>, <span class="Constant">1</span>:address:channel/stdin, <span class="Constant">2</span>:address:channel/buffered-stdin
+    wait-for-routine <span class="Constant">4</span>:number/buffer-routine
+    <span class="Constant">5</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">2</span>:address:channel/buffered-stdin
+    assert <span class="Constant">5</span>:boolean, [
+F buffer-lines-blocks-until-newline: channel should be empty <span class="muRecipe">after</span> buffer-lines bring-up]
     <span class="Comment"># write 'a'</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 97/a
-    restart 4:number/buffer-routine
-    wait-for-routine 4:number/buffer-routine
-    6:boolean<span class="Special"> &lt;- </span>channel-empty? 2:address:channel/buffered-stdin
-    <span class="Identifier">assert</span> 6:boolean, [
-F buffer-lines-blocks-until-newline: channel should be empty after writing 'a']
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">97/a</span>
+    restart <span class="Constant">4</span>:number/buffer-routine
+    wait-for-routine <span class="Constant">4</span>:number/buffer-routine
+    <span class="Constant">6</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">2</span>:address:channel/buffered-stdin
+    assert <span class="Constant">6</span>:boolean, [
+F buffer-lines-blocks-until-newline: channel should be empty <span class="muRecipe">after</span> writing 'a']
     <span class="Comment"># write 'b'</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 98/b
-    restart 4:number/buffer-routine
-    wait-for-routine 4:number/buffer-routine
-    7:boolean<span class="Special"> &lt;- </span>channel-empty? 2:address:channel/buffered-stdin
-    <span class="Identifier">assert</span> 7:boolean, [
-F buffer-lines-blocks-until-newline: channel should be empty after writing 'b']
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">98/b</span>
+    restart <span class="Constant">4</span>:number/buffer-routine
+    wait-for-routine <span class="Constant">4</span>:number/buffer-routine
+    <span class="Constant">7</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">2</span>:address:channel/buffered-stdin
+    assert <span class="Constant">7</span>:boolean, [
+F buffer-lines-blocks-until-newline: channel should be empty <span class="muRecipe">after</span> writing 'b']
     <span class="Comment"># write newline</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 10/newline
-    restart 4:number/buffer-routine
-    wait-for-routine 4:number/buffer-routine
-    8:boolean<span class="Special"> &lt;- </span>channel-empty? 2:address:channel/buffered-stdin
-    9:boolean/completed?<span class="Special"> &lt;- </span>not 8:boolean
-    <span class="Identifier">assert</span> 9:boolean/completed?, [
-F buffer-lines-blocks-until-newline: channel should contain data after writing newline]
-    trace 1, [test], [reached end]
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">10/newline</span>
+    restart <span class="Constant">4</span>:number/buffer-routine
+    wait-for-routine <span class="Constant">4</span>:number/buffer-routine
+    <span class="Constant">8</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">2</span>:address:channel/buffered-stdin
+    <span class="Constant">9</span>:boolean/completed?<span class="Special"> &lt;- </span>not <span class="Constant">8</span>:boolean
+    assert <span class="Constant">9</span>:boolean/completed?, [
+F buffer-lines-blocks-until-newline: channel should contain data <span class="muRecipe">after</span> writing newline]
+    trace <span class="Constant">1</span>, <span class="Constant">[test]</span>, <span class="Constant">[reached end]</span>
   ]
   trace-should-contain [
     test: reached end