about summary refs log tree commit diff stats
path: root/059generic_recipe.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-11-07 22:56:06 -0800
committerKartik K. Agaram <vc@akkartik.com>2015-11-07 22:56:06 -0800
commit91abd257e27bd694bfc59c4cf1439171eef10a09 (patch)
treed1d3b7d8dad4b6461d97da64c9fa1b0fc4e0b1b3 /059generic_recipe.cc
parent82c886d71c12ad902ea8b9c81c7993af7ddf2d2b (diff)
downloadmu-91abd257e27bd694bfc59c4cf1439171eef10a09.tar.gz
2393 - redo 2391
Got that idea to work with a special-case for 'new'. Requires parsing
new's first ingredient, performing the replacement, and then turning it
back into a string. I didn't want to replace NEW with ALLOCATE right
here, because then it messes with my invariant that transform should
never see a naked ALLOCATE.

Layer 11 still not working, but everything else is. Let's clean up
before we diagnose the new breakage.
Diffstat (limited to '059generic_recipe.cc')
-rw-r--r--059generic_recipe.cc178
1 files changed, 139 insertions, 39 deletions
diff --git a/059generic_recipe.cc b/059generic_recipe.cc
index 64dbf6a1..3588f183 100644
--- a/059generic_recipe.cc
+++ b/059generic_recipe.cc
@@ -20,19 +20,10 @@ recipe foo a:_t -> result:_t [
 +mem: storing 14 in location 11
 +mem: storing 15 in location 12
 
-//: Before anything else, disable all previous transforms which rely on
-//: reagent.type if a recipe contains any type ingredients.
+//: Before anything else, disable transforms for generic recipes.
 
-:(after "void check_instruction(const recipe_ordinal r)")
-  if (any_type_ingredient_in_header(r)) return;
-:(after "void check_or_set_invalid_types(const recipe_ordinal r)")
-  if (any_type_ingredient_in_header(r)) return;
-:(after "void transform_names(const recipe_ordinal r)")
-  if (any_type_ingredient_in_header(r)) return;
-:(after "void transform_new_to_allocate(const recipe_ordinal r)")
-  if (any_type_ingredient_in_header(r)) return;
-:(after "void check_header_products(const recipe_ordinal r)")
-  if (any_type_ingredient_in_header(r)) return;
+:(before "End Transform Checks")
+if (any_type_ingredient_in_header(/*recipe_ordinal*/p->first)) continue;
 
 //: We'll be creating recipes without loading them from anywhere by
 //: *specializing* existing recipes, so make sure we don't clear any of those
@@ -50,16 +41,9 @@ if (best_score == -1) {
     variants.push_back(new_variant(exemplar, inst));
     inst.name = get(Recipe, variants.back()).name;
     trace(9992, "transform") << "new specialization: " << inst.name << end();
-//?     cerr << "new specialization: " << inst.name << '\n';
   }
 }
 
-//: Don't bother resolving ambiguous calls inside generic recipes. Just do
-//: their specializations.
-
-:(after "void resolve_ambiguous_calls")
-if (any_type_ingredient_in_header(r)) return;
-
 :(code)
 recipe_ordinal pick_matching_generic_variant(vector<recipe_ordinal>& variants, const instruction& inst, long long int& best_score) {
   recipe_ordinal result = 0;
@@ -140,42 +124,95 @@ recipe_ordinal new_variant(recipe_ordinal exemplar, const instruction& inst) {
   string new_name = next_unused_recipe_name(inst.name);
   trace(9993, "transform") << "switching " << inst.name << " to " << new_name << end();
   assert(!contains_key(Recipe_ordinal, new_name));
-  recipe_ordinal result = put(Recipe_ordinal, new_name, Next_recipe_ordinal++);
+  recipe_ordinal new_recipe_ordinal = put(Recipe_ordinal, new_name, Next_recipe_ordinal++);
   // make a copy
   assert(contains_key(Recipe, exemplar));
-  assert(!contains_key(Recipe, result));
-  recently_added_recipes.push_back(result);
-  put(Recipe, result, get(Recipe, exemplar));
-  recipe& new_recipe = get(Recipe, result);
-  // update its name
+  assert(!contains_key(Recipe, new_recipe_ordinal));
+  recently_added_recipes.push_back(new_recipe_ordinal);
+  put(Recipe, new_recipe_ordinal, get(Recipe, exemplar));
+  recipe& new_recipe = get(Recipe, new_recipe_ordinal);
+  // Since the exemplar never ran any transforms, we have to redo some of the
+  // work of the check_types_by_name transform while supporting type-ingredients.
+  compute_type_names(new_recipe);
+  // that gives enough information to replace type-ingredients with concrete types
   new_recipe.name = new_name;
-  // update its contents
-  map<string, string> mappings;  // weak references
+  map<string, string> mappings;
   compute_type_ingredient_mappings(get(Recipe, exemplar), inst, mappings);
   replace_type_ingredients(new_recipe, mappings);
-  return result;
+  ensure_all_concrete_types(new_recipe);
+  // finally, perform all transforms on the new specialization
+  cerr << "contents of " << new_recipe.name << '\n';
+  for (long long int index = 0; index < SIZE(new_recipe.steps); ++index) {
+    instruction& inst = new_recipe.steps.at(index);
+    cerr << "inst: " << inst.to_string() << '\n';
+    for (long long int i = 0; i < SIZE(inst.ingredients); ++i) {
+      cerr << "  " << inst.ingredients.at(i).to_string() << " => " << dump_types(inst.ingredients.at(i)) << '\n';
+    }
+    cerr << "--\n";
+    for (long long int i = 0; i < SIZE(inst.products); ++i)
+      cerr << "  " << inst.products.at(i).to_string() << " => " << dump_types(inst.products.at(i)) << '\n';
+  }
+  for (long long int t = 0; t < SIZE(Transform); ++t) {
+    (*Transform.at(t))(new_recipe_ordinal);
+  }
+  new_recipe.transformed_until = SIZE(Transform)-1;
+  return new_recipe_ordinal;
+}
+
+void compute_type_names(recipe& variant) {
+  map<string, string_tree*> type_names;
+  for (long long int i = 0; i < SIZE(variant.ingredients); ++i) {
+    save_or_deduce_type_name(variant.ingredients.at(i), type_names);
+  }
+  for (long long int i = 0; i < SIZE(variant.products); ++i) {
+    save_or_deduce_type_name(variant.products.at(i), type_names);
+  }
+  for (long long int i = 0; i < SIZE(variant.steps); ++i) {
+    instruction& inst = variant.steps.at(i);
+    for (long long int in = 0; in < SIZE(inst.ingredients); ++in) {
+      save_or_deduce_type_name(inst.ingredients.at(in), type_names);
+    }
+    for (long long int out = 0; out < SIZE(inst.products); ++out) {
+      save_or_deduce_type_name(inst.products.at(out), type_names);
+    }
+  }
+}
+
+void save_or_deduce_type_name(reagent& x, map<string, string_tree*>& type_name) {
+  if (!x.properties.at(0).second && contains_key(type_name, x.name)) {
+    x.properties.at(0).second = new string_tree(*get(type_name, x.name));
+    return;
+  }
+  if (!x.properties.at(0).second) {
+    raise << "unknown type for " << x.original_string << '\n' << end();
+    return;
+  }
+  if (contains_key(type_name, x.name)) return;
+  if (x.properties.at(0).second->value == "offset" || x.properties.at(0).second->value == "variant") return;  // special-case for container-access instructions
+  put(type_name, x.name, x.properties.at(0).second);
+  ostringstream type_name_buf;
+  dump_property(x.properties.at(0).second, type_name_buf);
+  trace(9993, "transform") << "type of " << x.name << " is " << type_name_buf.str() << end();
 }
 
 void compute_type_ingredient_mappings(const recipe& exemplar, const instruction& inst, map<string, string>& mappings) {
-//?   cerr << "=== " << exemplar.name << " vs " << inst.to_string() << '\n';
   for (long long int i = 0; i < SIZE(exemplar.ingredients); ++i) {
+    const reagent& base = exemplar.ingredients.at(i);
     reagent ingredient = inst.ingredients.at(i);
+    assert(ingredient.properties.at(0).second);
     canonize_type(ingredient);
-    accumulate_type_ingredients(exemplar.ingredients.at(i), ingredient, mappings, exemplar);
+    accumulate_type_ingredients(base, ingredient, mappings, exemplar);
   }
   for (long long int i = 0; i < SIZE(exemplar.products); ++i) {
+    const reagent& base = exemplar.products.at(i);
     reagent product = inst.products.at(i);
+    assert(product.properties.at(0).second);
     canonize_type(product);
-    accumulate_type_ingredients(exemplar.products.at(i), product, mappings, exemplar);
+    accumulate_type_ingredients(base, product, mappings, exemplar);
   }
 }
 
-void accumulate_type_ingredients(const reagent& base, const reagent& refinement, map<string, string>& mappings, const recipe& exemplar) {
-//?   cerr << base.to_string() << " vs " << refinement.to_string() << '\n';
-  if (!refinement.properties.at(0).second) {
-    if (!Trace_stream) cerr << "Turn on START_TRACING_UNTIL_END_OF_SCOPE in 020run.cc for more details.\n";
-    DUMP("");
-  }
+void accumulate_type_ingredients(const reagent& base, reagent& refinement, map<string, string>& mappings, const recipe& exemplar) {
   assert(refinement.properties.at(0).second);
   accumulate_type_ingredients(base.properties.at(0).second, refinement.properties.at(0).second, mappings, exemplar, base);
 }
@@ -190,10 +227,10 @@ void accumulate_type_ingredients(const string_tree* base, const string_tree* ref
     assert(!refinement->value.empty());
     if (!contains_key(mappings, base->value)) {
       trace(9993, "transform") << "adding mapping from " << base->value << " to " << refinement->value << end();
+      cerr << "adding mapping from " << base->value << " to " << refinement->value << '\n';
       put(mappings, base->value, refinement->value);
     }
     else {
-//?       cerr << base->value << ": " << get(mappings, base->value) << " => " << refinement->value << '\n';
       assert(get(mappings, base->value) == refinement->value);
     }
   }
@@ -224,13 +261,46 @@ void replace_type_ingredients(recipe& new_recipe, const map<string, string>& map
     for (long long int j = 0; j < SIZE(inst.products); ++j) {
       replace_type_ingredients(inst.products.at(j), mappings);
     }
+    // special-case for new: replace type ingredient in first ingredient *value*
+    if (inst.name == "new" && inst.ingredients.at(0).name.at(0) != '[') {
+      cerr << "about to translate new ingredient: " << inst.ingredients.at(0).name << '\n';
+      string_tree* type_name = parse_string_tree(inst.ingredients.at(0).name);
+      dump_property(type_name, cerr); cerr << '\n';
+      replace_type_ingredients(type_name, mappings);
+      cerr << "=> "; dump_property(type_name, cerr); cerr << '\n';
+      inst.ingredients.at(0).name = simple_string(type_name);
+      delete type_name;
+    }
+  }
+}
+
+string simple_string(string_tree* x) {
+  ostringstream out;
+  simple_string(x, out);
+  cerr << "translated new ingredient: " << out.str() << '\n';
+  return out.str();
+}
+
+void simple_string(string_tree* x, ostream& out) {
+  if (!x->left && !x->right) {
+    out << x->value;
+    return;
+  }
+  out << '(';
+  for (string_tree* curr = x; curr; curr = curr->right) {
+    if (curr != x) out << ' ';
+    if (curr->left)
+      simple_string(curr->left, out);
+    else
+      out << curr->value;
   }
+  out << ')';
 }
 
 void replace_type_ingredients(reagent& x, const map<string, string>& mappings) {
-  if (!x.type) return;
   trace(9993, "transform") << "replacing in ingredient " << x.original_string << end();
   // replace properties
+  assert(x.properties.at(0).second);
   replace_type_ingredients(x.properties.at(0).second, mappings);
   // refresh types from properties
   delete x.type;
@@ -243,12 +313,42 @@ void replace_type_ingredients(string_tree* type, const map<string, string>& mapp
   if (!type) return;
   if (is_type_ingredient_name(type->value) && contains_key(mappings, type->value)) {
     trace(9993, "transform") << type->value << " => " << mappings.find(type->value)->second << end();
+    cerr << type->value << " => " << mappings.find(type->value)->second << '\n';
     type->value = mappings.find(type->value)->second;
   }
   replace_type_ingredients(type->left, mappings);
   replace_type_ingredients(type->right, mappings);
 }
 
+void ensure_all_concrete_types(const recipe& new_recipe) {
+  for (long long int i = 0; i < SIZE(new_recipe.ingredients); ++i) {
+    ensure_all_concrete_types(new_recipe.ingredients.at(i).type);
+  }
+  for (long long int i = 0; i < SIZE(new_recipe.products); ++i) {
+    ensure_all_concrete_types(new_recipe.products.at(i).type);
+  }
+  for (long long int i = 0; i < SIZE(new_recipe.steps); ++i) {
+    const instruction& inst = new_recipe.steps.at(i);
+    for (long long int j = 0; j < SIZE(inst.ingredients); ++j) {
+      ensure_all_concrete_types(inst.ingredients.at(j).type);
+    }
+    for (long long int j = 0; j < SIZE(inst.products); ++j) {
+      ensure_all_concrete_types(inst.products.at(j).type);
+    }
+  }
+}
+
+void ensure_all_concrete_types(const type_tree* x) {
+  if (!x) {
+    raise << "AAA null type\n" << end();
+    return;
+  }
+  if (x->value == -1) {
+    raise << "AAA unknown type\n" << end();
+    return;
+  }
+}
+
 :(scenario generic_recipe_2)
 recipe main [
   10:point <- merge 14, 15