diff options
Diffstat (limited to 'html/057static_dispatch.cc.html')
-rw-r--r-- | html/057static_dispatch.cc.html | 241 |
1 files changed, 223 insertions, 18 deletions
diff --git a/html/057static_dispatch.cc.html b/html/057static_dispatch.cc.html index 243b9c28..1c7b28b7 100644 --- a/html/057static_dispatch.cc.html +++ b/html/057static_dispatch.cc.html @@ -14,11 +14,13 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .traceContains { color: #008000; } -.Identifier { color: #804000; } +.traceAbsent { color: #c00000; } +.cSpecial { color: #008000; } +.CommentedCode { color: #6c6c6c; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } -.CommentedCode { color: #6c6c6c; } +.Identifier { color: #804000; } .Constant { color: #00a0a0; } --> </style> @@ -65,12 +67,11 @@ for <span class="Delimiter">(</span>map<string<span class="Delimiter">,</span <span class="Delimiter">:(before "End Load Recipe Header(result)")</span> if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> const recipe_ordinal r = get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">);</span> -<span class="CommentedCode">//? if (variant_already_exists(result)) cerr << "AAAAAAAAAAAAAAAAAA variant already exists " << result.name << '\n';</span> if <span class="Delimiter">((</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">)</span> || get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>has_header<span class="Delimiter">)</span> && !variant_already_exists<span class="Delimiter">(</span>result<span class="Delimiter">))</span> <span class="Delimiter">{</span> string new_name = next_unused_recipe_name<span class="Delimiter">(</span>result<span class="Delimiter">.</span>name<span class="Delimiter">);</span> put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> new_name<span class="Delimiter">,</span> Next_recipe_ordinal++<span class="Delimiter">);</span> - get<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> new_name<span class="Delimiter">));</span> + get_or_insert<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> new_name<span class="Delimiter">));</span> result<span class="Delimiter">.</span>name = new_name<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -82,7 +83,7 @@ else <span class="Delimiter">{</span> <span class="Delimiter">:(code)</span> bool variant_already_exists<span class="Delimiter">(</span>const recipe& rr<span class="Delimiter">)</span> <span class="Delimiter">{</span> - const vector<recipe_ordinal>& variants = get<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> rr<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + const vector<recipe_ordinal>& variants = get_or_insert<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> rr<span class="Delimiter">.</span>name<span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>variants<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> && all_reagents_match<span class="Delimiter">(</span>rr<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))))</span> <span class="Delimiter">{</span> @@ -110,11 +111,24 @@ bool all_reagents_match<span class="Delimiter">(</span>const recipe& r1<span <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -bool exact_match<span class="Delimiter">(</span>type_tree* a<span class="Delimiter">,</span> type_tree* b<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>a == b<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Globals")</span> +set<string> Literal_type_names<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End One-time Setup")</span> +Literal_type_names<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">"number"</span><span class="Delimiter">);</span> +Literal_type_names<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">"character"</span><span class="Delimiter">);</span> +<span class="Delimiter">:(code)</span> +bool deeply_equal_types<span class="Delimiter">(</span>const string_tree* a<span class="Delimiter">,</span> const string_tree* b<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!a<span class="Delimiter">)</span> <span class="Identifier">return</span> !b<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!b<span class="Delimiter">)</span> <span class="Identifier">return</span> !a<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>a<span class="Delimiter">-></span>value == <span class="Constant">"literal"</span> && b<span class="Delimiter">-></span>value == <span class="Constant">"literal"</span><span class="Delimiter">)</span> + <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>a<span class="Delimiter">-></span>value == <span class="Constant">"literal"</span><span class="Delimiter">)</span> + <span class="Identifier">return</span> Literal_type_names<span class="Delimiter">.</span>find<span class="Delimiter">(</span>b<span class="Delimiter">-></span>value<span class="Delimiter">)</span> != Literal_type_names<span class="Delimiter">.</span>end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>b<span class="Delimiter">-></span>value == <span class="Constant">"literal"</span><span class="Delimiter">)</span> + <span class="Identifier">return</span> Literal_type_names<span class="Delimiter">.</span>find<span class="Delimiter">(</span>a<span class="Delimiter">-></span>value<span class="Delimiter">)</span> != Literal_type_names<span class="Delimiter">.</span>end<span class="Delimiter">();</span> <span class="Identifier">return</span> a<span class="Delimiter">-></span>value == b<span class="Delimiter">-></span>value - && exact_match<span class="Delimiter">(</span>a<span class="Delimiter">-></span>left<span class="Delimiter">,</span> b<span class="Delimiter">-></span>left<span class="Delimiter">)</span> - && exact_match<span class="Delimiter">(</span>a<span class="Delimiter">-></span>right<span class="Delimiter">,</span> b<span class="Delimiter">-></span>right<span class="Delimiter">);</span> + && deeply_equal_types<span class="Delimiter">(</span>a<span class="Delimiter">-></span>left<span class="Delimiter">,</span> b<span class="Delimiter">-></span>left<span class="Delimiter">)</span> + && deeply_equal_types<span class="Delimiter">(</span>a<span class="Delimiter">-></span>right<span class="Delimiter">,</span> b<span class="Delimiter">-></span>right<span class="Delimiter">);</span> <span class="Delimiter">}</span> string next_unused_recipe_name<span class="Delimiter">(</span>const string& recipe_name<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -141,32 +155,33 @@ recipe test a:number<span class="Delimiter">,</span> b:number <span class="Delim ] <span class="traceContains">+mem: storing 2 in location 7</span> -<span class="Comment">//: after insert_fragments (tangle) and before computing operation ids</span> <span class="Comment">//: after filling in all missing types (because we'll be introducing 'blank' types in this transform in a later layer, for shape-shifting recipes)</span> -<span class="Delimiter">:(after "Transform.push_back(deduce_types_from_header)")</span> +<span class="Delimiter">:(after "End Type Modifying Transforms")</span> Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>resolve_ambiguous_calls<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> <span class="Delimiter">:(code)</span> void resolve_ambiguous_calls<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> recipe& caller_recipe = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"--- resolve ambiguous calls for recipe "</span> << caller_recipe<span class="Delimiter">.</span>name << end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr << "--- resolve ambiguous calls for recipe " << caller_recipe.name << '\n';</span> for <span class="Delimiter">(</span>long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> index < SIZE<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> instruction& inst = caller_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span> if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>is_label<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> - if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> - assert<span class="Delimiter">(</span>!get<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>name<span class="Delimiter">).</span>empty<span class="Delimiter">());</span> + if <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>name<span class="Delimiter">).</span>empty<span class="Delimiter">())</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> replace_best_variant<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">);</span> <span class="Delimiter">}</span> -<span class="CommentedCode">//? if (caller_recipe.name == "main") cerr << "=============== " << debug_string(caller_recipe) << '\n';</span> <span class="Delimiter">}</span> void replace_best_variant<span class="Delimiter">(</span>instruction& inst<span class="Delimiter">,</span> const recipe& caller_recipe<span class="Delimiter">)</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"instruction "</span> << inst<span class="Delimiter">.</span>name << end<span class="Delimiter">();</span> vector<recipe_ordinal>& variants = get<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>name<span class="Delimiter">);</span> +<span class="CommentedCode">//? trace(9992, "transform") << "checking base: " << get(Recipe_ordinal, inst.name) << end();</span> long long int best_score = variant_score<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>name<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"score for base: "</span> << best_score << end<span class="Delimiter">();</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>variants<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? trace(9992, "transform") << "checking variant " << i << ": " << variants.at(i) << end();</span> long long int current_score = variant_score<span class="Delimiter">(</span>inst<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> - trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"checking variant "</span> << i << <span class="Constant">": "</span> << current_score << end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"score for variant "</span> << i << <span class="Constant">": "</span> << current_score << end<span class="Delimiter">();</span> if <span class="Delimiter">(</span>current_score > best_score<span class="Delimiter">)</span> <span class="Delimiter">{</span> inst<span class="Delimiter">.</span>name = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)).</span>name<span class="Delimiter">;</span> best_score = current_score<span class="Delimiter">;</span> @@ -176,32 +191,74 @@ void replace_best_variant<span class="Delimiter">(</span>instruction& inst<s <span class="Delimiter">}</span> long long int variant_score<span class="Delimiter">(</span>const instruction& inst<span class="Delimiter">,</span> recipe_ordinal variant<span class="Delimiter">)</span> <span class="Delimiter">{</span> + long long int result = <span class="Constant">1000</span><span class="Delimiter">;</span> if <span class="Delimiter">(</span>variant == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Comment">// ghost from a previous test</span> +<span class="CommentedCode">//? cerr << "variant score: " << inst.to_string() << '\n';</span> + if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">))</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>variant < MAX_PRIMITIVE_RECIPES<span class="Delimiter">);</span> + <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> const vector<reagent>& header_ingredients = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>ingredients<span class="Delimiter">;</span> if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> < SIZE<span class="Delimiter">(</span>header_ingredients<span class="Delimiter">))</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"too few ingredients"</span> << end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr << "too few ingredients\n";</span> <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> +<span class="CommentedCode">//? cerr << "=== checking ingredients\n";</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>header_ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>header_ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"mismatch: ingredient "</span> << i << end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr << "mismatch: ingredient " << i << '\n';</span> <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>types_strictly_match<span class="Delimiter">(</span>header_ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"strict match: ingredient "</span> << i << end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr << "strict match: ingredient " << i << '\n';</span> + <span class="Delimiter">}</span> + else if <span class="Delimiter">(</span>boolean_matches_literal<span class="Delimiter">(</span>header_ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + <span class="Comment">// slight penalty for coercing literal to boolean (prefer direct conversion to number if possible)</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"boolean matches literal: ingredient "</span> << i << end<span class="Delimiter">();</span> + result--<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + <span class="Comment">// slightly larger penalty for modifying type in other ways</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"non-strict match: ingredient "</span> << i << end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr << "non-strict match: ingredient " << i << '\n';</span> + result-=<span class="Constant">10</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> <span class="Delimiter">}</span> +<span class="CommentedCode">//? cerr << "=== done checking ingredients\n";</span> if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> > SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>products<span class="Delimiter">))</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"too few products"</span> << end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr << "too few products\n";</span> <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> const vector<reagent>& header_products = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>products<span class="Delimiter">;</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>header_products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"mismatch: product "</span> << i << end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr << "mismatch: product " << i << '\n';</span> <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>types_strictly_match<span class="Delimiter">(</span>header_products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"strict match: product "</span> << i << end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr << "strict match: product " << i << '\n';</span> + <span class="Delimiter">}</span> + else if <span class="Delimiter">(</span>boolean_matches_literal<span class="Delimiter">(</span>header_products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> + <span class="Comment">// slight penalty for coercing literal to boolean (prefer direct conversion to number if possible)</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"boolean matches literal: product "</span> << i << end<span class="Delimiter">();</span> + result--<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + <span class="Comment">// slightly larger penalty for modifying type in other ways</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"non-strict match: product "</span> << i << end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr << "non-strict match: product " << i << '\n';</span> + result-=<span class="Constant">10</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> <span class="Delimiter">}</span> - <span class="Comment">// the greater the number of unused ingredients, the lower the score</span> - <span class="Identifier">return</span> <span class="Constant">100</span> - <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>products<span class="Delimiter">)</span>-SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">))</span> - - <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span>-SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>ingredients<span class="Delimiter">));</span> <span class="Comment">// ok to go negative</span> + <span class="Comment">// the greater the number of unused ingredients/products, the lower the score</span> + <span class="Identifier">return</span> result - <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>products<span class="Delimiter">)</span>-SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">))</span> + - <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span>-SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variant<span class="Delimiter">).</span>ingredients<span class="Delimiter">));</span> <span class="Comment">// ok to go negative</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario static_dispatch_disabled_on_headerless_definition)</span> @@ -223,6 +280,154 @@ recipe test a:number <span class="Delimiter">-></span> z:number [ z<span class="Special"> <- </span>copy <span class="Constant">1</span> ] <span class="traceContains">+warn: redefining recipe test</span> + +<span class="Delimiter">:(scenario static_dispatch_on_primitive_names)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">3</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">2</span>:number + <span class="Constant">4</span>:boolean<span class="Special"> <- </span>copy <span class="Constant">0</span>/<span class="Constant">false</span> + <span class="Constant">5</span>:boolean<span class="Special"> <- </span>copy <span class="Constant">0</span>/<span class="Constant">false</span> + <span class="Constant">6</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">4</span>:boolean<span class="Delimiter">,</span> <span class="Constant">5</span>:boolean +] + +<span class="Comment"># temporarily hardcode number equality to always fail</span> +recipe equal x:number<span class="Delimiter">,</span> y:number <span class="Delimiter">-></span> z:boolean [ + local-scope + load-ingredients + z<span class="Special"> <- </span>copy <span class="Constant">0</span>/<span class="Constant">false</span> +] +<span class="Comment"># comparing numbers used overload</span> +<span class="traceContains">+mem: storing 0 in location 3</span> +<span class="Comment"># comparing booleans continues to use primitive</span> +<span class="traceContains">+mem: storing 1 in location 6</span> + +<span class="Delimiter">:(scenario static_dispatch_prefers_literals_to_be_numbers_rather_than_addresses)</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>foo <span class="Constant">0</span> +] +recipe foo x:address:number <span class="Delimiter">-></span> y:number [ + reply <span class="Constant">34</span> +] +recipe foo x:number <span class="Delimiter">-></span> y:number [ + reply <span class="Constant">35</span> +] +<span class="traceContains">+mem: storing 35 in location 1</span> + +<span class="Delimiter">:(scenario static_dispatch_on_non_literal_character_ignores_variant_with_numbers)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + local-scope + x:character<span class="Special"> <- </span>copy <span class="Constant">10</span>/newline + <span class="Constant">1</span>:number/<span class="Special">raw <- </span>foo x +] +recipe foo x:number <span class="Delimiter">-></span> y:number [ + load-ingredients + reply <span class="Constant">34</span> +] +<span class="traceContains">+error: foo: wrong type for ingredient x:number</span> +<span class="traceAbsent">-mem: storing 34 in location 1</span> + +<span class="Delimiter">:(scenario static_dispatch_dispatches_literal_to_boolean_before_character)</span> +recipe main [ + <span class="Constant">1</span>:number/<span class="Special">raw <- </span>foo <span class="Constant">0</span> <span class="Comment"># valid literal for boolean</span> +] +recipe foo x:character <span class="Delimiter">-></span> y:number [ + local-scope + load-ingredients + reply <span class="Constant">34</span> +] +recipe foo x:boolean <span class="Delimiter">-></span> y:number [ + local-scope + load-ingredients + reply <span class="Constant">35</span> +] +<span class="Comment"># boolean variant is preferred</span> +<span class="traceContains">+mem: storing 35 in location 1</span> + +<span class="Delimiter">:(scenario static_dispatch_dispatches_literal_to_character_when_out_of_boolean_range)</span> +recipe main [ + <span class="Constant">1</span>:number/<span class="Special">raw <- </span>foo <span class="Constant">97</span> <span class="Comment"># not a valid literal for boolean</span> +] +recipe foo x:character <span class="Delimiter">-></span> y:number [ + local-scope + load-ingredients + reply <span class="Constant">34</span> +] +recipe foo x:boolean <span class="Delimiter">-></span> y:number [ + local-scope + load-ingredients + reply <span class="Constant">35</span> +] +<span class="Comment"># character variant is preferred</span> +<span class="traceContains">+mem: storing 34 in location 1</span> + +<span class="Delimiter">:(scenario static_dispatch_dispatches_literal_to_number_if_at_all_possible)</span> +recipe main [ + <span class="Constant">1</span>:number/<span class="Special">raw <- </span>foo <span class="Constant">97</span> +] +recipe foo x:character <span class="Delimiter">-></span> y:number [ + local-scope + load-ingredients + reply <span class="Constant">34</span> +] +recipe foo x:number <span class="Delimiter">-></span> y:number [ + local-scope + load-ingredients + reply <span class="Constant">35</span> +] +<span class="Comment"># number variant is preferred</span> +<span class="traceContains">+mem: storing 35 in location 1</span> + +<span class="Comment">//: after we make all attempts to dispatch, any unhandled cases will end up at</span> +<span class="Comment">//: some wrong variant and trigger an error while trying to load-ingredients</span> + +<span class="Delimiter">:(scenario static_dispatch_shows_clear_error_on_missing_variant)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>foo <span class="Constant">34</span> +] +recipe foo x:boolean <span class="Delimiter">-></span> y:number [ + local-scope + load-ingredients + reply <span class="Constant">35</span> +] +<span class="traceContains">+error: foo: wrong type for ingredient x:boolean</span> +<span class="traceContains">+error: (we're inside recipe foo x:boolean -> y:number)</span> +<span class="traceContains">+error: (we're trying to call '1:number <- foo 34' inside recipe main)</span> + +<span class="Delimiter">:(before "End next-ingredient Type Mismatch Error")</span> +raise_error << <span class="Constant">" (we're inside "</span> << header_label<span class="Delimiter">(</span>current_call<span class="Delimiter">().</span>running_recipe<span class="Delimiter">)</span> << <span class="Constant">")</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> +raise_error << <span class="Constant">" (we're trying to call '"</span> << to_instruction<span class="Delimiter">(</span>*++Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>begin<span class="Delimiter">()).</span>to_string<span class="Delimiter">()</span> << <span class="Constant">"' inside "</span> << header_label<span class="Delimiter">((</span>++Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>begin<span class="Delimiter">())-></span>running_recipe<span class="Delimiter">)</span> << <span class="Constant">")</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + +<span class="Delimiter">:(scenario static_dispatch_shows_clear_error_on_missing_variant_2)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + <span class="Constant">1</span>:boolean<span class="Special"> <- </span>foo <span class="Constant">34</span> +] +recipe foo x:number <span class="Delimiter">-></span> y:number [ + local-scope + load-ingredients + reply x +] +<span class="traceContains">+error: foo: reply ingredient x can't be saved in 1:boolean</span> +<span class="traceContains">+error: (we just returned from recipe foo x:number -> y:number)</span> + +<span class="Delimiter">:(before "End reply Type Mismatch Error")</span> +raise_error << <span class="Constant">" (we just returned from "</span> << header_label<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>operation<span class="Delimiter">)</span> << <span class="Constant">")</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + +<span class="Delimiter">:(code)</span> +string header_label<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const recipe& caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> + ostringstream out<span class="Delimiter">;</span> + out << <span class="Constant">"recipe "</span> << caller<span class="Delimiter">.</span>name<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> + out << <span class="Constant">' '</span> << caller<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!caller<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> out << <span class="Constant">" ->"</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> + out << <span class="Constant">' '</span> << caller<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string<span class="Delimiter">;</span> + <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> +<span class="Delimiter">}</span> </pre> </body> </html> |