about summary refs log tree commit diff stats
path: root/html/010vm.cc.html
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-09-10 10:43:19 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-09-10 10:43:19 -0700
commit44c1aeef226542d692f0002b5cca5a3c30935d18 (patch)
tree46452902ff779d93e4adcb57cda29d923766a5be /html/010vm.cc.html
parentc7db6a160a9a43d0905d5dea44e742b47acfa42f (diff)
downloadmu-44c1aeef226542d692f0002b5cca5a3c30935d18.tar.gz
3315
Diffstat (limited to 'html/010vm.cc.html')
-rw-r--r--html/010vm.cc.html303
1 files changed, 213 insertions, 90 deletions
diff --git a/html/010vm.cc.html b/html/010vm.cc.html
index cc6b5360..e539a833 100644
--- a/html/010vm.cc.html
+++ b/html/010vm.cc.html
@@ -21,6 +21,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
 .Identifier { color: #fcb165; }
 .Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; }
 .PreProc { color: #800080; }
+.CommentedCode { color: #6c6c6c; }
 -->
 </style>
 
@@ -104,40 +105,41 @@ recipe_ordinal Next_recipe_ordinal = <span class="Constant">1</span><span class=
 <span class="Comment">// Types can range from a simple type ordinal, to arbitrarily complex trees of</span>
 <span class="Comment">// type parameters, like (map (address array character) (list number))</span>
 <span class="Normal">struct</span> type_tree <span class="Delimiter">{</span>
-  string name<span class="Delimiter">;</span>
-  type_ordinal value<span class="Delimiter">;</span>
-  type_tree* left<span class="Delimiter">;</span>
-  type_tree* right<span class="Delimiter">;</span>
+  <span class="Normal">bool</span> atom<span class="Delimiter">;</span>
+  string name<span class="Delimiter">;</span>  <span class="Comment">// only if atom</span>
+  type_ordinal value<span class="Delimiter">;</span>  <span class="Comment">// only if atom</span>
+  type_tree* left<span class="Delimiter">;</span>  <span class="Comment">// only if !atom</span>
+  type_tree* right<span class="Delimiter">;</span>  <span class="Comment">// only if !atom</span>
   ~type_tree<span class="Delimiter">();</span>
   type_tree<span class="Delimiter">(</span><span class="Normal">const</span> type_tree&amp; old<span class="Delimiter">);</span>
-  <span class="Comment">// simple: type ordinal</span>
+  <span class="Comment">// atomic type ordinal</span>
   <span class="Normal">explicit</span> type_tree<span class="Delimiter">(</span>string name<span class="Delimiter">);</span>
-  type_tree<span class="Delimiter">(</span>string name<span class="Delimiter">,</span> type_ordinal v<span class="Delimiter">)</span> :name<span class="Delimiter">(</span>name<span class="Delimiter">),</span> value<span class="Delimiter">(</span>v<span class="Delimiter">),</span> left<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> right<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span>
-  <span class="Comment">// intermediate: list of type ordinals</span>
-  type_tree<span class="Delimiter">(</span>string name<span class="Delimiter">,</span> type_ordinal v<span class="Delimiter">,</span> type_tree* r<span class="Delimiter">)</span> :name<span class="Delimiter">(</span>name<span class="Delimiter">),</span> value<span class="Delimiter">(</span>v<span class="Delimiter">),</span> left<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> right<span class="Delimiter">(</span>r<span class="Delimiter">)</span> <span class="Delimiter">{}</span>
-  type_tree<span class="Delimiter">(</span>string name<span class="Delimiter">,</span> type_tree* r<span class="Delimiter">);</span>
-  <span class="Comment">// advanced: tree containing type ordinals</span>
-  type_tree<span class="Delimiter">(</span>type_tree* l<span class="Delimiter">,</span> type_tree* r<span class="Delimiter">)</span> :value<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">),</span> left<span class="Delimiter">(</span>l<span class="Delimiter">),</span> right<span class="Delimiter">(</span>r<span class="Delimiter">)</span> <span class="Delimiter">{}</span>
+  type_tree<span class="Delimiter">(</span>string name<span class="Delimiter">,</span> type_ordinal v<span class="Delimiter">)</span> :atom<span class="Delimiter">(</span><span class="Constant">true</span><span class="Delimiter">),</span> name<span class="Delimiter">(</span>name<span class="Delimiter">),</span> value<span class="Delimiter">(</span>v<span class="Delimiter">),</span> left<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> right<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span>
+  <span class="Comment">// tree of type ordinals</span>
+  type_tree<span class="Delimiter">(</span>type_tree* l<span class="Delimiter">,</span> type_tree* r<span class="Delimiter">)</span> :atom<span class="Delimiter">(</span><span class="Constant">false</span><span class="Delimiter">),</span> value<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">),</span> left<span class="Delimiter">(</span>l<span class="Delimiter">),</span> right<span class="Delimiter">(</span>r<span class="Delimiter">)</span> <span class="Delimiter">{}</span>
+  type_tree&amp; <span class="Normal">operator</span>=<span class="Delimiter">(</span><span class="Normal">const</span> type_tree&amp; old<span class="Delimiter">);</span>
+  <span class="Normal">bool</span> <span class="Normal">operator</span>==<span class="Delimiter">(</span><span class="Normal">const</span> type_tree&amp; other<span class="Delimiter">)</span> <span class="Normal">const</span><span class="Delimiter">;</span>
+  <span class="Normal">bool</span> <span class="Normal">operator</span>!=<span class="Delimiter">(</span><span class="Normal">const</span> type_tree&amp; other<span class="Delimiter">)</span> <span class="Normal">const</span> <span class="Delimiter">{</span> <span class="Identifier">return</span> !<span class="Normal">operator</span>==<span class="Delimiter">(</span>other<span class="Delimiter">);</span> <span class="Delimiter">}</span>
+  <span class="Normal">bool</span> <span class="Normal">operator</span>&lt;<span class="Delimiter">(</span><span class="Normal">const</span> type_tree&amp; other<span class="Delimiter">)</span> <span class="Normal">const</span><span class="Delimiter">;</span>
+  <span class="Normal">bool</span> <span class="Normal">operator</span>&gt;<span class="Delimiter">(</span><span class="Normal">const</span> type_tree&amp; other<span class="Delimiter">)</span> <span class="Normal">const</span> <span class="Delimiter">{</span> <span class="Identifier">return</span> other<span class="Delimiter">.</span><span class="Normal">operator</span>&lt;<span class="Delimiter">(</span>*<span class="Normal">this</span><span class="Delimiter">);</span> <span class="Delimiter">}</span>
 <span class="Delimiter">};</span>
 
 <span class="Normal">struct</span> string_tree <span class="Delimiter">{</span>
-  string value<span class="Delimiter">;</span>
-  string_tree* left<span class="Delimiter">;</span>
-  string_tree* right<span class="Delimiter">;</span>
+  <span class="Normal">bool</span> atom<span class="Delimiter">;</span>
+  string value<span class="Delimiter">;</span>  <span class="Comment">// only if atom</span>
+  string_tree* left<span class="Delimiter">;</span>  <span class="Comment">// only if !atom</span>
+  string_tree* right<span class="Delimiter">;</span>  <span class="Comment">// only if !atom</span>
   ~string_tree<span class="Delimiter">();</span>
   string_tree<span class="Delimiter">(</span><span class="Normal">const</span> string_tree&amp; old<span class="Delimiter">);</span>
-  <span class="Comment">// simple: flat string</span>
-  <span class="Normal">explicit</span> string_tree<span class="Delimiter">(</span>string v<span class="Delimiter">)</span> :value<span class="Delimiter">(</span>v<span class="Delimiter">),</span> left<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> right<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span>
-  <span class="Comment">// intermediate: list of strings</span>
-  string_tree<span class="Delimiter">(</span>string v<span class="Delimiter">,</span> string_tree* r<span class="Delimiter">)</span> :value<span class="Delimiter">(</span>v<span class="Delimiter">),</span> left<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> right<span class="Delimiter">(</span>r<span class="Delimiter">)</span> <span class="Delimiter">{}</span>
-  <span class="Comment">// advanced: tree containing strings</span>
-  string_tree<span class="Delimiter">(</span>string_tree* l<span class="Delimiter">,</span> string_tree* r<span class="Delimiter">)</span> :left<span class="Delimiter">(</span>l<span class="Delimiter">),</span> right<span class="Delimiter">(</span>r<span class="Delimiter">)</span> <span class="Delimiter">{}</span>
+  <span class="Comment">// atomic string</span>
+  <span class="Normal">explicit</span> string_tree<span class="Delimiter">(</span>string v<span class="Delimiter">)</span> :atom<span class="Delimiter">(</span><span class="Constant">true</span><span class="Delimiter">),</span> value<span class="Delimiter">(</span>v<span class="Delimiter">),</span> left<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> right<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span>
+  <span class="Comment">// tree of strings</span>
+  string_tree<span class="Delimiter">(</span>string_tree* l<span class="Delimiter">,</span> string_tree* r<span class="Delimiter">)</span> :atom<span class="Delimiter">(</span><span class="Constant">false</span><span class="Delimiter">),</span> left<span class="Delimiter">(</span>l<span class="Delimiter">),</span> right<span class="Delimiter">(</span>r<span class="Delimiter">)</span> <span class="Delimiter">{}</span>
 <span class="Delimiter">};</span>
 
 <span class="Comment">// End type_tree Definition</span>
 <span class="Delimiter">:(code)</span>
-type_tree::type_tree<span class="Delimiter">(</span>string name<span class="Delimiter">)</span> :name<span class="Delimiter">(</span>name<span class="Delimiter">),</span> value<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">)),</span> left<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> right<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span>
-type_tree::type_tree<span class="Delimiter">(</span>string name<span class="Delimiter">,</span> type_tree* r<span class="Delimiter">)</span> :name<span class="Delimiter">(</span>name<span class="Delimiter">),</span> value<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">)),</span> left<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> right<span class="Delimiter">(</span>r<span class="Delimiter">)</span> <span class="Delimiter">{}</span>
+type_tree::type_tree<span class="Delimiter">(</span>string name<span class="Delimiter">)</span> :atom<span class="Delimiter">(</span><span class="Constant">true</span><span class="Delimiter">),</span> name<span class="Delimiter">(</span>name<span class="Delimiter">),</span> value<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">)),</span> left<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> right<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span>
 
 <span class="Delimiter">:(before &quot;End Globals&quot;)</span>
 <span class="Comment">// Locations refer to a common 'memory'. Each location can store a number.</span>
@@ -281,8 +283,6 @@ restore_snapshots<span class="Delimiter">();</span>
   <span class="Comment">// End restore_snapshots</span>
 <span class="Delimiter">}</span>
 
-^L
-
 <span class="SalientComment">//:: Helpers</span>
 
 <span class="Delimiter">:(code)</span>
@@ -306,6 +306,7 @@ reagent::reagent<span class="Delimiter">(</span><span class="Normal">const</span
   first_row &gt;&gt; std::noskipws<span class="Delimiter">;</span>
   name = slurp_until<span class="Delimiter">(</span>first_row<span class="Delimiter">,</span> <span class="Constant">':'</span><span class="Delimiter">);</span>
   string_tree* type_names = parse_property_list<span class="Delimiter">(</span>first_row<span class="Delimiter">);</span>
+  <span class="Comment">// End Parsing Reagent Type Property(type_names)</span>
   type = new_type_tree<span class="Delimiter">(</span>type_names<span class="Delimiter">);</span>
   <span class="Normal">delete</span> type_names<span class="Delimiter">;</span>
   <span class="Comment">// special cases</span>
@@ -331,26 +332,29 @@ reagent::reagent<span class="Delimiter">(</span><span class="Normal">const</span
 string_tree* parse_property_list<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   skip_whitespace_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
   <span class="Normal">if</span> <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">NULL</span><span class="Delimiter">;</span>
-  string_tree* result = <span class="Normal">new</span> string_tree<span class="Delimiter">(</span>slurp_until<span class="Delimiter">(</span>in<span class="Delimiter">,</span> <span class="Constant">':'</span><span class="Delimiter">));</span>
-  result<span class="Delimiter">-&gt;</span>right = parse_property_list<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
-  <span class="Identifier">return</span> result<span class="Delimiter">;</span>
+  string_tree* left = <span class="Normal">new</span> string_tree<span class="Delimiter">(</span>slurp_until<span class="Delimiter">(</span>in<span class="Delimiter">,</span> <span class="Constant">':'</span><span class="Delimiter">));</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Identifier">return</span> left<span class="Delimiter">;</span>
+  string_tree* right = parse_property_list<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
+  <span class="Identifier">return</span> <span class="Normal">new</span> string_tree<span class="Delimiter">(</span>left<span class="Delimiter">,</span> right<span class="Delimiter">);</span>
 <span class="Delimiter">}</span>
 
 type_tree* new_type_tree<span class="Delimiter">(</span><span class="Normal">const</span> string_tree* properties<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   <span class="Normal">if</span> <span class="Delimiter">(</span>!properties<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">NULL</span><span class="Delimiter">;</span>
-  type_tree* result = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">&quot;&quot;</span><span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span>
-  <span class="Normal">if</span> <span class="Delimiter">(</span>!properties<span class="Delimiter">-&gt;</span>value<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span>
-    <span class="Normal">const</span> string&amp; type_name = result<span class="Delimiter">-&gt;</span>name = properties<span class="Delimiter">-&gt;</span>value<span class="Delimiter">;</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>properties<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    <span class="Normal">const</span> string&amp; type_name = properties<span class="Delimiter">-&gt;</span>value<span class="Delimiter">;</span>
+    <span class="Normal">int</span> value = <span class="Constant">0</span><span class="Delimiter">;</span>
     <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type_name<span class="Delimiter">))</span>
-      result<span class="Delimiter">-&gt;</span>value = get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type_name<span class="Delimiter">);</span>
+      value = get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type_name<span class="Delimiter">);</span>
     <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>type_name<span class="Delimiter">))</span>  <span class="Comment">// sometimes types will contain non-type tags, like numbers for the size of an array</span>
-      result<span class="Delimiter">-&gt;</span>value = <span class="Constant">0</span><span class="Delimiter">;</span>
-    <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>properties<span class="Delimiter">-&gt;</span>value != <span class="Constant">&quot;-&gt;&quot;</span><span class="Delimiter">)</span>  <span class="Comment">// used in recipe types</span>
-      result<span class="Delimiter">-&gt;</span>value = -<span class="Constant">1</span><span class="Delimiter">;</span>  <span class="Comment">// should never happen; will trigger errors later</span>
+      value = <span class="Constant">0</span><span class="Delimiter">;</span>
+    <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>properties<span class="Delimiter">-&gt;</span>value == <span class="Constant">&quot;-&gt;&quot;</span><span class="Delimiter">)</span>  <span class="Comment">// used in recipe types</span>
+      value = <span class="Constant">0</span><span class="Delimiter">;</span>
+    <span class="Normal">else</span>
+      value = -<span class="Constant">1</span><span class="Delimiter">;</span>  <span class="Comment">// should never happen; will trigger errors later</span>
+    <span class="Identifier">return</span> <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>type_name<span class="Delimiter">,</span> value<span class="Delimiter">);</span>
   <span class="Delimiter">}</span>
-  result<span class="Delimiter">-&gt;</span>left = new_type_tree<span class="Delimiter">(</span>properties<span class="Delimiter">-&gt;</span>left<span class="Delimiter">);</span>
-  result<span class="Delimiter">-&gt;</span>right = new_type_tree<span class="Delimiter">(</span>properties<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span>
-  <span class="Identifier">return</span> result<span class="Delimiter">;</span>
+  <span class="Identifier">return</span> <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>new_type_tree<span class="Delimiter">(</span>properties<span class="Delimiter">-&gt;</span>left<span class="Delimiter">),</span>
+                       new_type_tree<span class="Delimiter">(</span>properties<span class="Delimiter">-&gt;</span>right<span class="Delimiter">));</span>
 <span class="Delimiter">}</span>
 
 <span class="Comment">//: avoid memory leaks for the type tree</span>
@@ -369,13 +373,103 @@ reagent::reagent<span class="Delimiter">(</span><span class="Normal">const</span
 <span class="Delimiter">}</span>
 
 type_tree::type_tree<span class="Delimiter">(</span><span class="Normal">const</span> type_tree&amp; old<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  atom = old<span class="Delimiter">.</span>atom<span class="Delimiter">;</span>
+  name = old<span class="Delimiter">.</span>name<span class="Delimiter">;</span>
+  value = old<span class="Delimiter">.</span>value<span class="Delimiter">;</span>
+  left = old<span class="Delimiter">.</span>left ? <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*old<span class="Delimiter">.</span>left<span class="Delimiter">)</span> : <span class="Constant">NULL</span><span class="Delimiter">;</span>
+  right = old<span class="Delimiter">.</span>right ? <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*old<span class="Delimiter">.</span>right<span class="Delimiter">)</span> : <span class="Constant">NULL</span><span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
+type_tree&amp; type_tree::<span class="Normal">operator</span>=<span class="Delimiter">(</span><span class="Normal">const</span> type_tree&amp; old<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  atom = old<span class="Delimiter">.</span>atom<span class="Delimiter">;</span>
   name = old<span class="Delimiter">.</span>name<span class="Delimiter">;</span>
   value = old<span class="Delimiter">.</span>value<span class="Delimiter">;</span>
   left = old<span class="Delimiter">.</span>left ? <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*old<span class="Delimiter">.</span>left<span class="Delimiter">)</span> : <span class="Constant">NULL</span><span class="Delimiter">;</span>
   right = old<span class="Delimiter">.</span>right ? <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*old<span class="Delimiter">.</span>right<span class="Delimiter">)</span> : <span class="Constant">NULL</span><span class="Delimiter">;</span>
+  <span class="Identifier">return</span> *<span class="Normal">this</span><span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
+<span class="Normal">bool</span> type_tree::<span class="Normal">operator</span>==<span class="Delimiter">(</span><span class="Normal">const</span> type_tree&amp; other<span class="Delimiter">)</span> <span class="Normal">const</span> <span class="Delimiter">{</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>atom != other<span class="Delimiter">.</span>atom<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>atom<span class="Delimiter">)</span>
+    <span class="Identifier">return</span> name == other<span class="Delimiter">.</span>name &amp;&amp; value == other<span class="Delimiter">.</span>value<span class="Delimiter">;</span>
+  <span class="Identifier">return</span> <span class="Delimiter">(</span>left == other<span class="Delimiter">.</span>left || *left == *other<span class="Delimiter">.</span>left<span class="Delimiter">)</span>
+      &amp;&amp; <span class="Delimiter">(</span>right == other<span class="Delimiter">.</span>right || *right == *other<span class="Delimiter">.</span>right<span class="Delimiter">);</span>
+<span class="Delimiter">}</span>
+
+<span class="Comment">// only constraint we care about: if a &lt; b then !(b &lt; a)</span>
+<span class="Normal">bool</span> type_tree::<span class="Normal">operator</span>&lt;<span class="Delimiter">(</span><span class="Normal">const</span> type_tree&amp; other<span class="Delimiter">)</span> <span class="Normal">const</span> <span class="Delimiter">{</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>atom != other<span class="Delimiter">.</span>atom<span class="Delimiter">)</span> <span class="Identifier">return</span> atom &gt; other<span class="Delimiter">.</span>atom<span class="Delimiter">;</span>  <span class="Comment">// atoms before non-atoms</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>atom<span class="Delimiter">)</span> <span class="Identifier">return</span> name &lt; other<span class="Delimiter">.</span>name<span class="Delimiter">;</span>  <span class="Comment">// sort atoms in lexical order</span>
+  <span class="Comment">// first location in one that's missing in the other makes that side 'smaller'</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>left &amp;&amp; !other<span class="Delimiter">.</span>left<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>!left &amp;&amp; other<span class="Delimiter">.</span>left<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>right &amp;&amp; !other<span class="Delimiter">.</span>right<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>!right &amp;&amp; other<span class="Delimiter">.</span>right<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
+  <span class="Comment">// if one side is equal that's easy</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>left == other<span class="Delimiter">.</span>left || *left == *other<span class="Delimiter">.</span>left<span class="Delimiter">)</span> <span class="Identifier">return</span> *right &lt; *other<span class="Delimiter">.</span>right<span class="Delimiter">;</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>right == other<span class="Delimiter">.</span>right || *right == *other<span class="Delimiter">.</span>right<span class="Delimiter">)</span> <span class="Identifier">return</span> *left &lt; *other<span class="Delimiter">.</span>left<span class="Delimiter">;</span>
+  <span class="Comment">// if the two sides criss-cross, pick the side with the smaller lhs</span>
+  <span class="Normal">if</span> <span class="Delimiter">((</span>left == other<span class="Delimiter">.</span>right || *left == *other<span class="Delimiter">.</span>right<span class="Delimiter">)</span>
+      &amp;&amp; <span class="Delimiter">(</span>right == other<span class="Delimiter">.</span>left || *right == *other<span class="Delimiter">.</span>left<span class="Delimiter">))</span>
+    <span class="Identifier">return</span> *left &lt; *other<span class="Delimiter">.</span>left<span class="Delimiter">;</span>
+  <span class="Comment">// now the hard case: both sides are not equal</span>
+  <span class="Comment">// make sure we stay consistent between (a &lt; b) and (b &lt; a)</span>
+  <span class="Comment">// just return the side with the smallest of the 4 branches</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>*left &lt; *other<span class="Delimiter">.</span>left &amp;&amp; *left &lt; *other<span class="Delimiter">.</span>right<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>*right &lt; *other<span class="Delimiter">.</span>left &amp;&amp; *right &lt; *other<span class="Delimiter">.</span>right<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
+  <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+<span class="Delimiter">:(before &quot;End Unit Tests&quot;)</span>
+<span class="Comment">// These unit tests don't always use valid types.</span>
+<span class="Normal">void</span> test_compare_atom_types<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  reagent a<span class="Delimiter">(</span><span class="Constant">&quot;a:address&quot;</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">&quot;b:boolean&quot;</span><span class="Delimiter">);</span>
+  CHECK<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type &lt; *b<span class="Delimiter">.</span>type<span class="Delimiter">);</span>
+  CHECK<span class="Delimiter">(</span>!<span class="Delimiter">(</span>*b<span class="Delimiter">.</span>type &lt; *a<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
+<span class="Delimiter">}</span>
+<span class="Normal">void</span> test_compare_equal_atom_types<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  reagent a<span class="Delimiter">(</span><span class="Constant">&quot;a:address&quot;</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">&quot;b:address&quot;</span><span class="Delimiter">);</span>
+  CHECK<span class="Delimiter">(</span>!<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type &lt; *b<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
+  CHECK<span class="Delimiter">(</span>!<span class="Delimiter">(</span>*b<span class="Delimiter">.</span>type &lt; *a<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
+<span class="Delimiter">}</span>
+<span class="Normal">void</span> test_compare_atom_with_non_atom<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  reagent a<span class="Delimiter">(</span><span class="Constant">&quot;a:address:number&quot;</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">&quot;b:boolean&quot;</span><span class="Delimiter">);</span>
+  CHECK<span class="Delimiter">(</span>!<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type &lt; *b<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
+  CHECK<span class="Delimiter">(</span>*b<span class="Delimiter">.</span>type &lt; *a<span class="Delimiter">.</span>type<span class="Delimiter">);</span>
+<span class="Delimiter">}</span>
+<span class="Normal">void</span> test_compare_lists_with_identical_structure<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  reagent a<span class="Delimiter">(</span><span class="Constant">&quot;a:address:address&quot;</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">&quot;b:address:boolean&quot;</span><span class="Delimiter">);</span>
+  CHECK<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type &lt; *b<span class="Delimiter">.</span>type<span class="Delimiter">);</span>
+  CHECK<span class="Delimiter">(</span>!<span class="Delimiter">(</span>*b<span class="Delimiter">.</span>type &lt; *a<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
+<span class="Delimiter">}</span>
+<span class="Normal">void</span> test_compare_identical_lists<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  reagent a<span class="Delimiter">(</span><span class="Constant">&quot;a:address:boolean&quot;</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">&quot;b:address:boolean&quot;</span><span class="Delimiter">);</span>
+  CHECK<span class="Delimiter">(</span>!<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type &lt; *b<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
+  CHECK<span class="Delimiter">(</span>!<span class="Delimiter">(</span>*b<span class="Delimiter">.</span>type &lt; *a<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
+<span class="Delimiter">}</span>
+<span class="Normal">void</span> test_compare_list_with_extra_element<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  reagent a<span class="Delimiter">(</span><span class="Constant">&quot;a:address:address&quot;</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">&quot;b:address:address:number&quot;</span><span class="Delimiter">);</span>
+  CHECK<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type &lt; *b<span class="Delimiter">.</span>type<span class="Delimiter">);</span>
+  CHECK<span class="Delimiter">(</span>!<span class="Delimiter">(</span>*b<span class="Delimiter">.</span>type &lt; *a<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
+<span class="Delimiter">}</span>
+<span class="Normal">void</span> test_compare_list_with_smaller_left_but_larger_right<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  reagent a<span class="Delimiter">(</span><span class="Constant">&quot;a:address:number&quot;</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">&quot;b:character:array&quot;</span><span class="Delimiter">);</span>
+  assert<span class="Delimiter">(</span>a<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">-&gt;</span>atom &amp;&amp; a<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span>
+  assert<span class="Delimiter">(</span>b<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">-&gt;</span>atom &amp;&amp; b<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span>
+  CHECK<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type &lt; *b<span class="Delimiter">.</span>type<span class="Delimiter">);</span>
+  CHECK<span class="Delimiter">(</span>!<span class="Delimiter">(</span>*b<span class="Delimiter">.</span>type &lt; *a<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
+<span class="Delimiter">}</span>
+<span class="Normal">void</span> test_compare_list_with_smaller_left_but_larger_right_identical_types<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  reagent a<span class="Delimiter">(</span><span class="Constant">&quot;a:address:boolean&quot;</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">&quot;b:boolean:address&quot;</span><span class="Delimiter">);</span>
+  assert<span class="Delimiter">(</span>a<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">-&gt;</span>atom &amp;&amp; a<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span>
+  assert<span class="Delimiter">(</span>b<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">-&gt;</span>atom &amp;&amp; b<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span>
+  CHECK<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type &lt; *b<span class="Delimiter">.</span>type<span class="Delimiter">);</span>
+  CHECK<span class="Delimiter">(</span>!<span class="Delimiter">(</span>*b<span class="Delimiter">.</span>type &lt; *a<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
 <span class="Delimiter">}</span>
 
-string_tree::string_tree<span class="Delimiter">(</span><span class="Normal">const</span> string_tree&amp; old<span class="Delimiter">)</span> <span class="Delimiter">{</span>  <span class="Comment">// :value(old.value) {</span>
+<span class="Delimiter">:(code)</span>
+string_tree::string_tree<span class="Delimiter">(</span><span class="Normal">const</span> string_tree&amp; old<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  atom = old<span class="Delimiter">.</span>atom<span class="Delimiter">;</span>
   value = old<span class="Delimiter">.</span>value<span class="Delimiter">;</span>
   left = old<span class="Delimiter">.</span>left ? <span class="Normal">new</span> string_tree<span class="Delimiter">(</span>*old<span class="Delimiter">.</span>left<span class="Delimiter">)</span> : <span class="Constant">NULL</span><span class="Delimiter">;</span>
   right = old<span class="Delimiter">.</span>right ? <span class="Normal">new</span> string_tree<span class="Delimiter">(</span>*old<span class="Delimiter">.</span>right<span class="Delimiter">)</span> : <span class="Constant">NULL</span><span class="Delimiter">;</span>
@@ -420,6 +514,26 @@ string_tree::~string_tree<span class="Delimiter">()</span> <span class="Delimite
   <span class="Normal">delete</span> right<span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
+<span class="Normal">void</span> append<span class="Delimiter">(</span>type_tree*&amp; base<span class="Delimiter">,</span> type_tree* extra<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>!base<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    base = extra<span class="Delimiter">;</span>
+    <span class="Identifier">return</span><span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
+  type_tree* curr = base<span class="Delimiter">;</span>
+  <span class="Normal">while</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> curr = curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">;</span>
+  curr<span class="Delimiter">-&gt;</span>right = extra<span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
+<span class="Normal">void</span> append<span class="Delimiter">(</span>string_tree*&amp; base<span class="Delimiter">,</span> string_tree* extra<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>!base<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    base = extra<span class="Delimiter">;</span>
+    <span class="Identifier">return</span><span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
+  string_tree* curr = base<span class="Delimiter">;</span>
+  <span class="Normal">while</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> curr = curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">;</span>
+  curr<span class="Delimiter">-&gt;</span>right = extra<span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
 string slurp_until<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">,</span> <span class="Normal">char</span> delim<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   ostringstream out<span class="Delimiter">;</span>
   <span class="Normal">char</span> c<span class="Delimiter">;</span>
@@ -449,7 +563,7 @@ string_tree* property<span class="Delimiter">(</span><span class="Normal">const<
 <span class="Delimiter">}</span>
 
 <span class="Delimiter">:(before &quot;End Globals&quot;)</span>
-<span class="Normal">const</span> string Ignore<span class="Delimiter">(</span><span class="Constant">&quot;,&quot;</span><span class="Delimiter">);</span>  <span class="Comment">// commas are ignored in mu except within [] strings</span>
+<span class="Normal">extern</span> <span class="Normal">const</span> string Ignore<span class="Delimiter">(</span><span class="Constant">&quot;,&quot;</span><span class="Delimiter">);</span>  <span class="Comment">// commas are ignored in mu except within [] strings</span>
 <span class="Delimiter">:(code)</span>
 <span class="Normal">void</span> skip_whitespace_but_not_newline<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   <span class="Normal">while</span> <span class="Delimiter">(</span><span class="Constant">true</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
@@ -545,7 +659,7 @@ string to_string<span class="Delimiter">(</span><span class="Normal">const</span
 <span class="Delimiter">}</span>
 
 <span class="Comment">// special name for ignoring some products</span>
-<span class="Normal">inline</span> <span class="Normal">bool</span> is_dummy<span class="Delimiter">(</span><span class="Normal">const</span> reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+<span class="Normal">bool</span> is_dummy<span class="Delimiter">(</span><span class="Normal">const</span> reagent&amp; x<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   <span class="Identifier">return</span> x<span class="Delimiter">.</span>name == <span class="Constant">&quot;_&quot;</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
@@ -558,27 +672,25 @@ string debug_string<span class="Delimiter">(</span><span class="Normal">const</s
 string to_string<span class="Delimiter">(</span><span class="Normal">const</span> string_tree* property<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   <span class="Normal">if</span> <span class="Delimiter">(</span>!property<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">&quot;()&quot;</span><span class="Delimiter">;</span>
   ostringstream out<span class="Delimiter">;</span>
-  <span class="Normal">if</span> <span class="Delimiter">(</span>!property<span class="Delimiter">-&gt;</span>left &amp;&amp; !property<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span>
-    <span class="Comment">// abbreviate a single-node tree to just its contents</span>
-    out &lt;&lt; <span class="Constant">'&quot;'</span> &lt;&lt; property<span class="Delimiter">-&gt;</span>value &lt;&lt; <span class="Constant">'&quot;'</span><span class="Delimiter">;</span>
-  <span class="Normal">else</span>
-    dump<span class="Delimiter">(</span>property<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
+  dump<span class="Delimiter">(</span>property<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
   <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span>
 <span class="Delimiter">}</span>
 
 <span class="Normal">void</span> dump<span class="Delimiter">(</span><span class="Normal">const</span> string_tree* x<span class="Delimiter">,</span> ostream&amp; out<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-  <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">-&gt;</span>left &amp;&amp; !x<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    out &lt;&lt; x<span class="Delimiter">-&gt;</span>value<span class="Delimiter">;</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    out &lt;&lt; <span class="Constant">'&quot;'</span> &lt;&lt; x<span class="Delimiter">-&gt;</span>value &lt;&lt; <span class="Constant">'&quot;'</span><span class="Delimiter">;</span>
     <span class="Identifier">return</span><span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
   out &lt;&lt; <span class="Constant">'('</span><span class="Delimiter">;</span>
-  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">const</span> string_tree* curr = x<span class="Delimiter">;</span> curr<span class="Delimiter">;</span> curr = curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    <span class="Normal">if</span> <span class="Delimiter">(</span>curr != x<span class="Delimiter">)</span> out &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span>
-    <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>left<span class="Delimiter">)</span>
-      dump<span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
-    <span class="Normal">else</span>
-      out &lt;&lt; <span class="Constant">'&quot;'</span> &lt;&lt; curr<span class="Delimiter">-&gt;</span>value &lt;&lt; <span class="Constant">'&quot;'</span><span class="Delimiter">;</span>
+  <span class="Normal">const</span> string_tree* curr = x<span class="Delimiter">;</span>
+  <span class="Normal">while</span> <span class="Delimiter">(</span>curr &amp;&amp; !curr<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    dump<span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
+    <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> out &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span>
+    curr = curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
+  <span class="Comment">// final right</span>
+  dump<span class="Delimiter">(</span>curr<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
   out &lt;&lt; <span class="Constant">')'</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
@@ -591,18 +703,20 @@ string to_string<span class="Delimiter">(</span><span class="Normal">const</span
 <span class="Delimiter">}</span>
 
 <span class="Normal">void</span> dump<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* x<span class="Delimiter">,</span> ostream&amp; out<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-  <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">-&gt;</span>left &amp;&amp; !x<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span>
     dump<span class="Delimiter">(</span>x<span class="Delimiter">-&gt;</span>value<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
     <span class="Identifier">return</span><span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
   out &lt;&lt; <span class="Constant">'('</span><span class="Delimiter">;</span>
-  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">const</span> type_tree* curr = x<span class="Delimiter">;</span> curr<span class="Delimiter">;</span> curr = curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    <span class="Normal">if</span> <span class="Delimiter">(</span>curr != x<span class="Delimiter">)</span> out &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span>
-    <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>left<span class="Delimiter">)</span>
-      dump<span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
-    <span class="Normal">else</span>
-      dump<span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>value<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
+  <span class="Normal">const</span> type_tree* curr = x<span class="Delimiter">;</span>
+  <span class="Normal">while</span> <span class="Delimiter">(</span>curr &amp;&amp; !curr<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    dump<span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
+    <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> out &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span>
+    curr = curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
+  <span class="Comment">// final right</span>
+  dump<span class="Delimiter">(</span>curr<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
   out &lt;&lt; <span class="Constant">')'</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
@@ -621,19 +735,21 @@ string names_to_string<span class="Delimiter">(</span><span class="Normal">const
   <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span>
 <span class="Delimiter">}</span>
 
-<span class="Normal">void</span> dump_names<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">,</span> ostream&amp; out<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-  <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">-&gt;</span>left &amp;&amp; !type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    out &lt;&lt; <span class="Constant">'&quot;'</span> &lt;&lt; type<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">'&quot;'</span><span class="Delimiter">;</span>
+<span class="Normal">void</span> dump_names<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* x<span class="Delimiter">,</span> ostream&amp; out<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    out &lt;&lt; <span class="Constant">'&quot;'</span> &lt;&lt; x<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">'&quot;'</span><span class="Delimiter">;</span>
     <span class="Identifier">return</span><span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
   out &lt;&lt; <span class="Constant">'('</span><span class="Delimiter">;</span>
-  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">const</span> type_tree* curr = type<span class="Delimiter">;</span> curr<span class="Delimiter">;</span> curr = curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    <span class="Normal">if</span> <span class="Delimiter">(</span>curr != type<span class="Delimiter">)</span> out &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span>
-    <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>left<span class="Delimiter">)</span>
-      dump_names<span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
-    <span class="Normal">else</span>
-      out &lt;&lt; <span class="Constant">'&quot;'</span> &lt;&lt; curr<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">'&quot;'</span><span class="Delimiter">;</span>
+  <span class="Normal">const</span> type_tree* curr = x<span class="Delimiter">;</span>
+  <span class="Normal">while</span> <span class="Delimiter">(</span>curr &amp;&amp; !curr<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    dump_names<span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
+    <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> out &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span>
+    curr = curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
+  <span class="Comment">// final right</span>
+  dump_names<span class="Delimiter">(</span>curr<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
   out &lt;&lt; <span class="Constant">')'</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
@@ -645,19 +761,21 @@ string names_to_string_without_quotes<span class="Delimiter">(</span><span class
   <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span>
 <span class="Delimiter">}</span>
 
-<span class="Normal">void</span> dump_names_without_quotes<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">,</span> ostream&amp; out<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-  <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">-&gt;</span>left &amp;&amp; !type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    out &lt;&lt; type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">;</span>
+<span class="Normal">void</span> dump_names_without_quotes<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* x<span class="Delimiter">,</span> ostream&amp; out<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    out &lt;&lt; x<span class="Delimiter">-&gt;</span>name<span class="Delimiter">;</span>
     <span class="Identifier">return</span><span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
   out &lt;&lt; <span class="Constant">'('</span><span class="Delimiter">;</span>
-  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">const</span> type_tree* curr = type<span class="Delimiter">;</span> curr<span class="Delimiter">;</span> curr = curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    <span class="Normal">if</span> <span class="Delimiter">(</span>curr != type<span class="Delimiter">)</span> out &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span>
-    <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>left<span class="Delimiter">)</span>
-      dump_names_without_quotes<span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
-    <span class="Normal">else</span>
-      out &lt;&lt; curr<span class="Delimiter">-&gt;</span>name<span class="Delimiter">;</span>
+  <span class="Normal">const</span> type_tree* curr = x<span class="Delimiter">;</span>
+  <span class="Normal">while</span> <span class="Delimiter">(</span>curr &amp;&amp; !curr<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    dump_names_without_quotes<span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
+    <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> out &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span>
+    curr = curr<span class="Delimiter">-&gt;</span>right<span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
+  <span class="Comment">// final right</span>
+  dump_names_without_quotes<span class="Delimiter">(</span>curr<span class="Delimiter">,</span> out<span class="Delimiter">);</span>
   out &lt;&lt; <span class="Constant">')'</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
@@ -677,6 +795,8 @@ ostream&amp; <span class="Normal">operator</span>&lt;&lt;<span class="Delimiter"
     <span class="Identifier">return</span> os<span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
   ostringstream tmp<span class="Delimiter">;</span>
+  <span class="Comment">// more accurate, but too slow</span>
+<span class="CommentedCode">//?   tmp.precision(308);  // for 64-bit numbers</span>
   tmp &lt;&lt; std::fixed &lt;&lt; x<span class="Delimiter">.</span>x<span class="Delimiter">;</span>
   os &lt;&lt; trim_floating_point<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>str<span class="Delimiter">());</span>
   <span class="Identifier">return</span> os<span class="Delimiter">;</span>
@@ -684,28 +804,31 @@ ostream&amp; <span class="Normal">operator</span>&lt;&lt;<span class="Delimiter"
 
 string trim_floating_point<span class="Delimiter">(</span><span class="Normal">const</span> string&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   <span class="Normal">if</span> <span class="Delimiter">(</span>in<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">&quot;&quot;</span><span class="Delimiter">;</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>in<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">'.'</span><span class="Delimiter">)</span> == string::npos<span class="Delimiter">)</span> <span class="Identifier">return</span> in<span class="Delimiter">;</span>
   <span class="Normal">int</span> length = SIZE<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
   <span class="Normal">while</span> <span class="Delimiter">(</span>length &gt; <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
     <span class="Normal">if</span> <span class="Delimiter">(</span>in<span class="Delimiter">.</span>at<span class="Delimiter">(</span>length-<span class="Constant">1</span><span class="Delimiter">)</span> != <span class="Constant">'0'</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
     --length<span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
   <span class="Normal">if</span> <span class="Delimiter">(</span>in<span class="Delimiter">.</span>at<span class="Delimiter">(</span>length-<span class="Constant">1</span><span class="Delimiter">)</span> == <span class="Constant">'.'</span><span class="Delimiter">)</span> --length<span class="Delimiter">;</span>
+  <span class="Normal">if</span> <span class="Delimiter">(</span>length == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">&quot;0&quot;</span><span class="Delimiter">;</span>
   <span class="Identifier">return</span> in<span class="Delimiter">.</span>substr<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> length<span class="Delimiter">);</span>
 <span class="Delimiter">}</span>
 
 <span class="Normal">void</span> test_trim_floating_point<span class="Delimiter">()</span> <span class="Delimiter">{</span>
-  CHECK_EQ<span class="Delimiter">(</span><span class="Constant">&quot;&quot;</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;&quot;</span><span class="Delimiter">));</span>
-  CHECK_EQ<span class="Delimiter">(</span><span class="Constant">&quot;0&quot;</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;000000000&quot;</span><span class="Delimiter">));</span>
-  CHECK_EQ<span class="Delimiter">(</span><span class="Constant">&quot;1.5&quot;</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;1.5000&quot;</span><span class="Delimiter">));</span>
-  CHECK_EQ<span class="Delimiter">(</span><span class="Constant">&quot;1.000001&quot;</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;1.000001&quot;</span><span class="Delimiter">));</span>
-  CHECK_EQ<span class="Delimiter">(</span><span class="Constant">&quot;23&quot;</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;23.000000&quot;</span><span class="Delimiter">));</span>
-  CHECK_EQ<span class="Delimiter">(</span><span class="Constant">&quot;23&quot;</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;23.0&quot;</span><span class="Delimiter">));</span>
-  CHECK_EQ<span class="Delimiter">(</span><span class="Constant">&quot;23&quot;</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;23.&quot;</span><span class="Delimiter">));</span>
-  CHECK_EQ<span class="Delimiter">(</span><span class="Constant">&quot;23&quot;</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;23&quot;</span><span class="Delimiter">));</span>
-  CHECK_EQ<span class="Delimiter">(</span><span class="Constant">&quot;3&quot;</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;3.000000&quot;</span><span class="Delimiter">));</span>
-  CHECK_EQ<span class="Delimiter">(</span><span class="Constant">&quot;3&quot;</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;3.0&quot;</span><span class="Delimiter">));</span>
-  CHECK_EQ<span class="Delimiter">(</span><span class="Constant">&quot;3&quot;</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;3.&quot;</span><span class="Delimiter">));</span>
-  CHECK_EQ<span class="Delimiter">(</span><span class="Constant">&quot;3&quot;</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;3&quot;</span><span class="Delimiter">));</span>
+  CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;&quot;</span><span class="Delimiter">);</span>
+  CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;.0&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;0&quot;</span><span class="Delimiter">);</span>
+  CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;1.5000&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;1.5&quot;</span><span class="Delimiter">);</span>
+  CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;1.000001&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;1.000001&quot;</span><span class="Delimiter">);</span>
+  CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;23.000000&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;23&quot;</span><span class="Delimiter">);</span>
+  CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;23.0&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;23&quot;</span><span class="Delimiter">);</span>
+  CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;23.&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;23&quot;</span><span class="Delimiter">);</span>
+  CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;23&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;23&quot;</span><span class="Delimiter">);</span>
+  CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;230&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;230&quot;</span><span class="Delimiter">);</span>
+  CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;3.000000&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;3&quot;</span><span class="Delimiter">);</span>
+  CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;3.0&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;3&quot;</span><span class="Delimiter">);</span>
+  CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;3.&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;3&quot;</span><span class="Delimiter">);</span>
+  CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">&quot;3&quot;</span><span class="Delimiter">),</span> <span class="Constant">&quot;3&quot;</span><span class="Delimiter">);</span>
 <span class="Delimiter">}</span>
 
 <span class="Delimiter">:(before &quot;End Includes&quot;)</span>