diff options
Diffstat (limited to 'html/059shape_shifting_recipe.cc.html')
-rw-r--r-- | html/059shape_shifting_recipe.cc.html | 252 |
1 files changed, 230 insertions, 22 deletions
diff --git a/html/059shape_shifting_recipe.cc.html b/html/059shape_shifting_recipe.cc.html index 2df37fa3..13c436c4 100644 --- a/html/059shape_shifting_recipe.cc.html +++ b/html/059shape_shifting_recipe.cc.html @@ -16,6 +16,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } .traceContains { color: #008000; } .Special { color: #ff6060; } .cSpecial { color: #008000; } +.CommentedCode { color: #6c6c6c; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .SalientComment { color: #00ffff; } @@ -54,11 +55,26 @@ recipe foo a:_t <span class="Delimiter">-></span> result:_t [ <span class="traceContains">+mem: storing 14 in location 11</span> <span class="traceContains">+mem: storing 15 in location 12</span> -<span class="Comment">//: Before anything else, disable transforms for shape-shifting recipes.</span> +<span class="Comment">//: Before anything else, disable transforms for shape-shifting recipes and</span> +<span class="Comment">//: make sure we never try to actually run a shape-shifting recipe. We should</span> +<span class="Comment">//: be rewriting such instructions to *specializations* with the type</span> +<span class="Comment">//: ingredients filled in.</span> <span class="Delimiter">:(before "End Transform Checks")</span> if <span class="Delimiter">(</span>any_type_ingredient_in_header<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">recipe_ordinal</span><span class="Comment">*/</span>p<span class="Delimiter">-></span>first<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> +<span class="Delimiter">:(after "Running One Instruction")</span> +if <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>running_step_index == <span class="Constant">0</span> + && any_type_ingredient_in_header<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>running_recipe<span class="Delimiter">))</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? DUMP("");</span> + raise_error << <span class="Constant">"ran into unspecialized shape-shifting recipe "</span> << current_recipe_name<span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: Make sure we don't match up literals with type ingredients without</span> +<span class="Comment">//: specialization.</span> +<span class="Delimiter">:(before "End valid_type_for_literal Special-cases")</span> +if <span class="Delimiter">(</span>contains_type_ingredient_name<span class="Delimiter">(</span>lhs<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Comment">//: We'll be creating recipes without loading them from anywhere by</span> <span class="Comment">//: *specializing* existing recipes, so make sure we don't clear any of those</span> <span class="Comment">//: when we start running tests.</span> @@ -68,24 +84,35 @@ recently_added_types<span class="Delimiter">.</span>clear<span class="Delimiter" <span class="Delimiter">:(before "End Instruction Dispatch(inst, best_score)")</span> if <span class="Delimiter">(</span>best_score == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? if (inst.name == "push-duplex") Trace_stream = new trace_stream;</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">"no variant found; searching for variant with suitable type ingredients"</span> << end<span class="Delimiter">();</span> recipe_ordinal exemplar = pick_matching_shape_shifting_variant<span class="Delimiter">(</span>variants<span class="Delimiter">,</span> inst<span class="Delimiter">,</span> best_score<span class="Delimiter">);</span> if <span class="Delimiter">(</span>exemplar<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">"found variant to specialize: "</span> << exemplar << <span class="Constant">' '</span> << get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> exemplar<span class="Delimiter">).</span>name << end<span class="Delimiter">();</span> variants<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_variant<span class="Delimiter">(</span>exemplar<span class="Delimiter">,</span> inst<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">));</span> +<span class="CommentedCode">//? cerr << "-- replacing " << inst.name << " with " << get(Recipe, variants.back()).name << '\n' << debug_string(get(Recipe, variants.back()));</span> inst<span class="Delimiter">.</span>name = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> variants<span class="Delimiter">.</span>back<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">"new specialization: "</span> << inst<span class="Delimiter">.</span>name << end<span class="Delimiter">();</span> <span class="Delimiter">}</span> +<span class="CommentedCode">//? if (inst.name == "push-duplex") {</span> +<span class="CommentedCode">//? cerr << "======== {\n";</span> +<span class="CommentedCode">//? cerr << inst.to_string() << '\n';</span> +<span class="CommentedCode">//? DUMP("");</span> +<span class="CommentedCode">//? cerr << "======== }\n";</span> +<span class="CommentedCode">//? }</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> recipe_ordinal pick_matching_shape_shifting_variant<span class="Delimiter">(</span>vector<recipe_ordinal>& variants<span class="Delimiter">,</span> const instruction& inst<span class="Delimiter">,</span> long long int& best_score<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cerr << "---- " << inst.name << ": " << non_ghost_size(variants) << '\n';</span> recipe_ordinal result = <span class="Constant">0</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>variants<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// ghost from a previous test</span> +<span class="CommentedCode">//? cerr << "-- variant " << i << "\n" << debug_string(get(Recipe, variants.at(i)));</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 shape-shifting variant "</span> << i << end<span class="Delimiter">();</span> long long int current_score = shape_shifting_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">"final score: "</span> << current_score << end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr << get(Recipe, variants.at(i)).name << ": " << current_score << '\n';</span> if <span class="Delimiter">(</span>current_score > best_score<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">"matches"</span> << end<span class="Delimiter">();</span> result = variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> @@ -96,6 +123,7 @@ recipe_ordinal pick_matching_shape_shifting_variant<span class="Delimiter">(</sp <span class="Delimiter">}</span> long long int shape_shifting_variant_score<span class="Delimiter">(</span>const instruction& inst<span class="Delimiter">,</span> recipe_ordinal variant<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cerr << "======== " << inst.to_string() << '\n';</span> if <span class="Delimiter">(</span>!any_type_ingredient_in_header<span class="Delimiter">(</span>variant<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">"no type ingredients"</span> << end<span class="Delimiter">();</span> <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> @@ -106,7 +134,7 @@ long long int shape_shifting_variant_score<span class="Delimiter">(</span>const <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</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>header_ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!non_type_ingredients_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> + if <span class="Delimiter">(</span>!deeply_equal_concrete_types<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="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -117,7 +145,7 @@ long long int shape_shifting_variant_score<span class="Delimiter">(</span>const <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>!non_type_ingredients_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> + if <span class="Delimiter">(</span>!deeply_equal_concrete_types<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="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -139,9 +167,29 @@ bool any_type_ingredient_in_header<span class="Delimiter">(</span>recipe_ordinal <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -bool non_type_ingredients_match<span class="Delimiter">(</span>const reagent& lhs<span class="Delimiter">,</span> const reagent& rhs<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>contains_type_ingredient_name<span class="Delimiter">(</span>lhs<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> - <span class="Identifier">return</span> types_match<span class="Delimiter">(</span>lhs<span class="Delimiter">,</span> rhs<span class="Delimiter">);</span> +bool deeply_equal_concrete_types<span class="Delimiter">(</span>reagent lhs<span class="Delimiter">,</span> reagent rhs<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cerr << debug_string(lhs) << " vs " << debug_string(rhs) << '\n';</span> +<span class="CommentedCode">//? bool result = deeply_equal_concrete_types(lhs.properties.at(0).second, rhs.properties.at(0).second, rhs);</span> +<span class="CommentedCode">//? cerr << " => " << result << '\n';</span> +<span class="CommentedCode">//? return result;</span> +<span class="CommentedCode">//? cerr << "== " << debug_string(lhs) << " vs " << debug_string(rhs) << '\n';</span> + canonize_type<span class="Delimiter">(</span>lhs<span class="Delimiter">);</span> + canonize_type<span class="Delimiter">(</span>rhs<span class="Delimiter">);</span> + <span class="Identifier">return</span> deeply_equal_concrete_types<span class="Delimiter">(</span>lhs<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">,</span> rhs<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">,</span> rhs<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +bool deeply_equal_concrete_types<span class="Delimiter">(</span>const string_tree* lhs<span class="Delimiter">,</span> const string_tree* rhs<span class="Delimiter">,</span> const reagent& rhs_reagent<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!lhs<span class="Delimiter">)</span> <span class="Identifier">return</span> !rhs<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!rhs<span class="Delimiter">)</span> <span class="Identifier">return</span> !lhs<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>is_type_ingredient_name<span class="Delimiter">(</span>lhs<span class="Delimiter">-></span>value<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Comment">// type ingredient matches anything</span> + if <span class="Delimiter">(</span>Literal_type_names<span class="Delimiter">.</span>find<span class="Delimiter">(</span>lhs<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> Literal_type_names<span class="Delimiter">.</span>find<span class="Delimiter">(</span>rhs<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>rhs<span class="Delimiter">-></span>value == <span class="Constant">"literal"</span> && lhs<span class="Delimiter">-></span>value == <span class="Constant">"address"</span><span class="Delimiter">)</span> + <span class="Identifier">return</span> rhs_reagent<span class="Delimiter">.</span>name == <span class="Constant">"0"</span><span class="Delimiter">;</span> +<span class="CommentedCode">//? cerr << lhs->value << " vs " << rhs->value << '\n';</span> + <span class="Identifier">return</span> lhs<span class="Delimiter">-></span>value == rhs<span class="Delimiter">-></span>value + && deeply_equal_concrete_types<span class="Delimiter">(</span>lhs<span class="Delimiter">-></span>left<span class="Delimiter">,</span> rhs<span class="Delimiter">-></span>left<span class="Delimiter">,</span> rhs_reagent<span class="Delimiter">)</span> + && deeply_equal_concrete_types<span class="Delimiter">(</span>lhs<span class="Delimiter">-></span>right<span class="Delimiter">,</span> rhs<span class="Delimiter">-></span>right<span class="Delimiter">,</span> rhs_reagent<span class="Delimiter">);</span> <span class="Delimiter">}</span> bool contains_type_ingredient_name<span class="Delimiter">(</span>const reagent& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -183,7 +231,7 @@ recipe_ordinal new_variant<span class="Delimiter">(</span>recipe_ordinal exempla delete p<span class="Delimiter">-></span>second<span class="Delimiter">;</span> if <span class="Delimiter">(</span>error<span class="Delimiter">)</span> <span class="Identifier">return</span> exemplar<span class="Delimiter">;</span> <span class="Delimiter">}</span> - ensure_all_concrete_types<span class="Delimiter">(</span>new_recipe<span class="Delimiter">);</span> + ensure_all_concrete_types<span class="Delimiter">(</span>new_recipe<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> exemplar<span class="Delimiter">));</span> <span class="Comment">// finally, perform all transforms on the new specialization</span> for <span class="Delimiter">(</span>long long int t = <span class="Constant">0</span><span class="Delimiter">;</span> t < SIZE<span class="Delimiter">(</span>Transform<span class="Delimiter">);</span> ++t<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Delimiter">(</span>*Transform<span class="Delimiter">.</span>at<span class="Delimiter">(</span>t<span class="Delimiter">))(</span>new_recipe_ordinal<span class="Delimiter">);</span> @@ -227,14 +275,17 @@ void save_or_deduce_type_name<span class="Delimiter">(</span>reagent& x<span <span class="Delimiter">}</span> void compute_type_ingredient_mappings<span class="Delimiter">(</span>const recipe& exemplar<span class="Delimiter">,</span> const instruction& inst<span class="Delimiter">,</span> map<string<span class="Delimiter">,</span> const string_tree*>& mappings<span class="Delimiter">,</span> const recipe& caller_recipe<span class="Delimiter">,</span> bool* error<span class="Delimiter">)</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>exemplar<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + long long int limit = min<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">),</span> SIZE<span class="Delimiter">(</span>exemplar<span class="Delimiter">.</span>ingredients<span class="Delimiter">));</span> + for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i < limit<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> const reagent& exemplar_reagent = exemplar<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> reagent ingredient = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> assert<span class="Delimiter">(</span>ingredient<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">);</span> canonize_type<span class="Delimiter">(</span>ingredient<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>exemplar_reagent<span class="Delimiter">)</span> && ingredient<span class="Delimiter">.</span>name == <span class="Constant">"0"</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// assume it matches</span> accumulate_type_ingredients<span class="Delimiter">(</span>exemplar_reagent<span class="Delimiter">,</span> ingredient<span class="Delimiter">,</span> mappings<span class="Delimiter">,</span> exemplar<span class="Delimiter">,</span> inst<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">,</span> error<span class="Delimiter">);</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>exemplar<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + limit = min<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">),</span> SIZE<span class="Delimiter">(</span>exemplar<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 < limit<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> const reagent& exemplar_reagent = exemplar<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> reagent product = inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> assert<span class="Delimiter">(</span>product<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">);</span> @@ -243,6 +294,10 @@ void compute_type_ingredient_mappings<span class="Delimiter">(</span>const recip <span class="Delimiter">}</span> <span class="Delimiter">}</span> +inline long long int min<span class="Delimiter">(</span>long long int a<span class="Delimiter">,</span> long long int b<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> <span class="Delimiter">(</span>a < b<span class="Delimiter">)</span> ? a : b<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + void accumulate_type_ingredients<span class="Delimiter">(</span>const reagent& exemplar_reagent<span class="Delimiter">,</span> reagent& refinement<span class="Delimiter">,</span> map<string<span class="Delimiter">,</span> const string_tree*>& mappings<span class="Delimiter">,</span> const recipe& exemplar<span class="Delimiter">,</span> const instruction& call_instruction<span class="Delimiter">,</span> const recipe& caller_recipe<span class="Delimiter">,</span> bool* error<span class="Delimiter">)</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>refinement<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">);</span> accumulate_type_ingredients<span class="Delimiter">(</span>exemplar_reagent<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">,</span> refinement<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">,</span> mappings<span class="Delimiter">,</span> exemplar<span class="Delimiter">,</span> exemplar_reagent<span class="Delimiter">,</span> call_instruction<span class="Delimiter">,</span> caller_recipe<span class="Delimiter">,</span> error<span class="Delimiter">);</span> @@ -262,11 +317,15 @@ void accumulate_type_ingredients<span class="Delimiter">(</span>const string_tre <span class="Delimiter">}</span> if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>mappings<span class="Delimiter">,</span> exemplar_type<span class="Delimiter">-></span>value<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">"adding mapping from "</span> << exemplar_type<span class="Delimiter">-></span>value << <span class="Constant">" to "</span> << debug_string<span class="Delimiter">(</span>refinement_type<span class="Delimiter">)</span> << end<span class="Delimiter">();</span> - put<span class="Delimiter">(</span>mappings<span class="Delimiter">,</span> exemplar_type<span class="Delimiter">-></span>value<span class="Delimiter">,</span> new string_tree<span class="Delimiter">(</span>*refinement_type<span class="Delimiter">));</span> + if <span class="Delimiter">(</span>refinement_type<span class="Delimiter">-></span>value == <span class="Constant">"literal"</span><span class="Delimiter">)</span> + put<span class="Delimiter">(</span>mappings<span class="Delimiter">,</span> exemplar_type<span class="Delimiter">-></span>value<span class="Delimiter">,</span> new string_tree<span class="Delimiter">(</span><span class="Constant">"number"</span><span class="Delimiter">));</span> + else + put<span class="Delimiter">(</span>mappings<span class="Delimiter">,</span> exemplar_type<span class="Delimiter">-></span>value<span class="Delimiter">,</span> new string_tree<span class="Delimiter">(</span>*refinement_type<span class="Delimiter">));</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!deeply_equal<span class="Delimiter">(</span>get<span class="Delimiter">(</span>mappings<span class="Delimiter">,</span> exemplar_type<span class="Delimiter">-></span>value<span class="Delimiter">),</span> refinement_type<span class="Delimiter">))</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!deeply_equal_types<span class="Delimiter">(</span>get<span class="Delimiter">(</span>mappings<span class="Delimiter">,</span> exemplar_type<span class="Delimiter">-></span>value<span class="Delimiter">),</span> refinement_type<span class="Delimiter">))</span> <span class="Delimiter">{</span> raise_error << maybe<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"no call found for '"</span> << call_instruction<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> +<span class="CommentedCode">//? cerr << exemplar_type->value << ": " << debug_string(get(mappings, exemplar_type->value)) << " vs " << debug_string(refinement_type) << '\n';</span> *error = <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -330,31 +389,39 @@ void replace_type_ingredients<span class="Delimiter">(</span>string_tree* type<s replace_type_ingredients<span class="Delimiter">(</span>type<span class="Delimiter">-></span>right<span class="Delimiter">,</span> mappings<span class="Delimiter">);</span> <span class="Delimiter">}</span> -void ensure_all_concrete_types<span class="Delimiter">(</span>const recipe& new_recipe<span class="Delimiter">)</span> <span class="Delimiter">{</span> +void ensure_all_concrete_types<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">const</span><span class="Comment">*/</span> recipe& new_recipe<span class="Delimiter">,</span> const recipe& exemplar<span class="Delimiter">)</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>new_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> - ensure_all_concrete_types<span class="Delimiter">(</span>new_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">);</span> + ensure_all_concrete_types<span class="Delimiter">(</span>new_recipe<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> exemplar<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>new_recipe<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> - ensure_all_concrete_types<span class="Delimiter">(</span>new_recipe<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">);</span> + ensure_all_concrete_types<span class="Delimiter">(</span>new_recipe<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> exemplar<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>new_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - const instruction& inst = new_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + instruction& inst = new_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> - ensure_all_concrete_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>type<span class="Delimiter">);</span> + ensure_all_concrete_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">),</span> exemplar<span class="Delimiter">);</span> for <span class="Delimiter">(</span>long long int j = <span class="Constant">0</span><span class="Delimiter">;</span> j < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> - ensure_all_concrete_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">).</span>type<span class="Delimiter">);</span> + ensure_all_concrete_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">),</span> exemplar<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> -void ensure_all_concrete_types<span class="Delimiter">(</span>const type_tree* x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - if <span class="Delimiter">(</span>!x<span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << <span class="Constant">"null type</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> +void ensure_all_concrete_types<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">const</span><span class="Comment">*/</span> reagent& x<span class="Delimiter">,</span> const recipe& exemplar<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error << maybe<span class="Delimiter">(</span>exemplar<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"failed to map a type to "</span> << x<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + x<span class="Delimiter">.</span>type = new type_tree<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// just to prevent crashes later</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - if <span class="Delimiter">(</span>x<span class="Delimiter">-></span>value == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << <span class="Constant">"unknown type</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise_error << maybe<span class="Delimiter">(</span>exemplar<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"failed to map a type to the unknown "</span> << x<span class="Delimiter">.</span>original_string << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> +long long int non_ghost_size<span class="Delimiter">(</span>vector<recipe_ordinal>& variants<span class="Delimiter">)</span> <span class="Delimiter">{</span> + long long int result = <span class="Constant">0</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>variants<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> + if <span class="Delimiter">(</span>variants<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> != -<span class="Constant">1</span><span class="Delimiter">)</span> ++result<span class="Delimiter">;</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + <span class="Delimiter">:(scenario shape_shifting_recipe_2)</span> recipe main [ <span class="Constant">10</span>:point<span class="Special"> <- </span>merge <span class="Constant">14</span><span class="Delimiter">,</span> <span class="Constant">15</span> @@ -476,6 +543,147 @@ recipe foo a:_t <span class="Delimiter">-></span> b:_t [ b<span class="Special"> <- </span>copy a ] <span class="traceContains">+error: main: no call found for 'b:address:number <- foo a'</span> + +<span class="Delimiter">:(scenario specialize_inside_recipe_without_header)</span> +recipe main [ + foo <span class="Constant">3</span> +] +recipe foo [ + local-scope + x:number<span class="Special"> <- </span>next-ingredient <span class="Comment"># ensure no header</span> + <span class="Constant">1</span>:number/<span class="Special">raw <- </span>bar x <span class="Comment"># call a shape-shifting recipe</span> +] +recipe bar x:_elem <span class="Delimiter">-></span> y:_elem [ + local-scope + load-ingredients + y<span class="Special"> <- </span>add x<span class="Delimiter">,</span> <span class="Constant">1</span> +] +<span class="traceContains">+mem: storing 4 in location 1</span> + +<span class="Delimiter">:(scenario specialize_with_literal)</span> +recipe main [ + local-scope + <span class="Comment"># permit literal to map to number</span> + <span class="Constant">1</span>:number/<span class="Special">raw <- </span>foo <span class="Constant">3</span> +] +recipe foo x:_elem <span class="Delimiter">-></span> y:_elem [ + local-scope + load-ingredients + y<span class="Special"> <- </span>add x<span class="Delimiter">,</span> <span class="Constant">1</span> +] +<span class="traceContains">+mem: storing 4 in location 1</span> + +<span class="Delimiter">:(scenario specialize_with_literal_2)</span> +recipe main [ + local-scope + <span class="Comment"># permit literal to map to character</span> + <span class="Constant">1</span>:character/<span class="Special">raw <- </span>foo <span class="Constant">3</span> +] +recipe foo x:_elem <span class="Delimiter">-></span> y:_elem [ + local-scope + load-ingredients + y<span class="Special"> <- </span>add x<span class="Delimiter">,</span> <span class="Constant">1</span> +] +<span class="traceContains">+mem: storing 4 in location 1</span> + +<span class="Delimiter">:(scenario specialize_with_literal_3)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + local-scope + <span class="Comment"># permit '0' to map to address to shape-shifting type-ingredient</span> + <span class="Constant">1</span>:address:character/<span class="Special">raw <- </span>foo <span class="Constant">0</span> +] +recipe foo x:address:_elem <span class="Delimiter">-></span> y:address:_elem [ + local-scope + load-ingredients + y<span class="Special"> <- </span>copy x +] +<span class="traceContains">+mem: storing 0 in location 1</span> +$error: <span class="Constant">0</span> + +<span class="Delimiter">:(scenario specialize_with_literal_4)</span> +<span class="Special">% Hide_errors = true;</span> +recipe main [ + local-scope + <span class="Comment"># ambiguous call: what's the type of its ingredient?!</span> + foo <span class="Constant">0</span> +] +recipe foo x:address:_elem <span class="Delimiter">-></span> y:address:_elem [ + local-scope + load-ingredients + y<span class="Special"> <- </span>copy x +] +<span class="traceContains">+error: foo: failed to map a type to x</span> +<span class="traceContains">+error: foo: failed to map a type to y</span> + +<span class="Delimiter">:(scenario specialize_with_literal_5)</span> +recipe main [ + foo <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">4</span> <span class="Comment"># recipe mapping two variables to literals</span> +] +recipe foo x:_elem<span class="Delimiter">,</span> y:_elem [ + local-scope + load-ingredients + <span class="Constant">1</span>:number/<span class="Special">raw <- </span>add x<span class="Delimiter">,</span> y +] +<span class="traceContains">+mem: storing 7 in location 1</span> + +<span class="Delimiter">:(scenario multiple_shape_shifting_variants)</span> +<span class="Comment"># try to call two different shape-shifting recipes with the same name</span> +recipe main [ + e1:d1:number<span class="Special"> <- </span>merge <span class="Constant">3</span> + e2:d2:number<span class="Special"> <- </span>merge <span class="Constant">4</span><span class="Delimiter">,</span> <span class="Constant">5</span> + <span class="Constant">1</span>:number/<span class="Special">raw <- </span>foo e1 + <span class="Constant">2</span>:number/<span class="Special">raw <- </span>foo e2 +] +<span class="Comment"># the two shape-shifting definitions</span> +recipe foo a:d1:_elem <span class="Delimiter">-></span> b:number [ + local-scope + load-ingredients + reply <span class="Constant">34</span> +] +recipe foo a:d2:_elem <span class="Delimiter">-></span> b:number [ + local-scope + load-ingredients + reply <span class="Constant">35</span> +] +<span class="Comment"># the shape-shifting containers they use</span> +container d1:_elem [ + x:_elem +] +container d2:_elem [ + x:number + y:_elem +] +<span class="traceContains">+mem: storing 34 in location 1</span> +<span class="traceContains">+mem: storing 35 in location 2</span> + +<span class="Delimiter">:(scenario multiple_shape_shifting_variants_2)</span> +<span class="Comment"># static dispatch between shape-shifting variants, _including pointer lookups_</span> +recipe main [ + e1:d1:number<span class="Special"> <- </span>merge <span class="Constant">3</span> + e2:address:d2:number<span class="Special"> <- </span>new <span class="Delimiter">{(</span>d2 number<span class="Delimiter">)</span>: type<span class="Delimiter">}</span> + <span class="Constant">1</span>:number/<span class="Special">raw <- </span>foo e1 + <span class="Constant">2</span>:number/<span class="Special">raw <- </span>foo *e2 <span class="Comment"># different from previous scenario</span> +] +recipe foo a:d1:_elem <span class="Delimiter">-></span> b:number [ + local-scope + load-ingredients + reply <span class="Constant">34</span> +] +recipe foo a:d2:_elem <span class="Delimiter">-></span> b:number [ + local-scope + load-ingredients + reply <span class="Constant">35</span> +] +container d1:_elem [ + x:_elem +] +container d2:_elem [ + x:number + y:_elem +] +<span class="traceContains">+mem: storing 34 in location 1</span> +<span class="traceContains">+mem: storing 35 in location 2</span> </pre> </body> </html> |