about summary refs log blame commit diff stats
path: root/html/057static_dispatch.cc.html
blob: 04d02ab2cf0beab0bc8f0422e5bbb19b853b51c4 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16















                                                                                                 
                                
                               
                             


                              
                                  


































                                                                                                                                                                                                                                                                                                                 
                                                                                                 

                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   






                                                                                                                                                                                                                                                                           










                                                                                                                                                                                                                                                                                                                                                     
                                                                                         
                                                                                                            



                                                    
                                                                                                                                                                                   




                                                                                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                 
                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                 





                                                                                                                                                                                                                                                                                                                 
                                  

                                                                                                                   





                                                                                                                                                                                                                                                                                                                                                                                       

                                                                                                                                                                                                                                                                                                                                                                                                                             
                                                                                                                
                                    

                                                                                                                                                                                                                                                                                                                   

                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                
                                    



                                                                                                           














                                                                                                                                                                                                                                                                                                      
                                                                                                                                 

                                                                                                                                                                                                                         





                                                                                                                                                                                                                             
                                                                                                                                                                                                            


















                                                                                                                                                                                                                                                    










                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                               
                                                                                 




                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                     


                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                             






                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                        
                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                               
                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                                            





                                                                                                                                                                                                                                                                            


                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 


                                                                                                                                                                                                              
                                                                                           
                                                                                                                                                                                                                                                                                    




                                                                                                                                                                                                  


                                                                                                                                                                                                                                                                                                                     
                                                                                           

                                                                                                           
                                                                                              


                                                                                                                                                                                                                                                                                                                                                                                               
                                                                                                                      

                                                                                                             














                                                                                                                                                                                                                                                                                                                                                                                                               
                                  
                                                                                                   

                                                                                                                                                                                                                                                                                                                                                                                           
                                                                                        



                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                         

                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                   

                                                                                                             














                                                                                                                                                                                                                                                                                                                                                                                                         
                                  


                                                                                                                                                                                                                                                                                                                                                                                                                            




















                                                                                              





















                                                                                                                                                                                                  
















































                                                                                                                                           





























































































































                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        























                                                                                                                      



                                     
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - 057static_dispatch.cc</title>
<meta name="Generator" content="Vim/7.4">
<meta name="plugin-version" content="vim7.4_v1">
<meta name="syntax" content="cpp">
<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
<meta name="colorscheme" content="minimal">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
body { font-family: monospace; color: #eeeeee; background-color: #080808; }
* { font-size: 1.05em; }
.traceContains { color: #008000; }
.traceAbsent { color: #c00000; }
.Identifier { color: #804000; }
.cSpecial { color: #008000; }
.Comment { color: #9090ff; }
.Delimiter { color: #a04060; }
.Special { color: #ff6060; }
.CommentedCode { color: #6c6c6c; }
.Constant { color: #00a0a0; }
-->
</style>

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

-->
</script>
</head>
<body>
<pre id='vimCodeElement'>
<span class="Comment">//: Transform to maintain multiple variants of a recipe depending on the</span>
<span class="Comment">//: number and types of the ingredients and products. Allows us to use nice</span>
<span class="Comment">//: names like 'print' or 'length' in many mutually extensible ways.</span>

<span class="Delimiter">:(scenario static_dispatch)</span>
recipe main [
  <span class="Constant">7</span>:number/<span class="Special">raw &lt;- </span>test <span class="Constant">3</span>
]
recipe test a:number <span class="Delimiter">-&gt;</span> z:number [
  z<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>
]
recipe test a:number<span class="Delimiter">,</span> b:number <span class="Delimiter">-&gt;</span> z:number [
  z<span class="Special"> &lt;- </span>copy <span class="Constant">2</span>
]
<span class="traceContains">+mem: storing 1 in location 7</span>

<span class="Comment">//: When loading recipes, accumulate variants if headers don't collide, and</span>
<span class="Comment">//: raise a warning if headers collide.</span>

<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
map&lt;string<span class="Delimiter">,</span> vector&lt;recipe_ordinal&gt; &gt; Recipe_variants<span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End One-time Setup&quot;)</span>
put<span class="Delimiter">(</span>Recipe_variants<span class="Delimiter">,</span> <span class="Constant">&quot;main&quot;</span><span class="Delimiter">,</span> vector&lt;recipe_ordinal&gt;<span class="Delimiter">());</span>  <span class="Comment">// since we manually added main to Recipe_ordinal</span>
<span class="Delimiter">:(before &quot;Clear Other State For Recently_added_recipes&quot;)</span>
for <span class="Delimiter">(</span>map&lt;string<span class="Delimiter">,</span> vector&lt;recipe_ordinal&gt; &gt;::iterator p = Recipe_variants<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Recipe_variants<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<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 &lt; SIZE<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    if <span class="Delimiter">(</span>find<span class="Delimiter">(</span>Recently_added_recipes<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> Recently_added_recipes<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> != Recently_added_recipes<span class="Delimiter">.</span>end<span class="Delimiter">())</span>
      p<span class="Delimiter">-&gt;</span>second<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="Comment">// just leave a ghost</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(before &quot;End Load Recipe Header(result)&quot;)</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">//?   LOG &lt;&lt; &quot;checking &quot; &lt;&lt; r &lt;&lt; &quot; &quot; &lt;&lt; result.name &lt;&lt; '\n';</span>
<span class="CommentedCode">//?   cerr &lt;&lt; result.name &lt;&lt; &quot;: &quot; &lt;&lt; contains_key(Recipe, r) &lt;&lt; (contains_key(Recipe, r) ? get(Recipe, r).has_header : 0) &lt;&lt; matching_variant_name(result) &lt;&lt; '\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> <span class="Delimiter">{</span>
    string new_name = matching_variant_name<span class="Delimiter">(</span>result<span class="Delimiter">);</span>
    if <span class="Delimiter">(</span>new_name<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span>
      <span class="Comment">// variant doesn't already exist</span>
      new_name = next_unused_recipe_name<span class="Delimiter">(</span>result<span class="Delimiter">.</span>name<span class="Delimiter">);</span>
<span class="CommentedCode">//?       LOG &lt;&lt; &quot;adding a variant of &quot; &lt;&lt; result.name &lt;&lt; &quot;: &quot; &lt;&lt; new_name &lt;&lt; &quot; is now &quot; &lt;&lt; Next_recipe_ordinal &lt;&lt; '\n';</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_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>
    <span class="Delimiter">}</span>
    result<span class="Delimiter">.</span>name = new_name<span class="Delimiter">;</span>
<span class="CommentedCode">//?     cerr &lt;&lt; &quot;=&gt; &quot; &lt;&lt; new_name &lt;&lt; '\n';</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>
else <span class="Delimiter">{</span>
  <span class="Comment">// save first variant</span>
<span class="CommentedCode">//?   LOG &lt;&lt; &quot;saving first variant of &quot; &lt;&lt; result.name &lt;&lt; &quot;: &quot; &lt;&lt; Next_recipe_ordinal &lt;&lt; '\n';</span>
  put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> result<span class="Delimiter">.</span>name<span class="Delimiter">,</span> Next_recipe_ordinal++<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> result<span class="Delimiter">.</span>name<span class="Delimiter">));</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(code)</span>
string matching_variant_name<span class="Delimiter">(</span>const recipe&amp; rr<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  const vector&lt;recipe_ordinal&gt;&amp; 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 &lt; SIZE<span class="Delimiter">(</span>variants<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="CommentedCode">//?     LOG &lt;&lt; &quot;checking variant &quot; &lt;&lt; variants.at(i) &lt;&lt; &quot; of &quot; &lt;&lt; rr.name &lt;&lt; '\n';</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> <span class="Identifier">continue</span><span class="Delimiter">;</span>
    const recipe&amp; candidate = 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>
    if <span class="Delimiter">(</span>!all_reagents_match<span class="Delimiter">(</span>rr<span class="Delimiter">,</span> candidate<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
<span class="CommentedCode">//?     LOG &lt;&lt; &quot;  exists\n&quot;;</span>
    <span class="Identifier">return</span> candidate<span class="Delimiter">.</span>name<span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
<span class="CommentedCode">//?   LOG &lt;&lt; &quot;  does not exist\n&quot;;</span>
  <span class="Identifier">return</span> <span class="Constant">&quot;&quot;</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

bool all_reagents_match<span class="Delimiter">(</span>const recipe&amp; r1<span class="Delimiter">,</span> const recipe&amp; r2<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>r1<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != SIZE<span class="Delimiter">(</span>r2<span class="Delimiter">.</span>ingredients<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
  if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>r1<span class="Delimiter">.</span>products<span class="Delimiter">)</span> != SIZE<span class="Delimiter">(</span>r2<span class="Delimiter">.</span>products<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
  for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>r1<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    if <span class="Delimiter">(</span>!deeply_equal_types<span class="Delimiter">(</span>r1<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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>
                            r2<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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> <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">}</span>
  for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>r1<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    if <span class="Delimiter">(</span>!deeply_equal_types<span class="Delimiter">(</span>r1<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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>
                            r2<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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> <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">}</span>
  <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
set&lt;string&gt; Literal_type_names<span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End One-time Setup&quot;)</span>
Literal_type_names<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">&quot;number&quot;</span><span class="Delimiter">);</span>
Literal_type_names<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">&quot;character&quot;</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">-&gt;</span>value == <span class="Constant">&quot;literal&quot;</span> &amp;&amp; b<span class="Delimiter">-&gt;</span>value == <span class="Constant">&quot;literal&quot;</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">-&gt;</span>value == <span class="Constant">&quot;literal&quot;</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">-&gt;</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">-&gt;</span>value == <span class="Constant">&quot;literal&quot;</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">-&gt;</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">-&gt;</span>value == b<span class="Delimiter">-&gt;</span>value
      &amp;&amp; deeply_equal_types<span class="Delimiter">(</span>a<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> b<span class="Delimiter">-&gt;</span>left<span class="Delimiter">)</span>
      &amp;&amp; deeply_equal_types<span class="Delimiter">(</span>a<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> b<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span>
<span class="Delimiter">}</span>

string next_unused_recipe_name<span class="Delimiter">(</span>const string&amp; recipe_name<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  for <span class="Delimiter">(</span>long long int i = <span class="Constant">2</span><span class="Delimiter">;</span> <span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    ostringstream out<span class="Delimiter">;</span>
    out &lt;&lt; recipe_name &lt;&lt; <span class="Constant">'_'</span> &lt;&lt; i<span class="Delimiter">;</span>
    if <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> out<span class="Delimiter">.</span>str<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="Delimiter">}</span>

<span class="Comment">//: Once all the recipes are loaded, transform their bodies to replace each</span>
<span class="Comment">//: call with the most suitable variant.</span>

<span class="Delimiter">:(scenario static_dispatch_picks_most_similar_variant)</span>
recipe main [
  <span class="Constant">7</span>:number/<span class="Special">raw &lt;- </span>test <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">4</span><span class="Delimiter">,</span> <span class="Constant">5</span>
]
recipe test a:number <span class="Delimiter">-&gt;</span> z:number [
  z<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>
]
recipe test a:number<span class="Delimiter">,</span> b:number <span class="Delimiter">-&gt;</span> z:number [
  z<span class="Special"> &lt;- </span>copy <span class="Constant">2</span>
]
<span class="traceContains">+mem: storing 2 in location 7</span>

<span class="Comment">//: support recipe headers in a previous transform to fill in missing types</span>
<span class="Delimiter">:(before &quot;End check_or_set_invalid_types&quot;)</span>
for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  check_or_set_invalid_types<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">,</span> caller<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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>
                             maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">),</span> <span class="Constant">&quot;recipe header ingredient&quot;</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 &lt; SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  check_or_set_invalid_types<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">,</span> caller<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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>
                             maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">),</span> <span class="Constant">&quot;recipe header product&quot;</span><span class="Delimiter">);</span>
<span class="Delimiter">}</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 &quot;End Type Modifying Transforms&quot;)</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&amp; 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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- resolve ambiguous calls for recipe &quot;</span> &lt;&lt; caller_recipe<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span>
<span class="CommentedCode">//?   cerr &lt;&lt; &quot;--- resolve ambiguous calls for recipe &quot; &lt;&lt; caller_recipe.name &lt;&lt; '\n';</span>
  for <span class="Delimiter">(</span>long long int index = <span class="Constant">0</span><span class="Delimiter">;</span> index &lt; 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&amp; 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>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="Delimiter">}</span>

void replace_best_variant<span class="Delimiter">(</span>instruction&amp; inst<span class="Delimiter">,</span> const recipe&amp; 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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;instruction &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span>
  vector&lt;recipe_ordinal&gt;&amp; 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, &quot;transform&quot;) &lt;&lt; &quot;checking base: &quot; &lt;&lt; get(Recipe_ordinal, inst.name) &lt;&lt; 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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;score for base: &quot;</span> &lt;&lt; best_score &lt;&lt; end<span class="Delimiter">();</span>
  for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>variants<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="CommentedCode">//?     trace(9992, &quot;transform&quot;) &lt;&lt; &quot;checking variant &quot; &lt;&lt; i &lt;&lt; &quot;: &quot; &lt;&lt; variants.at(i) &lt;&lt; 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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;score for variant &quot;</span> &lt;&lt; i &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; current_score &lt;&lt; end<span class="Delimiter">();</span>
    if <span class="Delimiter">(</span>current_score &gt; 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>
    <span class="Delimiter">}</span>
  <span class="Delimiter">}</span>
  <span class="Comment">// End Instruction Dispatch(inst, best_score)</span>
  if <span class="Delimiter">(</span>best_score == -<span class="Constant">1</span> &amp;&amp; get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>name<span class="Delimiter">)</span> &gt;= MAX_PRIMITIVE_RECIPES<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise_error &lt;&lt; maybe<span class="Delimiter">(</span>caller_recipe<span class="Delimiter">.</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;failed to find a matching call for '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>

long long int variant_score<span class="Delimiter">(</span>const instruction&amp; 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 &lt;&lt; &quot;variant score: &quot; &lt;&lt; inst.to_string() &lt;&lt; '\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 &lt; 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&lt;reagent&gt;&amp; 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> &lt; 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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;too few ingredients&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
<span class="CommentedCode">//?     cerr &lt;&lt; &quot;too few ingredients\n&quot;;</span>
    <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
<span class="CommentedCode">//?   cerr &lt;&lt; &quot;=== checking ingredients\n&quot;;</span>
  for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; 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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;mismatch: ingredient &quot;</span> &lt;&lt; i &lt;&lt; end<span class="Delimiter">();</span>
<span class="CommentedCode">//?       cerr &lt;&lt; &quot;mismatch: ingredient &quot; &lt;&lt; i &lt;&lt; '\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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;strict match: ingredient &quot;</span> &lt;&lt; i &lt;&lt; end<span class="Delimiter">();</span>
<span class="CommentedCode">//?       cerr &lt;&lt; &quot;strict match: ingredient &quot; &lt;&lt; i &lt;&lt; '\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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;boolean matches literal: ingredient &quot;</span> &lt;&lt; i &lt;&lt; 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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;non-strict match: ingredient &quot;</span> &lt;&lt; i &lt;&lt; end<span class="Delimiter">();</span>
<span class="CommentedCode">//?       cerr &lt;&lt; &quot;non-strict match: ingredient &quot; &lt;&lt; i &lt;&lt; '\n';</span>
      result-=<span class="Constant">10</span><span class="Delimiter">;</span>
    <span class="Delimiter">}</span>
  <span class="Delimiter">}</span>
<span class="CommentedCode">//?   cerr &lt;&lt; &quot;=== done checking ingredients\n&quot;;</span>
  if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> &gt; 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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;too few products&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
<span class="CommentedCode">//?     cerr &lt;&lt; &quot;too few products\n&quot;;</span>
    <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  const vector&lt;reagent&gt;&amp; 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 &lt; 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>is_dummy<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="Identifier">continue</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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;mismatch: product &quot;</span> &lt;&lt; i &lt;&lt; end<span class="Delimiter">();</span>
<span class="CommentedCode">//?       cerr &lt;&lt; &quot;mismatch: product &quot; &lt;&lt; i &lt;&lt; '\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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;strict match: product &quot;</span> &lt;&lt; i &lt;&lt; end<span class="Delimiter">();</span>
<span class="CommentedCode">//?       cerr &lt;&lt; &quot;strict match: product &quot; &lt;&lt; i &lt;&lt; '\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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;boolean matches literal: product &quot;</span> &lt;&lt; i &lt;&lt; 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">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;non-strict match: product &quot;</span> &lt;&lt; i &lt;&lt; end<span class="Delimiter">();</span>
<span class="CommentedCode">//?       cerr &lt;&lt; &quot;non-strict match: product &quot; &lt;&lt; i &lt;&lt; '\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/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>
<span class="Special">% Hide_warnings = true;</span>
recipe test a:number <span class="Delimiter">-&gt;</span> z:number [
  z<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>
]
recipe test [
  reply <span class="Constant">34</span>
]
<span class="traceContains">+warn: redefining recipe test</span>

<span class="Delimiter">:(scenario static_dispatch_disabled_on_headerless_definition_2)</span>
<span class="Special">% Hide_warnings = true;</span>
recipe test [
  reply <span class="Constant">34</span>
]
recipe test a:number <span class="Delimiter">-&gt;</span> z:number [
  z<span class="Special"> &lt;- </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"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </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"> &lt;- </span>copy <span class="Constant">0</span>/<span class="Constant">false</span>
  <span class="Constant">5</span>:boolean<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>/<span class="Constant">false</span>
  <span class="Constant">6</span>:boolean<span class="Special"> &lt;- </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">-&gt;</span> z:boolean [
  local-scope
  load-ingredients
  z<span class="Special"> &lt;- </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_works_with_dummy_results_for_containers)</span>
<span class="Special">% Hide_errors = true;</span>
recipe main [
  _<span class="Special"> &lt;- </span>test <span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">4</span>
]
recipe test a:number <span class="Delimiter">-&gt;</span> z:point [
  local-scope
  load-ingredients
  z<span class="Special"> &lt;- </span>merge a<span class="Delimiter">,</span> <span class="Constant">0</span>
]
recipe test a:number<span class="Delimiter">,</span> b:number <span class="Delimiter">-&gt;</span> z:point [
  local-scope
  load-ingredients
  z<span class="Special"> &lt;- </span>merge a<span class="Delimiter">,</span> b
]
$error: <span class="Constant">0</span>

<span class="Delimiter">:(scenario static_dispatch_works_with_compound_type_containing_container_defined_after_first_use)</span>
<span class="Special">% Hide_errors = true;</span>
recipe main [
  x:address:foo<span class="Special"> &lt;- </span>new foo:type
  test x
]
container foo [
  x:number
]
recipe test a:address:foo <span class="Delimiter">-&gt;</span> z:number [
  local-scope
  load-ingredients
  z:number<span class="Special"> &lt;- </span>get *a<span class="Delimiter">,</span> x:offset
]
$error: <span class="Constant">0</span>

<span class="Delimiter">:(scenario static_dispatch_works_with_compound_type_containing_container_defined_after_second_use)</span>
<span class="Special">% Hide_errors = true;</span>
recipe main [
  x:address:foo<span class="Special"> &lt;- </span>new foo:type
  test x
]
recipe test a:address:foo <span class="Delimiter">-&gt;</span> z:number [
  local-scope
  load-ingredients
  z:number<span class="Special"> &lt;- </span>get *a<span class="Delimiter">,</span> x:offset
]
container foo [
  x:number
]
$error: <span class="Constant">0</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"> &lt;- </span>foo <span class="Constant">0</span>
]
recipe foo x:address:number <span class="Delimiter">-&gt;</span> y:number [
  reply <span class="Constant">34</span>
]
recipe foo x:number <span class="Delimiter">-&gt;</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"> &lt;- </span>copy <span class="Constant">10</span>/newline
  <span class="Constant">1</span>:number/<span class="Special">raw &lt;- </span>foo x
]
recipe foo x:number <span class="Delimiter">-&gt;</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 &lt;- </span>foo <span class="Constant">0</span>  <span class="Comment"># valid literal for boolean</span>
]
recipe foo x:character <span class="Delimiter">-&gt;</span> y:number [
  local-scope
  load-ingredients
  reply <span class="Constant">34</span>
]
recipe foo x:boolean <span class="Delimiter">-&gt;</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 &lt;- </span>foo <span class="Constant">97</span>  <span class="Comment"># not a valid literal for boolean</span>
]
recipe foo x:character <span class="Delimiter">-&gt;</span> y:number [
  local-scope
  load-ingredients
  reply <span class="Constant">34</span>
]
recipe foo x:boolean <span class="Delimiter">-&gt;</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 &lt;- </span>foo <span class="Constant">97</span>
]
recipe foo x:character <span class="Delimiter">-&gt;</span> y:number [
  local-scope
  load-ingredients
  reply <span class="Constant">34</span>
]
recipe foo x:number <span class="Delimiter">-&gt;</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"> &lt;- </span>foo <span class="Constant">34</span>
]
recipe foo x:boolean <span class="Delimiter">-&gt;</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 -&gt; y:number)</span>
<span class="traceContains">+error:   (we're trying to call '1:number &lt;- foo 34' inside recipe main)</span>

<span class="Delimiter">:(before &quot;End next-ingredient Type Mismatch Error&quot;)</span>
raise_error &lt;&lt; <span class="Constant">&quot;   (we're inside &quot;</span> &lt;&lt; header_label<span class="Delimiter">(</span>current_call<span class="Delimiter">().</span>running_recipe<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;)</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
raise_error &lt;&lt; <span class="Constant">&quot;   (we're trying to call '&quot;</span> &lt;&lt; to_instruction<span class="Delimiter">(</span>*++Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>begin<span class="Delimiter">()).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;' inside &quot;</span> &lt;&lt; header_label<span class="Delimiter">((</span>++Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>begin<span class="Delimiter">())-&gt;</span>running_recipe<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;)</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; 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"> &lt;- </span>foo <span class="Constant">34</span>
]
recipe foo x:number <span class="Delimiter">-&gt;</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 -&gt; y:number)</span>

<span class="Delimiter">:(before &quot;End reply Type Mismatch Error&quot;)</span>
raise_error &lt;&lt; <span class="Constant">&quot;   (we just returned from &quot;</span> &lt;&lt; header_label<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>operation<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;)</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; 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&amp; caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span>
  ostringstream out<span class="Delimiter">;</span>
  out &lt;&lt; <span class="Constant">&quot;recipe &quot;</span> &lt;&lt; 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 &lt; SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span>
    out &lt;&lt; <span class="Constant">' '</span> &lt;&lt; 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 &lt;&lt; <span class="Constant">&quot; -&gt;&quot;</span><span class="Delimiter">;</span>
  for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span>
    out &lt;&lt; <span class="Constant">' '</span> &lt;&lt; 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>

<span class="Delimiter">:(scenario reload_variant_retains_other_variants)</span>
recipe main [
  <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>foo <span class="Constant">1</span>:number
]
recipe foo x:number <span class="Delimiter">-&gt;</span> y:number [
  local-scope
  load-ingredients
  reply <span class="Constant">34</span>
]
recipe foo x:address:number <span class="Delimiter">-&gt;</span> y:number [
  local-scope
  load-ingredients
  reply <span class="Constant">35</span>
]
recipe! foo x:address:number <span class="Delimiter">-&gt;</span> y:number [
  local-scope
  load-ingredients
  reply <span class="Constant">36</span>
]
<span class="traceContains">+mem: storing 34 in location 2</span>
$error: <span class="Constant">0</span>
$warn: <span class="Constant">0</span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->