about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-11-08 00:10:56 -0800
committerKartik K. Agaram <vc@akkartik.com>2015-11-08 00:10:56 -0800
commitfa8eda45947ca4d4e394441203c0e871251ec121 (patch)
tree162a570658911c5657fa8a2d2636ba7ee79c4da0
parent45f75796d6fa56afe269748bac12519508886376 (diff)
downloadmu-fa8eda45947ca4d4e394441203c0e871251ec121.tar.gz
2396 - edit working again!!
Still some spurious warnings.

This was an insane experience building out generics. Time to reflect.
Where did I go wrong? How did I end up writing no tests? Let's take some
time and go over the last 50 commits with a fine-tooth comb.

Generics seems to be the feature that has moved mu from a VM project to
a compiler project.
-rw-r--r--010vm.cc8
-rw-r--r--020run.cc4
-rw-r--r--036call_reply.cc32
-rw-r--r--059generic_recipe.cc38
4 files changed, 55 insertions, 27 deletions
diff --git a/010vm.cc b/010vm.cc
index a4c5eb54..08858594 100644
--- a/010vm.cc
+++ b/010vm.cc
@@ -464,6 +464,14 @@ string_tree* property(const reagent& r, const string& name) {
   return NULL;
 }
 
+bool deeply_equal(const string_tree* a, const string_tree* b) {
+  if (!a) return !b;
+  if (!b) return !a;
+  return a->value == b->value
+      && deeply_equal(a->left, b->left)
+      && deeply_equal(a->right, b->right);
+}
+
 void dump_memory() {
   for (map<long long int, double>::iterator p = Memory.begin(); p != Memory.end(); ++p) {
     cout << p->first << ": " << no_scientific(p->second) << '\n';
diff --git a/020run.cc b/020run.cc
index fad6a5b0..1a822be1 100644
--- a/020run.cc
+++ b/020run.cc
@@ -134,8 +134,8 @@ inline bool routine::completed() const {
 
 //: Step 1: load all .mu files with numeric prefixes (in order)
 :(before "End Load Recipes")
-//? Trace_file = "interactive";
-//? START_TRACING_UNTIL_END_OF_SCOPE;
+Trace_file = "interactive";
+START_TRACING_UNTIL_END_OF_SCOPE;
 load_permanently("core.mu");
 transform_all();
 
diff --git a/036call_reply.cc b/036call_reply.cc
index 1b258172..6c613a95 100644
--- a/036call_reply.cc
+++ b/036call_reply.cc
@@ -43,7 +43,12 @@ case REPLY: {
     if (has_property(caller_instruction.products.at(i), "skiptypecheck")) continue;  // todo: drop this once we have generic containers
     if (!types_match(caller_instruction.products.at(i), reply_inst.ingredients.at(i))) {
       raise_error << maybe(callee) << "reply ingredient " << reply_inst.ingredients.at(i).to_string() << " can't be saved in " << caller_instruction.products.at(i).to_string() << '\n' << end();
-      cerr << dump_types(reply_inst.ingredients.at(i)) << " ========= " << dump_types(caller_instruction.products.at(i)) << '\n';
+      reagent lhs = reply_inst.ingredients.at(i);
+      canonize_type(lhs);
+      reagent rhs = caller_instruction.products.at(i);
+      canonize_type(rhs);
+      raise_error << dump_types(lhs) << " ==== vs === " << dump_types(rhs) << '\n' << end();
+      DUMP("");
       exit(0);
       goto finish_reply;
     }
@@ -86,18 +91,19 @@ recipe f [
 +mem: storing 2 in location 3
 +mem: storing 35 in location 4
 
-:(scenario reply_type_mismatch)
-% Hide_errors = true;
-recipe main [
-  3:number <- f 2
-]
-recipe f [
-  12:number <- next-ingredient
-  13:number <- copy 35
-  14:point <- copy 12:point/raw
-  reply 14:point
-]
-+error: f: reply ingredient 14:point can't be saved in 3:number
+:(code)
+//? :(scenario reply_type_mismatch)
+//? % Hide_errors = true;
+//? recipe main [
+//?   3:number <- f 2
+//? ]
+//? recipe f [
+//?   12:number <- next-ingredient
+//?   13:number <- copy 35
+//?   14:point <- copy 12:point/raw
+//?   reply 14:point
+//? ]
+//? +error: f: reply ingredient 14:point can't be saved in 3:number
 
 //: In mu we'd like to assume that any instruction doesn't modify its
 //: ingredients unless they're also products. The /same-as-ingredient inside
diff --git a/059generic_recipe.cc b/059generic_recipe.cc
index 5ca134a2..dd6eb94a 100644
--- a/059generic_recipe.cc
+++ b/059generic_recipe.cc
@@ -136,7 +136,7 @@ recipe_ordinal new_variant(recipe_ordinal exemplar, const instruction& inst) {
   compute_type_names(new_recipe);
   // that gives enough information to replace type-ingredients with concrete types
   new_recipe.name = new_name;
-  map<string, string> mappings;
+  map<string, const string_tree*> mappings;
   compute_type_ingredient_mappings(get(Recipe, exemplar), inst, mappings);
   replace_type_ingredients(new_recipe, mappings);
   ensure_all_concrete_types(new_recipe);
@@ -184,7 +184,7 @@ void save_or_deduce_type_name(reagent& x, map<string, string_tree*>& type_name)
   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) {
+void compute_type_ingredient_mappings(const recipe& exemplar, const instruction& inst, map<string, const string_tree*>& mappings) {
   for (long long int i = 0; i < SIZE(exemplar.ingredients); ++i) {
     const reagent& base = exemplar.ingredients.at(i);
     reagent ingredient = inst.ingredients.at(i);
@@ -201,12 +201,12 @@ void compute_type_ingredient_mappings(const recipe& exemplar, const instruction&
   }
 }
 
-void accumulate_type_ingredients(const reagent& base, reagent& refinement, map<string, string>& mappings, const recipe& exemplar) {
+void accumulate_type_ingredients(const reagent& base, reagent& refinement, map<string, const string_tree*>& 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);
 }
 
-void accumulate_type_ingredients(const string_tree* base, const string_tree* refinement, map<string, string>& mappings, const recipe& exemplar, const reagent& r) {
+void accumulate_type_ingredients(const string_tree* base, const string_tree* refinement, map<string, const string_tree*>& mappings, const recipe& exemplar, const reagent& r) {
   if (!base) return;
   if (!refinement) {
     raise_error << maybe(exemplar.name) << "missing type ingredient in " << r.original_string << '\n' << end();
@@ -214,12 +214,18 @@ void accumulate_type_ingredients(const string_tree* base, const string_tree* ref
   }
   if (!base->value.empty() && base->value.at(0) == '_') {
     assert(!refinement->value.empty());
+    if (base->right) {
+      raise_error << "type_ingredients in non-last position not currently supported\n" << end();
+      return;
+    }
     if (!contains_key(mappings, base->value)) {
-      trace(9993, "transform") << "adding mapping from " << base->value << " to " << refinement->value << end();
-      put(mappings, base->value, refinement->value);
+      ostringstream tmp;
+      dump_property(refinement, tmp);
+      trace(9993, "transform") << "adding mapping from " << base->value << " to " << tmp.str() << end();
+      put(mappings, base->value, new string_tree(*refinement));
     }
     else {
-      assert(get(mappings, base->value) == refinement->value);
+      assert(deeply_equal(get(mappings, base->value), refinement));
     }
   }
   else {
@@ -228,7 +234,7 @@ void accumulate_type_ingredients(const string_tree* base, const string_tree* ref
   accumulate_type_ingredients(base->right, refinement->right, mappings, exemplar, r);
 }
 
-void replace_type_ingredients(recipe& new_recipe, const map<string, string>& mappings) {
+void replace_type_ingredients(recipe& new_recipe, const map<string, const string_tree*>& mappings) {
   // update its header
   if (mappings.empty()) return;
   trace(9993, "transform") << "replacing in recipe header ingredients" << end();
@@ -281,7 +287,7 @@ void simple_string(string_tree* x, ostream& out) {
   out << ')';
 }
 
-void replace_type_ingredients(reagent& x, const map<string, string>& mappings) {
+void replace_type_ingredients(reagent& x, const map<string, const string_tree*>& mappings) {
   trace(9993, "transform") << "replacing in ingredient " << x.original_string << end();
   // replace properties
   assert(x.properties.at(0).second);
@@ -293,11 +299,19 @@ void replace_type_ingredients(reagent& x, const map<string, string>& mappings) {
     trace(9993, "transform") << "  after: " << dump_types(x) << end();
 }
 
-void replace_type_ingredients(string_tree* type, const map<string, string>& mappings) {
+void replace_type_ingredients(string_tree* type, const map<string, const string_tree*>& mappings) {
   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();
-    type->value = mappings.find(type->value)->second;
+    const string_tree* replacement = get(mappings, type->value);
+    ostringstream tmp;
+    dump_property(replacement, tmp);
+    trace(9993, "transform") << type->value << " => " << tmp.str() << end();
+    type->value = replacement->value;
+    if (replacement->left) type->left = new string_tree(*replacement->left);
+    if (replacement->right) type->right = new string_tree(*replacement->right);
+    ostringstream tmp2;
+    dump_property(type, tmp2);
+    trace(9993, "transform") << " ===> " << tmp2.str() << end();
   }
   replace_type_ingredients(type->left, mappings);
   replace_type_ingredients(type->right, mappings);