https://github.com/akkartik/mu/blob/master/072recipe.cc
  1 //: So far we've been calling a fixed recipe in each instruction, but we'd
  2 //: also like to make the recipe a variable, pass recipes to "higher-order"
  3 //: recipes, return recipes from recipes and so on.
  4 
  5 :(scenario call_literal_recipe)
  6 def main [
  7   1:num <- call f, 34
  8 ]
  9 def f x:num -> y:num [
 10   local-scope
 11   load-ingredients
 12   y <- copy x
 13 ]
 14 +mem: storing 34 in location 1
 15 
 16 :(before "End Mu Types Initialization")
 17 put(Type_ordinal, "recipe-literal", 0);
 18 // 'recipe' variables can store recipe-literal
 19 type_ordinal recipe = put(Type_ordinal, "recipe", Next_type_ordinal++);
 20 get_or_insert(Type, recipe).name = "recipe";
 21 
 22 :(after "Deduce Missing Type(x, caller)")
 23 if (!x.type)
 24   try_initialize_recipe_literal(x, caller);
 25 :(before "Type Check in Type-ingredient-aware check_or_set_types_by_name")
 26 if (!x.type)
 27   try_initialize_recipe_literal(x, variant);
 28 :(code)
 29 void try_initialize_recipe_literal(reagent& x, const recipe& caller) {
 30   if (x.type) return;
 31   if (!contains_key(Recipe_ordinal, x.name)) return;
 32   if (contains_reagent_with_non_recipe_literal_type(caller, x.name)) return;
 33   x.type = new type_tree("recipe-literal");
 34   x.set_value(get(Recipe_ordinal, x.name));
 35 }
 36 bool contains_reagent_with_non_recipe_literal_type(const recipe& caller, const string& name) {
 37   for (int i = 0;  i < SIZE(caller.steps);  ++i) {
 38     const instruction& inst = caller.steps.at(i);
 39     for (int i = 0;  i < SIZE(inst.ingredients);  ++i)
 40       if (is_matching_non_recipe_literal(inst.ingredients.at(i), name)) return true;
 41     for (int i = 0;  i < SIZE(inst.products);  ++i)
 42       if (is_matching_non_recipe_literal(inst.products.at(i), name)) return true;
 43   }
 44   return false;
 45 }
 46 bool is_matching_non_recipe_literal(const reagent& x, const string& name) {
 47   if (x.name != name) return false;
 48   if (!x.type) return false;
 49   return !x.type->atom || x.type->name != "recipe-literal";
 50 }
 51 
 52 //: It's confusing to use variable names that are also recipe names. Always
 53 //: assume variable types override recipe literals.
 54 :(scenario error_on_recipe_literal_used_as_a_variable)
 55 % Hide_errors = true;
 56 def main [
 57   local-scope
 58   a:bool <- equal break 0
 59   break:bool <- copy 0
 60 ]
 61 +error: main: missing type for 'break' in 'a:bool <- equal break, 0'
 62 
 63 :(before "End Primitive Recipe Declarations")
 64 CALL,
 65 :(before "End Primitive Recipe Numbers")
 66 put(Recipe_ordinal, "call", CALL);
 67 :(before "End Primitive Recipe Checks")
 68 case CALL: {
 69   if (inst.ingredients.empty()) {
 70     raise << maybe(get(Recipe, r).name) << "'call' requires at least one ingredient (the recipe to call)\n" << end();
 71     break;
 72   }
 73   if (!is_mu_recipe(inst.ingredients.at(0))) {
 74     raise << maybe(get(Recipe, r).name) << "first ingredient of 'call' should be a recipe, but got '" << inst.ingredients.at(0).original_string << "'\n" << end();
 75     break;
 76   }
 77   break;
 78 }
 79 :(before "End Primitive Recipe Implementations")
 80 case CALL: {
 81   // Begin Call
 82   if (Trace_stream) {
 83     ++Trace_stream->callstack_depth;
 84     trace("trace") << "indirect 'call': incrementing callstack depth to " << Trace_stream->callstack_depth << end();
 85     assert(Trace_stream->callstack_depth < 9000);  // 9998-101 plus cushion
 86   }
 87   if (!ingredients.at(0).at(0)) {
 88     raise << maybe(current_recipe_name()) << "tried to call empty recipe in '" << to_string(current_instruction()) << "'" << end();
 89     break;
 90   }
 91   const call& caller_frame = current_call();
 92   instruction/*copy*/ call_instruction = to_instruction(caller_frame);
 93   call_instruction.operation = ingredients.at(0).at(0);
 94   call_instruction.ingredients.erase(call_instruction.ingredients.begin());
 95   Current_routine->calls.push_front(call(ingredients.at(0).at(0)));
 96   ingredients.erase(ingredients.begin());  // drop the callee
 97   finish_call_housekeeping(call_instruction, ingredients);
 98   // not done with caller
 99   write_products = false;
100   fall_through_to_next_instruction = false;
101   break;
102 }
103 
104 :(scenario call_variable)
105 def main [
106   {1: (recipe number -> number)} <- copy f
107   2:num <- call {1: (recipe number -> number)}, 34
108 ]
109 def f x:num -> y:num [
110   local-scope
111   load-ingredients
112   y <- copy x
113 ]
114 +mem: storing 34 in location 2
115 
116 :(scenario call_literal_recipe_repeatedly)
117 def main [
118   1:num <- call f, 34
119   1:num <- call f, 35
120 ]
121 def f x:num -> y:num [
122   local-scope
123   load-ingredients
124   y <- copy x
125 ]
126 +mem: storing 34 in location 1
127 +mem: storing 35 in location 1
128 
129 :(scenario call_shape_shifting_recipe)
130 def main [
131   1:num <- call f, 34
132 ]
133 def f x:_elem -> y:_elem [
134   local-scope
135   load-ingredients
136   y <- copy x
137 ]
138 +mem: storing 34 in location 1
139 
140 :(scenario call_shape_shifting_recipe_inside_shape_shifting_recipe)
141 def main [
142   1:num <- f 34
143 ]
144 def f x:_elem -> y:_elem [
145   local-scope
146   load-ingredients
147   y <- call g x
148 ]
149 def g x:_elem -> y:_elem [
150   local-scope
151   load-ingredients
152   y <- copy x
153 ]
154 +mem: storing 34 in location 1
155 
156 :(scenario call_shape_shifting_recipe_repeatedly_inside_shape_shifting_recipe)
157 def main [
158   1:num <- f 34
159 ]
160 def f x:_elem -> y:_elem [
161   local-scope
162   load-ingredients
163   y <- call g x
164   y <- call g x
165 ]
166 def g x:_elem -> y:_elem [
167   local-scope
168   load-ingredients
169   y <- copy x
170 ]
171 +mem: storing 34 in location 1
172 
173 //:: check types for 'call' instructions
174 
175 :(scenario call_check_literal_recipe)
176 % Hide_errors = true;
177 def main [
178   1:num <- call f, 34
179 ]
180 def f x:point -> y:point [
181   local-scope
182   load-ingredients
183   y <- copy x
184 ]
185 +error: main: ingredient 0 has the wrong type at '1:num <- call f, 34'
186 +error: main: product 0 has the wrong type at '1:num <- call f, 34'
187 
188 :(scenario call_check_variable_recipe)
189 % Hide_errors = true;
190 def main [
191   {1: (recipe point -> point)} <- copy f
192   2:num <- call {1: (recipe point -> point)}, 34
193 ]
194 def f x:point -> y:point [
195   local-scope
196   load-ingredients
197   y <- copy x
198 ]
199 +error: main: ingredient 0 has the wrong type at '2:num <- call {1: (recipe point -> point)}, 34'
200 +error: main: product 0 has the wrong type at '2:num <- call {1: (recipe point -> point)}, 34'
201 
202 :(before "End resolve_ambiguous_call(r, index, inst, caller_recipe) Special-cases")
203 if (inst.name == "call" && !inst.ingredients.empty() && is_recipe_literal(inst.ingredients.at(0))) {
204   resolve_indirect_ambiguous_call(r, index, inst, caller_recipe);
205   return;
206 }
207 :(code)
208 bool is_recipe_literal(const reagent& x) {
209   return x.type && x.type->atom && x.type->name == "recipe-literal";
210 }
211 void resolve_indirect_ambiguous_call(const recipe_ordinal r, int index, instruction& inst, const recipe& caller_recipe) {
212   instruction inst2;
213   inst2.name = inst.ingredients.at(0).name;
214   for (int i = /*skip recipe*/1;  i < SIZE(inst.ingredients);  ++i)
215     inst2.ingredients.push_back(inst.ingredients.at(i));
216   for (int i = 0;  i < SIZE(inst.products);  ++i)
217     inst2.products.push_back(inst.products.at(i));
218   resolve_ambiguous_call(r, index, inst2, caller_recipe);
219   inst.ingredients.at(0).name = inst2.name;
220   inst.ingredients.at(0).set_value(get(Recipe_ordinal, inst2.name));
221 }
222 
223 :(after "Transform.push_back(check_instruction)")
224 Transform.push_back(check_indirect_calls_against_header);  // idempotent
225 :(code)
226 void check_indirect_calls_against_header(const recipe_ordinal r) {
227   trace(9991, "transform") << "--- type-check 'call' instructions inside recipe " << get(Recipe, r).name << end();
228   const recipe& caller = get(Recipe, r);
229   for (int i = 0;  i < SIZE(caller.steps);  ++i) {
230     const instruction& inst = caller.steps.at(i);
231     if (!is_indirect_call(inst.operation)) continue;
232     if (inst.ingredients.empty()) continue;  // error raised above
233     const reagent& callee = inst.ingredients.at(0);
234     if (!is_mu_recipe(callee)) continue;  // error raised above
235     const recipe callee_header = is_literal(callee) ? get(Recipe, callee.value) : from_reagent(inst.ingredients.at(0));
236     pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
<!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 - same-fringe.mu</title>
<meta name="Generator" content="Vim/8.0">
<meta name="plugin-version" content="vim7.4_v2">
<meta name="syntax" content="none">
<meta name="settings" content="number_lines,use_css,pre_wrap,no_foldcolumn,expand_tabs,line_ids,prevent_copy=">
<meta name="colorscheme" content="minimal-light">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #c6c6c6; }
body { font-size:12pt; font-family: monospace; color: #000000; background-color: #c6c6c6; }
a { color:inherit; }
* { font-size:12pt; font-size: 1em; }
.muControl { color: #804000; }
.muRecipe { color: #ff8700; }
.LineNr { }
.muData { color: #ffff00; }
.Delimiter { color: #c000c0; }
.Constant { color: #008787; }
.Special { color: #ff6060; }
.Comment { color: #005faf; }
-->
</style>

<script type='text/javascript'>
<!--

/* function to open any folds containing a jumped-to line before jumping to it */
function JumpToLine()
{
  var lineNum;
  lineNum = window.location.hash;
  lineNum = lineNum.substr(1); /* strip off '#' */

  if (lineNum.indexOf('L') == -1) {
    lineNum = 'L'+lineNum;
  }
  lineElem = document.getElementById(lineNum);
  /* Always jump to new location even if the line was hidden inside a fold, or
   * we corrected the raw number to a line ID.
   */
  if (lineElem) {
    lineElem.scrollIntoView(true);
  }
  return true;
}
if ('onhashchange' in window) {
  window.onhashchange = JumpToLine;
}

-->
</script>
</head>
<body onload='JumpToLine();'>
<a href='https://github.com/akkartik/mu/blob/master/same-fringe.mu'>https://github.com/akkartik/mu/blob/master/same-fringe.mu</a>
<pre id='vimCodeElement'>
<span id="L1" class="LineNr"> 1 </span><span class="Comment"># The 'same fringe' problem: <a href="http://wiki.c2.com/?SameFringeProblem">http://wiki.c2.com/?SameFringeProblem</a></span>
<span id="L2" class="LineNr"> 2 </span><span class="Comment"># Example program demonstrating coroutines using Mu's delimited continuations.</span>
<span id="L3" class="LineNr"> 3 </span><span class="Comment">#</span>
<span id="L4" class="LineNr"> 4 </span><span class="Comment"># Expected output:</span>
<span id="L5" class="LineNr"> 5 </span><span class="Comment">#   1</span>
<span id="L6" class="LineNr"> 6 </span><span class="Comment"># (i.e. that the two given trees x and y have the same leaves, in the same</span>
<span id="L7" class="LineNr"> 7 </span><span class="Comment"># order from left to right)</span>
<span id="L8" class="LineNr"> 8 </span>
<span id="L9" class="LineNr"> 9 </span><span class="muData">container</span> <a href='same-fringe.mu.html#L9'>tree</a>:_elem [
<span id="L10" class="LineNr">10 </span>  val:_elem
<span id="L11" class="LineNr">11 </span>  left:&amp;:<a href='same-fringe.mu.html#L9'>tree</a>:_elem
<span id="L12" class="LineNr">12 </span>  right:&amp;:<a href='same-fringe.mu.html#L9'>tree</a>:_elem
<span id="L13" class="LineNr">13 </span>]
<span id="L14" class="LineNr">14 </span>
<span id="L15" class="LineNr">15 </span><span class="muRecipe">def</span> <a href='same-fringe.mu.html#L15'>main</a> [
<span id="L16" class="LineNr">16 </span>  <span class="Constant">local-scope</span>
<span id="L17" class="LineNr">17 </span>  <span class="Comment"># x: ((a b) c)</span>
<span id="L18" class="LineNr">18 </span>  <span class="Comment"># y: (a (b c))</span>
<span id="L19" class="LineNr">19 </span>  a:&amp;:<a href='same-fringe.mu.html#L9'>tree</a>:num <span class="Special">&lt;-</span> new-tree<span class="Constant"> 3</span>
<span id="L20" class="LineNr">20 </span>  b:&amp;:<a href='same-fringe.mu.html#L9'>tree</a>:num <span class="Special">&lt;-</span> new-tree<span class="Constant"> 4</span>
<span id="L21" class="LineNr">21 </span>  c:&amp;:<a href='same-fringe.mu.html#L9'>tree</a>:num <span class="Special">&lt;-</span> new-tree<span class="Constant"> 5</span>
<span id="L22" class="LineNr">22 </span>  x1:&amp;:<a href='same-fringe.mu.html#L9'>tree</a>:num <span class="Special">&lt;-</span> new-tree a, b
<span id="L23" class="LineNr">23 </span>  x:&amp;:<a href='same-fringe.mu.html#L9'>tree</a>:num <span class="Special">&lt;-</span> new-tree x1, c
<span id="L24" class="LineNr">24 </span>  y1:&amp;:<a href='same-fringe.mu.html#L9'>tree</a>:num <span class="Special">&lt;-</span> new-tree b, c
<span id="L25" class="LineNr">25 </span>  y:&amp;:<a href='same-fringe.mu.html#L9'>tree</a>:num <span class="Special">&lt;-</span> new-tree a, y1
<span id="L26" class="LineNr">26 </span>  result:bool <span class="Special">&lt;-</span> <a href='same-fringe.mu.html#L30'>same-fringe</a> x, y
<span id="L27" class="LineNr">27 </span>  $print result <span class="Constant">10/newline</span>
<span id="L28" class="LineNr">28 </span>]
<span id="L29" class="LineNr">29 </span>
<span id="L30" class="LineNr">30 </span><span class="muRecipe">def</span> <a href='same-fringe.mu.html#L30'>same-fringe</a> a:&amp;:<a href='same-fringe.mu.html#L9'>tree</a>:_elem, b:&amp;:<a href='same-fringe.mu.html#L9'>tree</a>:_elem<span class="muRecipe"> -&gt; </span>result:bool [
<span id="L31" class="LineNr">31 </span>  <span class="Constant">local-scope</span>
<span id="L32" class="LineNr">32 </span>  <span class="Constant">load-inputs</span>
<span id="L33" class="LineNr">33 </span>  k1:continuation <span class="Special">&lt;-</span> <span class="muControl">call-with-continuation-mark</span> <span class="Constant">100/mark</span>, <a href='same-fringe.mu.html#L48'>process</a>, a
<span id="L34" class="LineNr">34 </span>  k2:continuation <span class="Special">&lt;-</span> <span class="muControl">call-with-continuation-mark</span> <span class="Constant">100/mark</span>, <a href='same-fringe.mu.html#L48'>process</a>, b
<span id="L35" class="LineNr">35 </span>  <span class="Delimiter">{</span>
<span id="L36" class="LineNr">36 </span>    k1, x:_elem, a-done?:bool <span class="Special">&lt;-</span> call k1
<span id="L37" class="LineNr">37 </span>    k2, y:_elem, b-done?:bool <span class="Special">&lt;-</span> call k2
<span id="L38" class="LineNr">38 </span>    <span class="muControl">break-if</span> a-done?
<span id="L39" class="LineNr">39 </span>    <span class="muControl">break-if</span> b-done?
<span id="L40" class="LineNr">40 </span>    match?:bool <span class="Special">&lt;-</span> equal x, y
<span id="L41" class="LineNr">41 </span>    <span class="muControl">return-unless</span> match?,<span class="Constant"> false</span>
<span id="L42" class="LineNr">42 </span>   <span class="muControl"> loop</span>
<span id="L43" class="LineNr">43 </span>  <span class="Delimiter">}</span>
<span id="L44" class="LineNr">44 </span>  result <span class="Special">&lt;-</span> and a-done?, b-done?
<span id="L45" class="LineNr">45 </span>]
<span id="L46" class="LineNr">46 </span>
<span id="L47" class="LineNr">47 </span><span class="Comment"># harness around traversal</span>
<span id="L48" class="LineNr">48 </span><span class="muRecipe">def</span> <a href='same-fringe.mu.html#L48'>process</a> t:&amp;:<a href='same-fringe.mu.html#L9'>tree</a>:_elem [
<span id="L49" class="LineNr">49 </span>  <span class="Constant">local-scope</span>
<span id="L50" class="LineNr">50 </span>  <span class="Constant">load-inputs</span>
<span id="L51" class="LineNr">51 </span>  <span class="muControl">return-continuation-until-mark</span> <span class="Constant">100/mark</span>  <span class="Comment"># initial</span>
<span id="L52" class="LineNr">52 </span>  <a href='same-fringe.mu.html#L59'>traverse</a> t
<span id="L53" class="LineNr">53 </span>  zero-val:&amp;:_elem <span class="Special">&lt;-</span> new <span class="Constant">_elem:type</span>
<span id="L54" class="LineNr">54 </span>  <span class="muControl">return-continuation-until-mark</span> <span class="Constant">100/mark</span>, *zero-val,<span class="Constant"> true/done</span>  <span class="Comment"># final</span>
<span id="L55" class="LineNr">55 </span>  assert<span class="Constant"> false</span>, <span class="Constant">[continuation called past done]</span>
<span id="L56" class="LineNr">56 </span>]
<span id="L57" class="LineNr">57 </span>
<span id="L58" class="LineNr">58 </span><span class="Comment"># core traversal</span>
<span id="L59" class="LineNr">59 </span><span class="muRecipe">def</span> <a href='same-fringe.mu.html#L59'>traverse</a> t:&amp;:<a href='same-fringe.mu.html#L9'>tree</a>:_elem [
<span id="L60" class="LineNr">60 </span>  <span class="Constant">local-scope</span>
<span id="L61" class="LineNr">61 </span>  <span class="Constant">load-inputs</span>
<span id="L62" class="LineNr">62 </span>  <span class="muControl">return-unless</span> t
<span id="L63" class="LineNr">63 </span>  l:&amp;:<a href='same-fringe.mu.html#L9'>tree</a>:_elem <span class="Special">&lt;-</span> get *t, <span class="Constant">left:offset</span>
<span id="L64" class="LineNr">64 </span>  <a href='same-fringe.mu.html#L59'>traverse</a> l
<span id="L65" class="LineNr">65 </span>  r:&amp;:<a href='same-fringe.mu.html#L9'>tree</a>:_elem <span class="Special">&lt;-</span> get *t, <span class="Constant">right:offset</span>
<span id="L66" class="LineNr">66 </span>  <a href='same-fringe.mu.html#L59'>traverse</a> r
<span id="L67" class="LineNr">67 </span>  <span class="muControl">return-if</span> l
<span id="L68" class="LineNr">68 </span>  <span class="muControl">return-if</span> r
<span id="L69" class="LineNr">69 </span>  <span class="Comment"># leaf</span>
<span id="L70" class="LineNr">70 </span>  v:_elem <span class="Special">&lt;-</span> get *t, <span class="Constant">val:offset</span>
<span id="L71" class="LineNr">71 </span>  <span class="muControl">return-continuation-until-mark</span> <span class="Constant">100/mark</span>, v,<span class