diff options
Diffstat (limited to 'html/010vm.cc.html')
-rw-r--r-- | html/010vm.cc.html | 303 |
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& 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& <span class="Normal">operator</span>=<span class="Delimiter">(</span><span class="Normal">const</span> type_tree& 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& 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& 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><<span class="Delimiter">(</span><span class="Normal">const</span> type_tree& 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& 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><<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& 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 "End Globals")</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 >> 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& 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">-></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">""</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">-></span>value<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - <span class="Normal">const</span> string& type_name = result<span class="Delimiter">-></span>name = properties<span class="Delimiter">-></span>value<span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>properties<span class="Delimiter">-></span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">const</span> string& type_name = properties<span class="Delimiter">-></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">-></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">-></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">-></span>value != <span class="Constant">"->"</span><span class="Delimiter">)</span> <span class="Comment">// used in recipe types</span> - result<span class="Delimiter">-></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">-></span>value == <span class="Constant">"->"</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">-></span>left = new_type_tree<span class="Delimiter">(</span>properties<span class="Delimiter">-></span>left<span class="Delimiter">);</span> - result<span class="Delimiter">-></span>right = new_type_tree<span class="Delimiter">(</span>properties<span class="Delimiter">-></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">-></span>left<span class="Delimiter">),</span> + new_type_tree<span class="Delimiter">(</span>properties<span class="Delimiter">-></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& 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& type_tree::<span class="Normal">operator</span>=<span class="Delimiter">(</span><span class="Normal">const</span> type_tree& 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& 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 && 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> + && <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 < b then !(b < a)</span> +<span class="Normal">bool</span> type_tree::<span class="Normal">operator</span><<span class="Delimiter">(</span><span class="Normal">const</span> type_tree& 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 > 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 < 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 && !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 && 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 && !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 && 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 < *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 < *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> + && <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 < *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 < b) and (b < 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 < *other<span class="Delimiter">.</span>left && *left < *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 < *other<span class="Delimiter">.</span>left && *right < *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 "End Unit Tests")</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">"a:address"</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">"b:boolean"</span><span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type < *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 < *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">"a:address"</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">"b:address"</span><span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>!<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type < *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 < *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">"a:address:number"</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">"b:boolean"</span><span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>!<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type < *b<span class="Delimiter">.</span>type<span class="Delimiter">));</span> + CHECK<span class="Delimiter">(</span>*b<span class="Delimiter">.</span>type < *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">"a:address:address"</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">"b:address:boolean"</span><span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type < *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 < *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">"a:address:boolean"</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">"b:address:boolean"</span><span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>!<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type < *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 < *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">"a:address:address"</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">"b:address:address:number"</span><span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type < *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 < *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">"a:address:number"</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">"b:character:array"</span><span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>a<span class="Delimiter">.</span>type<span class="Delimiter">-></span>left<span class="Delimiter">-></span>atom && a<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>atom<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>b<span class="Delimiter">.</span>type<span class="Delimiter">-></span>left<span class="Delimiter">-></span>atom && b<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>atom<span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type < *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 < *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">"a:address:boolean"</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">"b:boolean:address"</span><span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>a<span class="Delimiter">.</span>type<span class="Delimiter">-></span>left<span class="Delimiter">-></span>atom && a<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>atom<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>b<span class="Delimiter">.</span>type<span class="Delimiter">-></span>left<span class="Delimiter">-></span>atom && b<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>atom<span class="Delimiter">);</span> + CHECK<span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type < *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 < *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& 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& 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*& 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">-></span>right<span class="Delimiter">)</span> curr = curr<span class="Delimiter">-></span>right<span class="Delimiter">;</span> + curr<span class="Delimiter">-></span>right = extra<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Normal">void</span> append<span class="Delimiter">(</span>string_tree*& 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">-></span>right<span class="Delimiter">)</span> curr = curr<span class="Delimiter">-></span>right<span class="Delimiter">;</span> + curr<span class="Delimiter">-></span>right = extra<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + string slurp_until<span class="Delimiter">(</span>istream& 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 "End Globals")</span> -<span class="Normal">const</span> string Ignore<span class="Delimiter">(</span><span class="Constant">","</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">","</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& 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& 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& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Identifier">return</span> x<span class="Delimiter">.</span>name == <span class="Constant">"_"</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">"()"</span><span class="Delimiter">;</span> ostringstream out<span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!property<span class="Delimiter">-></span>left && !property<span class="Delimiter">-></span>right<span class="Delimiter">)</span> - <span class="Comment">// abbreviate a single-node tree to just its contents</span> - out << <span class="Constant">'"'</span> << property<span class="Delimiter">-></span>value << <span class="Constant">'"'</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& out<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">-></span>left && !x<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> - out << x<span class="Delimiter">-></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">-></span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span> + out << <span class="Constant">'"'</span> << x<span class="Delimiter">-></span>value << <span class="Constant">'"'</span><span class="Delimiter">;</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> out << <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">-></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 << <span class="Constant">' '</span><span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-></span>left<span class="Delimiter">)</span> - dump<span class="Delimiter">(</span>curr<span class="Delimiter">-></span>left<span class="Delimiter">,</span> out<span class="Delimiter">);</span> - <span class="Normal">else</span> - out << <span class="Constant">'"'</span> << curr<span class="Delimiter">-></span>value << <span class="Constant">'"'</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 && !curr<span class="Delimiter">-></span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span> + dump<span class="Delimiter">(</span>curr<span class="Delimiter">-></span>left<span class="Delimiter">,</span> out<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-></span>right<span class="Delimiter">)</span> out << <span class="Constant">' '</span><span class="Delimiter">;</span> + curr = curr<span class="Delimiter">-></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 << <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& out<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">-></span>left && !x<span class="Delimiter">-></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">-></span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span> dump<span class="Delimiter">(</span>x<span class="Delimiter">-></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 << <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">-></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 << <span class="Constant">' '</span><span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-></span>left<span class="Delimiter">)</span> - dump<span class="Delimiter">(</span>curr<span class="Delimiter">-></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">-></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 && !curr<span class="Delimiter">-></span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span> + dump<span class="Delimiter">(</span>curr<span class="Delimiter">-></span>left<span class="Delimiter">,</span> out<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-></span>right<span class="Delimiter">)</span> out << <span class="Constant">' '</span><span class="Delimiter">;</span> + curr = curr<span class="Delimiter">-></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 << <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& out<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">-></span>left && !type<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> - out << <span class="Constant">'"'</span> << type<span class="Delimiter">-></span>name << <span class="Constant">'"'</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& 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">-></span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span> + out << <span class="Constant">'"'</span> << x<span class="Delimiter">-></span>name << <span class="Constant">'"'</span><span class="Delimiter">;</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> out << <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">-></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 << <span class="Constant">' '</span><span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-></span>left<span class="Delimiter">)</span> - dump_names<span class="Delimiter">(</span>curr<span class="Delimiter">-></span>left<span class="Delimiter">,</span> out<span class="Delimiter">);</span> - <span class="Normal">else</span> - out << <span class="Constant">'"'</span> << curr<span class="Delimiter">-></span>name << <span class="Constant">'"'</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 && !curr<span class="Delimiter">-></span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span> + dump_names<span class="Delimiter">(</span>curr<span class="Delimiter">-></span>left<span class="Delimiter">,</span> out<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-></span>right<span class="Delimiter">)</span> out << <span class="Constant">' '</span><span class="Delimiter">;</span> + curr = curr<span class="Delimiter">-></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 << <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& out<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">-></span>left && !type<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> - out << type<span class="Delimiter">-></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& 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">-></span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span> + out << x<span class="Delimiter">-></span>name<span class="Delimiter">;</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> out << <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">-></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 << <span class="Constant">' '</span><span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-></span>left<span class="Delimiter">)</span> - dump_names_without_quotes<span class="Delimiter">(</span>curr<span class="Delimiter">-></span>left<span class="Delimiter">,</span> out<span class="Delimiter">);</span> - <span class="Normal">else</span> - out << curr<span class="Delimiter">-></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 && !curr<span class="Delimiter">-></span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span> + dump_names_without_quotes<span class="Delimiter">(</span>curr<span class="Delimiter">-></span>left<span class="Delimiter">,</span> out<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">-></span>right<span class="Delimiter">)</span> out << <span class="Constant">' '</span><span class="Delimiter">;</span> + curr = curr<span class="Delimiter">-></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 << <span class="Constant">')'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -677,6 +795,8 @@ ostream& <span class="Normal">operator</span><<<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 << std::fixed << x<span class="Delimiter">.</span>x<span class="Delimiter">;</span> os << 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& <span class="Normal">operator</span><<<span class="Delimiter" string trim_floating_point<span class="Delimiter">(</span><span class="Normal">const</span> string& 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">""</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 > <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">"0"</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">""</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">""</span><span class="Delimiter">));</span> - CHECK_EQ<span class="Delimiter">(</span><span class="Constant">"0"</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">"000000000"</span><span class="Delimiter">));</span> - CHECK_EQ<span class="Delimiter">(</span><span class="Constant">"1.5"</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">"1.5000"</span><span class="Delimiter">));</span> - CHECK_EQ<span class="Delimiter">(</span><span class="Constant">"1.000001"</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">"1.000001"</span><span class="Delimiter">));</span> - CHECK_EQ<span class="Delimiter">(</span><span class="Constant">"23"</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">"23.000000"</span><span class="Delimiter">));</span> - CHECK_EQ<span class="Delimiter">(</span><span class="Constant">"23"</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">"23.0"</span><span class="Delimiter">));</span> - CHECK_EQ<span class="Delimiter">(</span><span class="Constant">"23"</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">"23."</span><span class="Delimiter">));</span> - CHECK_EQ<span class="Delimiter">(</span><span class="Constant">"23"</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">"23"</span><span class="Delimiter">));</span> - CHECK_EQ<span class="Delimiter">(</span><span class="Constant">"3"</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">"3.000000"</span><span class="Delimiter">));</span> - CHECK_EQ<span class="Delimiter">(</span><span class="Constant">"3"</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">"3.0"</span><span class="Delimiter">));</span> - CHECK_EQ<span class="Delimiter">(</span><span class="Constant">"3"</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">"3."</span><span class="Delimiter">));</span> - CHECK_EQ<span class="Delimiter">(</span><span class="Constant">"3"</span><span class="Delimiter">,</span> trim_floating_point<span class="Delimiter">(</span><span class="Constant">"3"</span><span class="Delimiter">));</span> + CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">""</span><span class="Delimiter">),</span> <span class="Constant">""</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">".0"</span><span class="Delimiter">),</span> <span class="Constant">"0"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">"1.5000"</span><span class="Delimiter">),</span> <span class="Constant">"1.5"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">"1.000001"</span><span class="Delimiter">),</span> <span class="Constant">"1.000001"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">"23.000000"</span><span class="Delimiter">),</span> <span class="Constant">"23"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">"23.0"</span><span class="Delimiter">),</span> <span class="Constant">"23"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">"23."</span><span class="Delimiter">),</span> <span class="Constant">"23"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">"23"</span><span class="Delimiter">),</span> <span class="Constant">"23"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">"230"</span><span class="Delimiter">),</span> <span class="Constant">"230"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">"3.000000"</span><span class="Delimiter">),</span> <span class="Constant">"3"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">"3.0"</span><span class="Delimiter">),</span> <span class="Constant">"3"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">"3."</span><span class="Delimiter">),</span> <span class="Constant">"3"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>trim_floating_point<span class="Delimiter">(</span><span class="Constant">"3"</span><span class="Delimiter">),</span> <span class="Constant">"3"</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Includes")</span> |