diff options
-rw-r--r-- | 012transform.cc | 6 | ||||
-rw-r--r-- | 013update_operation.cc | 6 | ||||
-rw-r--r-- | 043space.cc | 15 | ||||
-rw-r--r-- | 047check_type_by_name.cc | 48 | ||||
-rw-r--r-- | 060immutable.cc | 17 |
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 |