about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-11-08 21:29:56 -0800
committerKartik K. Agaram <vc@akkartik.com>2015-11-08 21:29:56 -0800
commitb766f5f8747166b688413d15375880be510d8af6 (patch)
tree7d97f184e3f50fe5147e1ba71fc433dc215e4a59
parent92e3f56ef967185f19522e698872ff61ef4ef284 (diff)
downloadmu-b766f5f8747166b688413d15375880be510d8af6.tar.gz
2404 - ah, finally a useful assertion
And it caught a bug: I mean to always update type names and types in
sync.

The last month or so I've been getting reluctantly but inexorably
converted to the need and value of a type system. First I thought I just
need a minimal but rigorous type system to avoid memory corruption and
security issues. Now I think I also want it to be expressive enough to
be able to express what data different phases in a compiler read and
write, and to be able to designate specific fields as 'fully computed'
so that we can statically check that phases wait until their data is
available.

The phase-ordering problem in a compiler is perhaps the canary in the
coal-mine for a more general problem: even small changes can
dramatically explode the state space if they violate assumptions
previously held about the domain. My understanding of when type pointers
are null and not null is immeasurably more nuanced today than it was a
week ago, but I didn't need the nuance until I introduced generic
functions. That initial draft of a hundred lines bumped me up to a much
larger state space. How to make it more obvious when something happens
that is akin to discovering a new continent, or finding oneself
teleported to Jupiter?

Assumptions can be implicit or explicit. Perhaps a delete of an
assertion should be estimated at 1000 LoC of complexity?
-rw-r--r--056recipe_header.cc23
-rw-r--r--098check_type_pointers.cc34
-rw-r--r--edit/010-warnings.mu3
3 files changed, 50 insertions, 10 deletions
diff --git a/056recipe_header.cc b/056recipe_header.cc
index 6c3f3ce8..a6ffa629 100644
--- a/056recipe_header.cc
+++ b/056recipe_header.cc
@@ -148,13 +148,16 @@ void deduce_types_from_header(const recipe_ordinal r) {
   if (rr.products.empty()) return;
   trace(9991, "transform") << "--- deduce types from header for " << rr.name << end();
 //?   cerr << "--- deduce types from header for " << rr.name << '\n';
-  map<string, const type_tree*> header;
+  map<string, const type_tree*> header_type;
+  map<string, const string_tree*> header_type_name;
   for (long long int i = 0; i < SIZE(rr.ingredients); ++i) {
-    header[rr.ingredients.at(i).name] = rr.ingredients.at(i).type;
+    put(header_type, rr.ingredients.at(i).name, rr.ingredients.at(i).type);
+    put(header_type_name, rr.ingredients.at(i).name, rr.ingredients.at(i).properties.at(0).second);
     trace(9993, "transform") << "type of " << rr.ingredients.at(i).name << " is " << debug_string(rr.ingredients.at(i).type) << end();
   }
   for (long long int i = 0; i < SIZE(rr.products); ++i) {
-    header[rr.products.at(i).name] = rr.products.at(i).type;
+    put(header_type, rr.products.at(i).name, rr.products.at(i).type);
+    put(header_type_name, rr.products.at(i).name, rr.products.at(i).properties.at(0).second);
     trace(9993, "transform") << "type of " << rr.products.at(i).name << " is " << debug_string(rr.products.at(i).type) << end();
   }
   for (long long int i = 0; i < SIZE(rr.steps); ++i) {
@@ -162,21 +165,27 @@ void deduce_types_from_header(const recipe_ordinal r) {
     trace(9992, "transform") << "instruction: " << inst.to_string() << end();
     for (long long int i = 0; i < SIZE(inst.ingredients); ++i) {
       if (inst.ingredients.at(i).type) continue;
-      if (header.find(inst.ingredients.at(i).name) == header.end()) {
+      if (header_type.find(inst.ingredients.at(i).name) == header_type.end()) {
         raise << maybe(rr.name) << "unknown variable " << inst.ingredients.at(i).name << " in '" << inst.to_string() << "'\n" << end();
         continue;
       }
-      inst.ingredients.at(i).type = new type_tree(*header[inst.ingredients.at(i).name]);
+      if (!inst.ingredients.at(i).type)
+        inst.ingredients.at(i).type = new type_tree(*get(header_type, inst.ingredients.at(i).name));
+      if (!inst.ingredients.at(i).properties.at(0).second)
+        inst.ingredients.at(i).properties.at(0).second = new string_tree(*get(header_type_name, inst.ingredients.at(i).name));
       trace(9993, "transform") << "type of " << inst.ingredients.at(i).name << " is " << debug_string(inst.ingredients.at(i).type) << end();
     }
     for (long long int i = 0; i < SIZE(inst.products); ++i) {
       trace(9993, "transform") << "  product: " << debug_string(inst.products.at(i)) << end();
       if (inst.products.at(i).type) continue;
-      if (header.find(inst.products.at(i).name) == header.end()) {
+      if (header_type.find(inst.products.at(i).name) == header_type.end()) {
         raise << maybe(rr.name) << "unknown variable " << inst.products.at(i).name << " in '" << inst.to_string() << "'\n" << end();
         continue;
       }
-      inst.products.at(i).type = new type_tree(*header[inst.products.at(i).name]);
+      if (!inst.products.at(i).type)
+        inst.products.at(i).type = new type_tree(*get(header_type, inst.products.at(i).name));
+      if (!inst.products.at(i).properties.at(0).second)
+        inst.products.at(i).properties.at(0).second = new string_tree(*get(header_type_name, inst.products.at(i).name));
       trace(9993, "transform") << "type of " << inst.products.at(i).name << " is " << debug_string(inst.products.at(i).type) << end();
     }
   }
diff --git a/098check_type_pointers.cc b/098check_type_pointers.cc
new file mode 100644
index 00000000..f052b1d7
--- /dev/null
+++ b/098check_type_pointers.cc
@@ -0,0 +1,34 @@
+:(before "End Transform All")
+check_type_pointers();
+
+:(code)
+void check_type_pointers() {
+  for (map<recipe_ordinal, recipe>::iterator p = Recipe.begin(); p != Recipe.end(); ++p) {
+    if (any_type_ingredient_in_header(p->first)) continue;
+    const recipe& r = p->second;
+    trace(9991, "transform") << "--- checking type and type_name pointers for recipe " << r.name << end();
+    for (long long int i = 0; i < SIZE(r.steps); ++i) {
+      const instruction& inst = r.steps.at(i);
+      for (long long int j = 0; j < SIZE(inst.ingredients); ++j) {
+        if (!inst.ingredients.at(j).type) {
+          raise_error << maybe(r.name) << " '" << inst.to_string() << "' -- " << inst.ingredients.at(j).to_string() << " has no type\n" << end();
+          return;
+        }
+        if (!inst.ingredients.at(j).properties.at(0).second) {
+          raise_error << maybe(r.name) << " '" << inst.to_string() << "' -- " << inst.ingredients.at(j).to_string() << " has no type name\n" << end();
+          return;
+        }
+      }
+      for (long long int j = 0; j < SIZE(inst.products); ++j) {
+        if (!inst.products.at(j).type) {
+          raise_error << maybe(r.name) << " '" << inst.to_string() << "' -- " << inst.products.at(j).to_string() << " has no type\n" << end();
+          return;
+        }
+        if (!inst.products.at(j).properties.at(0).second) {
+          raise_error << maybe(r.name) << " '" << inst.to_string() << "' -- " << inst.products.at(j).to_string() << " has no type name\n" << end();
+          return;
+        }
+      }
+    }
+  }
+}
diff --git a/edit/010-warnings.mu b/edit/010-warnings.mu
index 59e328c1..6e5eeace 100644
--- a/edit/010-warnings.mu
+++ b/edit/010-warnings.mu
@@ -137,9 +137,6 @@ recipe foo [
     .  x <- copy 0                                     ┊                                                 .
     .]                                                 ┊                                                 .
     .foo: missing type for x in 'x <- copy 0'          ┊                                                 .
-    .foo: can't copy 0 to x; types don't match         ┊                                                 .
-    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                                                 .
-    .                                                  ┊                                                 .
   ]
 ]