about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-09-28 22:21:15 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-09-28 22:21:15 -0700
commit86a6c9cd8952b4600f648519a64a86156d1a3e10 (patch)
tree8884fbb2348535e92bc61e1aee0d01773f2b3c08
parentefb7c8d685ef8c7ec5a0e480b312003e907feaca (diff)
downloadmu-86a6c9cd8952b4600f648519a64a86156d1a3e10.tar.gz
2213 - start moving type checks out of 'run'
That way we only have to check each static instruction once, rather than
every time it runs.
-rw-r--r--020run.cc39
-rw-r--r--031address.cc5
-rw-r--r--032array.cc28
-rw-r--r--048_check_type_by_instruction.cc59
4 files changed, 88 insertions, 43 deletions
diff --git a/020run.cc b/020run.cc
index 6b28e3ff..116d44a7 100644
--- a/020run.cc
+++ b/020run.cc
@@ -83,20 +83,6 @@ void run_current_routine()
     switch (current_instruction().operation) {
       // Primitive Recipe Implementations
       case COPY: {
-        if (SIZE(current_instruction().products) != SIZE(ingredients)) {
-          raise << "ingredients and products should match in '" << current_instruction().to_string() << "'\n" << end();
-          break;
-        }
-        for (long long int i = 0; i < SIZE(ingredients); ++i) {
-          if (!is_mu_array(current_instruction().ingredients.at(i)) && is_mu_array(current_instruction().products.at(i))) {
-            raise << current_recipe_name() << ": can't copy " << current_instruction().ingredients.at(i).original_string << " to array " << current_instruction().products.at(i).original_string << "\n" << end();
-            goto finish_instruction;
-          }
-          if (is_mu_array(current_instruction().ingredients.at(i)) && !is_mu_array(current_instruction().products.at(i))) {
-            raise << current_recipe_name() << ": can't copy array " << current_instruction().ingredients.at(i).original_string << " to " << current_instruction().products.at(i).original_string << "\n" << end();
-            goto finish_instruction;
-          }
-        }
         copy(ingredients.begin(), ingredients.end(), inserter(products, products.begin()));
         break;
       }
@@ -317,10 +303,6 @@ bool is_literal(const reagent& r) {
   return SIZE(r.types) == 1 && r.types.at(0) == 0;
 }
 
-bool is_mu_array(reagent r) {
-  return !r.types.empty() && r.types.at(0) == Type_ordinal["array"];
-}
-
 :(code)
 // helper for tests
 void run(string form) {
@@ -352,27 +334,6 @@ recipe main [
 ]
 -mem: storing 34 in location 0
 
-:(scenario copy_checks_reagent_count)
-% Hide_warnings = true;
-recipe main [
-  1:number <- copy 34, 35
-]
-+warn: ingredients and products should match in '1:number <- copy 34, 35'
-
-:(scenario write_scalar_to_array_disallowed)
-% Hide_warnings = true;
-recipe main [
-  1:array:number <- copy 34
-]
-+warn: main: can't copy 34 to array 1:array:number
-
-:(scenario write_scalar_to_array_disallowed_2)
-% Hide_warnings = true;
-recipe main [
-  1:number, 2:array:number <- copy 34, 35
-]
-+warn: main: can't copy 35 to array 2:array:number
-
 //: mu is robust to various combinations of commas and spaces. You just have
 //: to put spaces around the '<-'.
 
diff --git a/031address.cc b/031address.cc
index 38a891ef..22a57189 100644
--- a/031address.cc
+++ b/031address.cc
@@ -29,9 +29,6 @@ if (x.value == 0) {
   return;
 }
 
-:(after "bool is_mu_array(reagent r)")
-r = canonize(r);
-
 //: writes to address 0 always loudly fail
 :(scenario store_to_0_warns)
 % Hide_warnings = true;
@@ -69,7 +66,7 @@ reagent lookup_memory(reagent x) {
   // populate types
   copy(++x.types.begin(), x.types.end(), inserter(result.types, result.types.begin()));
 
-  // drop-one 'lookup'
+  // drop one 'lookup'
   long long int i = 0;
   long long int len = SIZE(x.properties);
   for (i = 0; i < len; ++i) {
diff --git a/032array.cc b/032array.cc
index 1b8d5900..7ad84367 100644
--- a/032array.cc
+++ b/032array.cc
@@ -332,3 +332,31 @@ case LENGTH: {
 recipe_ordinal r = current_instruction().operation;
 if (r == CREATE_ARRAY || r == INDEX || r == INDEX_ADDRESS || r == LENGTH)
   return false;
+
+:(code)
+bool is_mu_array(reagent r) {
+  if (is_literal(r)) return false;
+  while (has_property(r, "lookup")) {
+    if (r.types.empty()) {
+      raise << "can't lookup non-address: " << r.original_string << '\n' << end();
+      return false;
+    }
+    if (r.types.at(0) != Type_ordinal["address"]) {
+      raise << "can't lookup non-address: " << r.original_string << '\n' << end();
+      return false;
+    }
+    r.types.erase(r.types.begin());
+    drop_one_lookup(r);
+  }
+  return !r.types.empty() && r.types.at(0) == Type_ordinal["array"];
+}
+
+void drop_one_lookup(reagent& r) {
+  for (vector<pair<string, vector<string> > >::iterator p = r.properties.begin(); p != r.properties.end(); ++p) {
+    if (p->first == "lookup") {
+      r.properties.erase(p);
+      return;
+    }
+  }
+  assert(false);
+}
diff --git a/048_check_type_by_instruction.cc b/048_check_type_by_instruction.cc
new file mode 100644
index 00000000..dab8916b
--- /dev/null
+++ b/048_check_type_by_instruction.cc
@@ -0,0 +1,59 @@
+
+
+:(after "int main")
+  Transform.push_back(check_types_by_instruction);
+
+:(code)
+void check_types_by_instruction(const recipe_ordinal r) {
+  map<string, vector<type_ordinal> > metadata;
+  for (long long int i = 0; i < SIZE(Recipe[r].steps); ++i) {
+    instruction& inst = Recipe[r].steps.at(i);
+    switch (inst.operation) {
+      // Primitive Recipe Type Checks
+      case COPY: {
+        if (SIZE(inst.products) != SIZE(inst.ingredients)) {
+          raise << "ingredients and products should match in '" << inst.to_string() << "'\n" << end();
+          break;
+        }
+        for (long long int i = 0; i < SIZE(inst.ingredients); ++i) {
+          if (!is_mu_array(inst.ingredients.at(i)) && is_mu_array(inst.products.at(i))) {
+            raise << Recipe[r].name << ": can't copy " << inst.ingredients.at(i).original_string << " to array " << inst.products.at(i).original_string << "\n" << end();
+            goto finish_checking_instruction;
+          }
+          if (is_mu_array(inst.ingredients.at(i)) && !is_mu_array(inst.products.at(i))) {
+            raise << Recipe[r].name << ": can't copy array " << inst.ingredients.at(i).original_string << " to " << inst.products.at(i).original_string << "\n" << end();
+            goto finish_checking_instruction;
+          }
+        }
+        break;
+      }
+      // End Primitive Recipe Type Checks
+      default: {
+        // Defined Recipe Type Checks
+        // End Defined Recipe Type Checks
+      }
+    }
+    finish_checking_instruction:;
+  }
+}
+
+:(scenario copy_checks_reagent_count)
+% Hide_warnings = true;
+recipe main [
+  1:number <- copy 34, 35
+]
++warn: ingredients and products should match in '1:number <- copy 34, 35'
+
+:(scenario write_scalar_to_array_disallowed)
+% Hide_warnings = true;
+recipe main [
+  1:array:number <- copy 34
+]
++warn: main: can't copy 34 to array 1:array:number
+
+:(scenario write_scalar_to_array_disallowed_2)
+% Hide_warnings = true;
+recipe main [
+  1:number, 2:array:number <- copy 34, 35
+]
++warn: main: can't copy 35 to array 2:array:number