about summary refs log tree commit diff stats
path: root/020_check_type_by_instruction.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-09-28 23:36:39 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-09-28 23:36:39 -0700
commitbb58e1797e8a813891d2ba8ceabcfb518c6f8050 (patch)
tree38ac76c87f12339766189621db31ec01017d9539 /020_check_type_by_instruction.cc
parent86a6c9cd8952b4600f648519a64a86156d1a3e10 (diff)
downloadmu-bb58e1797e8a813891d2ba8ceabcfb518c6f8050.tar.gz
2214
Diffstat (limited to '020_check_type_by_instruction.cc')
-rw-r--r--020_check_type_by_instruction.cc97
1 files changed, 97 insertions, 0 deletions
diff --git a/020_check_type_by_instruction.cc b/020_check_type_by_instruction.cc
new file mode 100644
index 00000000..d1eb9694
--- /dev/null
+++ b/020_check_type_by_instruction.cc
@@ -0,0 +1,97 @@
+
+
+:(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
+
+:(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);
+}
+
+bool is_literal(const reagent& r) {
+  return SIZE(r.types) == 1 && r.types.at(0) == 0;
+}
+
+// helper for tests
+void run(string form) {
+  vector<recipe_ordinal> tmp = load(form);
+  transform_all();
+}