about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-11-15 12:35:59 -0800
committerKartik K. Agaram <vc@akkartik.com>2015-11-15 12:35:59 -0800
commitc55e49b6374656099566fd22f39328c2da75b044 (patch)
treec5c248b9baff05b5910824884576cccbabf63e98
parent360d45e68edf92e85e3ae7cb198be88182374331 (diff)
downloadmu-c55e49b6374656099566fd22f39328c2da75b044.tar.gz
2445 - dispatch between shape-shifting variants
Starting to leave debug prints around once again, just in case one of
them is worth promoting to the trace..
-rw-r--r--010vm.cc4
-rw-r--r--029tools.cc1
-rw-r--r--057static_dispatch.cc10
-rw-r--r--058shape_shifting_container.cc2
-rw-r--r--059shape_shifting_recipe.cc108
5 files changed, 115 insertions, 10 deletions
diff --git a/010vm.cc b/010vm.cc
index 312aa3fc..016d3ad6 100644
--- a/010vm.cc
+++ b/010vm.cc
@@ -433,11 +433,11 @@ string instruction::to_string() const {
 
 string debug_string(const recipe& x) {
   ostringstream out;
-  out << "recipe " << x.name << '\n';
+  out << "- recipe " << x.name << '\n';
   // Begin debug_string(recipe x)
   for (long long int index = 0; index < SIZE(x.steps); ++index) {
     const instruction& inst = x.steps.at(index);
-    out << "  inst: " << inst.to_string() << '\n';
+    out << "inst: " << inst.to_string() << '\n';
     out << "  ingredients\n";
     for (long long int i = 0; i < SIZE(inst.ingredients); ++i)
       out << "    " << debug_string(inst.ingredients.at(i)) << '\n';
diff --git a/029tools.cc b/029tools.cc
index 92f551b3..0e14b1d4 100644
--- a/029tools.cc
+++ b/029tools.cc
@@ -251,6 +251,7 @@ case _PRINT: {
       }
     }
   }
+  cout.flush();
   break;
 }
 
diff --git a/057static_dispatch.cc b/057static_dispatch.cc
index 54da5354..6ca6ca7c 100644
--- a/057static_dispatch.cc
+++ b/057static_dispatch.cc
@@ -32,6 +32,7 @@ for (map<string, vector<recipe_ordinal> >::iterator p = Recipe_variants.begin();
 :(before "End Load Recipe Header(result)")
 if (contains_key(Recipe_ordinal, result.name)) {
   const recipe_ordinal r = get(Recipe_ordinal, result.name);
+//?   if (variant_already_exists(result)) cerr << "AAAAAAAAAAAAAAAAAA variant already exists " << result.name << '\n';
   if ((!contains_key(Recipe, r) || get(Recipe, r).has_header)
       && !variant_already_exists(result)) {
     string new_name = next_unused_recipe_name(result.name);
@@ -62,12 +63,16 @@ bool all_reagents_match(const recipe& r1, const recipe& r2) {
   if (SIZE(r1.ingredients) != SIZE(r2.ingredients)) return false;
   if (SIZE(r1.products) != SIZE(r2.products)) return false;
   for (long long int i = 0; i < SIZE(r1.ingredients); ++i) {
-    if (!exact_match(r1.ingredients.at(i).type, r2.ingredients.at(i).type))
+    if (!deeply_equal_types(r1.ingredients.at(i).properties.at(0).second,
+                            r2.ingredients.at(i).properties.at(0).second)) {
       return false;
+    }
   }
   for (long long int i = 0; i < SIZE(r1.products); ++i) {
-    if (!exact_match(r1.products.at(i).type, r2.products.at(i).type))
+    if (!deeply_equal_types(r1.products.at(i).properties.at(0).second,
+                            r2.products.at(i).properties.at(0).second)) {
       return false;
+    }
   }
   return true;
 }
@@ -119,6 +124,7 @@ void resolve_ambiguous_calls(recipe_ordinal r) {
     assert(!get(Recipe_variants, inst.name).empty());
     replace_best_variant(inst, caller_recipe);
   }
+//?   if (caller_recipe.name == "main") cerr << "=============== " << debug_string(caller_recipe) << '\n';
 }
 
 void replace_best_variant(instruction& inst, const recipe& caller_recipe) {
diff --git a/058shape_shifting_container.cc b/058shape_shifting_container.cc
index 1f0acab9..02042ac2 100644
--- a/058shape_shifting_container.cc
+++ b/058shape_shifting_container.cc
@@ -97,7 +97,7 @@ long long int size_of_type_ingredient(const type_tree* element_template, const t
   assert(!curr->left);  // unimplemented
   if (!contains_key(Type, curr->value)) {
     // temporarily while we're still ironing out kinks; eventually replace with a raise_error
-    DUMP("");
+//?     DUMP("");
     cerr << "missing type " << debug_string(curr) << '\n';
     exit(0);
   }
diff --git a/059shape_shifting_recipe.cc b/059shape_shifting_recipe.cc
index 4ca9779c..97914aaa 100644
--- a/059shape_shifting_recipe.cc
+++ b/059shape_shifting_recipe.cc
@@ -31,6 +31,7 @@ if (any_type_ingredient_in_header(/*recipe_ordinal*/p->first)) continue;
 :(after "Running One Instruction")
 if (Current_routine->calls.front().running_step_index == 0
     && any_type_ingredient_in_header(Current_routine->calls.front().running_recipe)) {
+//?   DUMP("");
   raise_error << "ran into unspecialized shape-shifting recipe " << current_recipe_name() << '\n' << end();
 }
 
@@ -48,24 +49,35 @@ recently_added_types.clear();
 
 :(before "End Instruction Dispatch(inst, best_score)")
 if (best_score == -1) {
+//?   if (inst.name == "push-duplex") Trace_stream = new trace_stream;
   trace(9992, "transform") << "no variant found; searching for variant with suitable type ingredients" << end();
   recipe_ordinal exemplar = pick_matching_shape_shifting_variant(variants, inst, best_score);
   if (exemplar) {
     trace(9992, "transform") << "found variant to specialize: " << exemplar << ' ' << get(Recipe, exemplar).name << end();
     variants.push_back(new_variant(exemplar, inst, caller_recipe));
+//?     cerr << "-- replacing " << inst.name << " with " << get(Recipe, variants.back()).name << '\n' << debug_string(get(Recipe, variants.back()));
     inst.name = get(Recipe, variants.back()).name;
     trace(9992, "transform") << "new specialization: " << inst.name << end();
   }
+//?   if (inst.name == "push-duplex") {
+//?     cerr << "======== {\n";
+//?     cerr << inst.to_string() << '\n';
+//?     DUMP("");
+//?     cerr << "======== }\n";
+//?   }
 }
 
 :(code)
 recipe_ordinal pick_matching_shape_shifting_variant(vector<recipe_ordinal>& variants, const instruction& inst, long long int& best_score) {
+//?   cerr << "---- " << inst.name << ": " << non_ghost_size(variants) << '\n';
   recipe_ordinal result = 0;
   for (long long int i = 0; i < SIZE(variants); ++i) {
     if (variants.at(i) == -1) continue;  // ghost from a previous test
+//?     cerr << "-- variant " << i << "\n" << debug_string(get(Recipe, variants.at(i)));
     trace(9992, "transform") << "checking shape-shifting variant " << i << end();
     long long int current_score = shape_shifting_variant_score(inst, variants.at(i));
     trace(9992, "transform") << "final score: " << current_score << end();
+//?     cerr << get(Recipe, variants.at(i)).name << ": " << current_score << '\n';
     if (current_score > best_score) {
       trace(9992, "transform") << "matches" << end();
       result = variants.at(i);
@@ -76,6 +88,7 @@ recipe_ordinal pick_matching_shape_shifting_variant(vector<recipe_ordinal>& vari
 }
 
 long long int shape_shifting_variant_score(const instruction& inst, recipe_ordinal variant) {
+//?   cerr << "======== " << inst.to_string() << '\n';
   if (!any_type_ingredient_in_header(variant)) {
     trace(9993, "transform") << "no type ingredients" << end();
     return -1;
@@ -86,7 +99,7 @@ long long int shape_shifting_variant_score(const instruction& inst, recipe_ordin
     return -1;
   }
   for (long long int i = 0; i < SIZE(header_ingredients); ++i) {
-    if (!non_type_ingredients_match(header_ingredients.at(i), inst.ingredients.at(i))) {
+    if (!deeply_equal_concrete_types(header_ingredients.at(i), inst.ingredients.at(i))) {
       trace(9993, "transform") << "mismatch: ingredient " << i << end();
       return -1;
     }
@@ -97,7 +110,7 @@ long long int shape_shifting_variant_score(const instruction& inst, recipe_ordin
   }
   const vector<reagent>& header_products = get(Recipe, variant).products;
   for (long long int i = 0; i < SIZE(inst.products); ++i) {
-    if (!non_type_ingredients_match(header_products.at(i), inst.products.at(i))) {
+    if (!deeply_equal_concrete_types(header_products.at(i), inst.products.at(i))) {
       trace(9993, "transform") << "mismatch: product " << i << end();
       return -1;
     }
@@ -119,9 +132,29 @@ bool any_type_ingredient_in_header(recipe_ordinal variant) {
   return false;
 }
 
-bool non_type_ingredients_match(const reagent& lhs, const reagent& rhs) {
-  if (contains_type_ingredient_name(lhs)) return true;
-  return types_match(lhs, rhs);
+bool deeply_equal_concrete_types(reagent lhs, reagent rhs) {
+//?   cerr << debug_string(lhs) << " vs " << debug_string(rhs) << '\n';
+//?   bool result = deeply_equal_concrete_types(lhs.properties.at(0).second, rhs.properties.at(0).second, rhs);
+//?   cerr << "  => " << result << '\n';
+//?   return result;
+//?   cerr << "== " << debug_string(lhs) << " vs " << debug_string(rhs) << '\n';
+  canonize_type(lhs);
+  canonize_type(rhs);
+  return deeply_equal_concrete_types(lhs.properties.at(0).second, rhs.properties.at(0).second, rhs);
+}
+
+bool deeply_equal_concrete_types(const string_tree* lhs, const string_tree* rhs, const reagent& rhs_reagent) {
+  if (!lhs) return !rhs;
+  if (!rhs) return !lhs;
+  if (is_type_ingredient_name(lhs->value)) return true;  // type ingredient matches anything
+  if (Literal_type_names.find(lhs->value) != Literal_type_names.end())
+    return Literal_type_names.find(rhs->value) != Literal_type_names.end();
+  if (rhs->value == "literal" && lhs->value == "address")
+    return rhs_reagent.name == "0";
+//?   cerr << lhs->value << " vs " << rhs->value << '\n';
+  return lhs->value == rhs->value
+      && deeply_equal_concrete_types(lhs->left, rhs->left, rhs_reagent)
+      && deeply_equal_concrete_types(lhs->right, rhs->right, rhs_reagent);
 }
 
 bool contains_type_ingredient_name(const reagent& x) {
@@ -347,6 +380,13 @@ void ensure_all_concrete_types(/*const*/ reagent& x, const recipe& exemplar) {
   }
 }
 
+long long int non_ghost_size(vector<recipe_ordinal>& variants) {
+  long long int result = 0;
+  for (long long int i = 0; i < SIZE(variants); ++i)
+    if (variants.at(i) != -1) ++result;
+  return result;
+}
+
 :(scenario shape_shifting_recipe_2)
 recipe main [
   10:point <- merge 14, 15
@@ -551,3 +591,61 @@ recipe foo x:_elem, y:_elem [
   1:number/raw <- add x, y
 ]
 +mem: storing 7 in location 1
+
+:(scenario multiple_shape_shifting_variants)
+# try to call two different shape-shifting recipes with the same name
+recipe main [
+  e1:d1:number <- merge 3
+  e2:d2:number <- merge 4, 5
+  1:number/raw <- foo e1
+  2:number/raw <- foo e2
+]
+# the two shape-shifting definitions
+recipe foo a:d1:_elem -> b:number [
+  local-scope
+  load-ingredients
+  reply 34
+]
+recipe foo a:d2:_elem -> b:number [
+  local-scope
+  load-ingredients
+  reply 35
+]
+# the shape-shifting containers they use
+container d1:_elem [
+  x:_elem
+]
+container d2:_elem [
+  x:number
+  y:_elem
+]
++mem: storing 34 in location 1
++mem: storing 35 in location 2
+
+:(scenario multiple_shape_shifting_variants_2)
+# static dispatch between shape-shifting variants, _including pointer lookups_
+recipe main [
+  e1:d1:number <- merge 3
+  e2:address:d2:number <- new {(d2 number): type}
+  1:number/raw <- foo e1
+  2:number/raw <- foo *e2  # different from previous scenario
+]
+recipe foo a:d1:_elem -> b:number [
+  local-scope
+  load-ingredients
+  reply 34
+]
+recipe foo a:d2:_elem -> b:number [
+  local-scope
+  load-ingredients
+  reply 35
+]
+container d1:_elem [
+  x:_elem
+]
+container d2:_elem [
+  x:number
+  y:_elem
+]
++mem: storing 34 in location 1
++mem: storing 35 in location 2