about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--054static_dispatch.cc4
-rw-r--r--056shape_shifting_recipe.cc61
-rw-r--r--061text.mu6
3 files changed, 63 insertions, 8 deletions
diff --git a/054static_dispatch.cc b/054static_dispatch.cc
index 702e5331..0af3ddeb 100644
--- a/054static_dispatch.cc
+++ b/054static_dispatch.cc
@@ -184,18 +184,22 @@ string best_variant(instruction& inst, const recipe& caller_recipe) {
   vector<recipe_ordinal> candidates;
 
   // Static Dispatch Phase 1
+//?   cerr << inst.name << " phase 1\n";
   candidates = strictly_matching_variants(inst, variants);
   if (!candidates.empty()) return best_variant(inst, candidates).name;
 
   // Static Dispatch Phase 2
+//?   cerr << inst.name << " phase 2\n";
   candidates = strictly_matching_variants_except_literal_against_address_or_boolean(inst, variants);
   if (!candidates.empty()) return best_variant(inst, candidates).name;
 
+//?   cerr << inst.name << " phase 3\n";
   // Static Dispatch Phase 3
   //: (shape-shifting recipes in a later layer)
   // End Static Dispatch Phase 3
 
   // Static Dispatch Phase 4
+//?   cerr << inst.name << " phase 4\n";
   candidates = matching_variants(inst, variants);
   if (!candidates.empty()) return best_variant(inst, candidates).name;
 
diff --git a/056shape_shifting_recipe.cc b/056shape_shifting_recipe.cc
index 4ad687c5..1184a7b0 100644
--- a/056shape_shifting_recipe.cc
+++ b/056shape_shifting_recipe.cc
@@ -123,17 +123,23 @@ vector<recipe_ordinal> keep_max(const instruction&, const vector<recipe_ordinal>
 recipe_ordinal best_shape_shifting_variant(const instruction& inst, const vector<recipe_ordinal>& candidates) {
   assert(!candidates.empty());
   if (SIZE(candidates) == 1) return candidates.at(0);
+//?   cerr << "A picking shape-shifting variant:\n";
   vector<recipe_ordinal> result1 = keep_max(inst, candidates, number_of_concrete_type_names);
   assert(!result1.empty());
   if (SIZE(result1) == 1) return result1.at(0);
-  vector<recipe_ordinal> result2 = keep_max(inst, result1, shape_shifting_tiebreak_heuristic);
-  if (SIZE(result2) > 1) {
-    raise << "couldn't decide the best shape-shifting variant for instruction '" << to_original_string(inst) << "'\n";
+//?   cerr << "B picking shape-shifting variant:\n";
+  vector<recipe_ordinal> result2 = keep_max(inst, result1, arity_fit);
+  assert(!result2.empty());
+  if (SIZE(result2) == 1) return result2.at(0);
+//?   cerr << "C picking shape-shifting variant:\n";
+  vector<recipe_ordinal> result3 = keep_max(inst, result2, number_of_type_ingredients);
+  if (SIZE(result3) > 1) {
+    raise << "\nCouldn't decide the best shape-shifting variant for instruction '" << to_original_string(inst) << "'\n" << end();
     cerr << "This is a hole in Mu. Please copy the following candidates into an email to Kartik Agaram <mu@akkartik.com>\n";
     for (int i = 0;  i < SIZE(candidates);  ++i)
       cerr << "  " << header_label(get(Recipe, candidates.at(i))) << '\n';
   }
-  return result2.at(0);
+  return result3.at(0);
 }
 
 vector<recipe_ordinal> keep_max(const instruction& inst, const vector<recipe_ordinal>& in,
@@ -142,8 +148,10 @@ vector<recipe_ordinal> keep_max(const instruction& inst, const vector<recipe_ord
   vector<recipe_ordinal> out;
   out.push_back(in.at(0));
   int best_score = (*scorer)(inst, in.at(0));
+//?   cerr << best_score << " " << header_label(get(Recipe, in.at(0))) << '\n';
   for (int i = 1;  i < SIZE(in);  ++i) {
     int score = (*scorer)(inst, in.at(i));
+//?     cerr << score << " " << header_label(get(Recipe, in.at(i))) << '\n';
     if (score == best_score) {
       out.push_back(in.at(i));
     }
@@ -156,7 +164,7 @@ vector<recipe_ordinal> keep_max(const instruction& inst, const vector<recipe_ord
   return out;
 }
 
-int shape_shifting_tiebreak_heuristic(const instruction& inst, recipe_ordinal candidate) {
+int arity_fit(const instruction& inst, recipe_ordinal candidate) {
   const recipe& r = get(Recipe, candidate);
   return (SIZE(inst.products) - SIZE(r.products))
        + (SIZE(r.ingredients) - SIZE(inst.ingredients));
@@ -228,6 +236,24 @@ int number_of_concrete_type_names(const type_tree* type) {
        + number_of_concrete_type_names(type->right);
 }
 
+int number_of_type_ingredients(unused const instruction& inst, recipe_ordinal r) {
+  const recipe& caller = get(Recipe, r);
+  int result = 0;
+  for (int i = 0;  i < SIZE(caller.ingredients);  ++i)
+    result += number_of_type_ingredients(caller.ingredients.at(i).type);
+  for (int i = 0;  i < SIZE(caller.products);  ++i)
+    result += number_of_type_ingredients(caller.products.at(i).type);
+  return result;
+}
+
+int number_of_type_ingredients(const type_tree* type) {
+  if (!type) return 0;
+  if (type->atom)
+    return is_type_ingredient_name(type->name) ? 1 : 0;
+  return number_of_type_ingredients(type->left)
+       + number_of_type_ingredients(type->right);
+}
+
 recipe_ordinal new_variant(recipe_ordinal exemplar, const instruction& inst, const recipe& caller_recipe) {
   string new_name = next_unused_recipe_name(inst.name);
   assert(!contains_key(Recipe_ordinal, new_name));
@@ -1102,3 +1128,28 @@ def main [
   add 0, 0
 ]
 $error: 0
+
+:(scenario specialization_heuristic_test_1)
+# modeled on the 'buffer' container in text.mu
+container foo_buffer:_elem [
+  x:num
+]
+def main [
+  append 1:&:foo_buffer:char/raw, 2:text/raw
+]
+def append buf:&:foo_buffer:_elem, x:_elem -> buf:&:foo_buffer:_elem [
+  local-scope
+  load-ingredients
+  stash 34
+]
+def append buf:&:foo_buffer:char, x:_elem -> buf:&:foo_buffer:char [
+  local-scope
+  load-ingredients
+  stash 35
+]
+def append buf:&:foo_buffer:_elem, x:&:@:_elem -> buf:&:foo_buffer:_elem [
+  local-scope
+  load-ingredients
+  stash 36
+]
++app: 36
diff --git a/061text.mu b/061text.mu
index 9cb44c79..e5fd8cc0 100644
--- a/061text.mu
+++ b/061text.mu
@@ -220,7 +220,7 @@ def append buf:&:buffer:char, c:char -> buf:&:buffer:char [
   *buf <- put *buf, length:offset, len
 ]
 
-def append buf:&:buffer:char, t:text -> buf:&:buffer:char [
+def append buf:&:buffer:_elem, t:&:@:_elem -> buf:&:buffer:_elem [
   local-scope
   load-ingredients
   len:num <- length *t
@@ -228,8 +228,8 @@ def append buf:&:buffer:char, t:text -> buf:&:buffer:char [
   {
     done?:bool <- greater-or-equal i, len
     break-if done?
-    c:char <- index *t, i
-    buf <- append buf, c
+    x:_elem <- index *t, i
+    buf <- append buf, x
     i <- add i, 1
     loop
   }