about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--012transform.cc6
-rw-r--r--013update_operation.cc6
-rw-r--r--043space.cc15
-rw-r--r--047check_type_by_name.cc48
-rw-r--r--060immutable.cc17
5 files changed, 53 insertions, 39 deletions
diff --git a/012transform.cc b/012transform.cc
index bbefe0f7..f1243648 100644
--- a/012transform.cc
+++ b/012transform.cc
@@ -79,3 +79,9 @@ void populate_value(reagent& r) {
   if (!is_integer(r.name)) return;
   r.set_value(to_integer(r.name));
 }
+
+// helper for tests -- temporarily suppress run
+void transform(string form) {
+  load(form);
+  transform_all();
+}
diff --git a/013update_operation.cc b/013update_operation.cc
index 0b0dee31..d27b018b 100644
--- a/013update_operation.cc
+++ b/013update_operation.cc
@@ -25,9 +25,3 @@ void update_instruction_operations(recipe_ordinal r) {
 string maybe(string s) {
   return s + ": ";
 }
-
-// temporarily suppress run
-void transform(string form) {
-  load(form);
-  transform_all();
-}
diff --git a/043space.cc b/043space.cc
index 9ca747b7..31a4173d 100644
--- a/043space.cc
+++ b/043space.cc
@@ -285,3 +285,18 @@ bool contains_non_special_name(const recipe_ordinal r) {
   }
   return false;
 }
+
+// reagent comparison -- only between reagents in a single recipe
+bool operator==(const reagent& a, const reagent& b) {
+  if (a.name != b.name) return false;
+  if (property(a, "space") != property(b, "space")) return false;
+  return true;
+}
+
+bool operator<(const reagent& a, const reagent& b) {
+  long long int aspace = 0, bspace = 0;
+  if (has_property(a, "space")) aspace = to_integer(property(a, "space")->value);
+  if (has_property(b, "space")) bspace = to_integer(property(b, "space")->value);
+  if (aspace != bspace) return aspace < bspace;
+  return a.name < b.name;
+}
diff --git a/047check_type_by_name.cc b/047check_type_by_name.cc
index 1cb6e032..043d8089 100644
--- a/047check_type_by_name.cc
+++ b/047check_type_by_name.cc
@@ -20,45 +20,46 @@ Transform.push_back(check_or_set_types_by_name);  // idempotent
 :(code)
 void check_or_set_types_by_name(const recipe_ordinal r) {
   trace(9991, "transform") << "--- deduce types for recipe " << get(Recipe, r).name << end();
-  map<string, type_tree*> type;
-  for (long long int i = 0; i < SIZE(get(Recipe, r).steps); ++i) {
-    instruction& inst = get(Recipe, r).steps.at(i);
+  recipe& caller = get(Recipe, r);
+  set<reagent> known;
+  for (long long int i = 0; i < SIZE(caller.steps); ++i) {
+    instruction& inst = caller.steps.at(i);
     for (long long int in = 0; in < SIZE(inst.ingredients); ++in) {
-      deduce_missing_type(type, inst.ingredients.at(in));
-      check_type(type, inst.ingredients.at(in), r);
+      deduce_missing_type(known, inst.ingredients.at(in));
+      check_type(known, inst.ingredients.at(in), r);
     }
     for (long long int out = 0; out < SIZE(inst.products); ++out) {
-      deduce_missing_type(type, inst.products.at(out));
-      check_type(type, inst.products.at(out), r);
+      deduce_missing_type(known, inst.products.at(out));
+      check_type(known, inst.products.at(out), r);
     }
   }
 }
 
-void deduce_missing_type(map<string, type_tree*>& type, reagent& x) {
+void deduce_missing_type(set<reagent>& known, reagent& x) {
   if (x.type) return;
-  if (!contains_key(type, x.name)) return;
-  x.type = new type_tree(*get(type, x.name));
+  if (known.find(x) == known.end()) return;
+  x.type = new type_tree(*known.find(x)->type);
   trace(9992, "transform") << x.name << " <= " << names_to_string(x.type) << end();
 }
 
-void check_type(map<string, type_tree*>& type, const reagent& x, const recipe_ordinal r) {
+void check_type(set<reagent>& known, const reagent& x, const recipe_ordinal r) {
   if (is_literal(x)) return;
   if (is_integer(x.name)) return;  // if you use raw locations you're probably doing something unsafe
   if (!x.type) return;  // might get filled in by other logic later
-  if (!contains_key(type, x.name)) {
+  if (known.find(x) == known.end()) {
     trace(9992, "transform") << x.name << " => " << names_to_string(x.type) << end();
-    put(type, x.name, x.type);
+    known.insert(x);
   }
-  if (!types_strictly_match(get(type, x.name), x.type)) {
+  if (!types_strictly_match(known.find(x)->type, x.type)) {
     raise << maybe(get(Recipe, r).name) << x.name << " used with multiple types\n" << end();
     return;
   }
-  if (get(type, x.name)->name == "array") {
-    if (!get(type, x.name)->right) {
+  if (x.type->name == "array") {
+    if (!x.type->right) {
       raise << maybe(get(Recipe, r).name) << x.name << " can't be just an array. What is it an array of?\n" << end();
       return;
     }
-    if (!get(type, x.name)->right->right) {
+    if (!x.type->right->right) {
       raise << get(Recipe, r).name << " can't determine the size of array variable " << x.name << ". Either allocate it separately and make the type of " << x.name << " address:shared:..., or specify the length of the array in the type of " << x.name << ".\n" << end();
       return;
     }
@@ -106,3 +107,16 @@ recipe main [
   x:array:number <- merge 2, 12, 13
 ]
 +error: main can't determine the size of array variable x. Either allocate it separately and make the type of x address:shared:..., or specify the length of the array in the type of x.
+
+:(scenarios transform)
+:(scenario transform_checks_types_of_identical_reagents_in_multiple_spaces)
+recipe foo [  # dummy
+]
+recipe main [
+  local-scope
+  0:address:shared:array:location/names:foo <- copy 0  # specify surrounding space
+  x:boolean <- copy 1/true
+  x:number/space:1 <- copy 34
+  x/space:1 <- copy 35
+]
+$error: 0
diff --git a/060immutable.cc b/060immutable.cc
index d1b133c4..3017a6d0 100644
--- a/060immutable.cc
+++ b/060immutable.cc
@@ -251,7 +251,7 @@ recipe run-closure x:address:shared:number, s:address:shared:array:location [
   local-scope
   load-ingredients
   0:address:shared:array:location/names:new-closure <- copy s
-  *x/space:1 <- copy 34
+  *x:address:number/space:1 <- copy 34
 ]
 $error: 0
 
@@ -431,21 +431,6 @@ set<long long int> ingredient_indices(const instruction& inst, const set<reagent
   return result;
 }
 
-// reagent comparison just for this layer; assumes reagents are in the same recipe
-bool operator==(const reagent& a, const reagent& b) {
-  if (a.name != b.name) return false;
-  if (property(a, "space") != property(b, "space")) return false;
-  return true;
-}
-
-bool operator<(const reagent& a, const reagent& b) {
-  long long int aspace = 0, bspace = 0;
-  if (has_property(a, "space")) aspace = to_integer(property(a, "space")->value);
-  if (has_property(b, "space")) bspace = to_integer(property(b, "space")->value);
-  if (aspace != bspace) return aspace < bspace;
-  return a.name < b.name;
-}
-
 //: Sometimes you want to pass in two addresses, one pointing inside the
 //: other. For example, you want to delete a node from a linked list. You
 //: can't pass both pointers back out, because if a caller tries to make both