From 5fe060d582d4a82444243a28b18085c971a85628 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Fri, 27 Jul 2018 17:07:52 -0700 Subject: 4447 --- html/045closure_name.cc.html | 295 +++++++++++++++++++++++-------------------- 1 file changed, 155 insertions(+), 140 deletions(-) (limited to 'html/045closure_name.cc.html') diff --git a/html/045closure_name.cc.html b/html/045closure_name.cc.html index 6cacabf7..01acd40d 100644 --- a/html/045closure_name.cc.html +++ b/html/045closure_name.cc.html @@ -71,14 +71,14 @@ if ('onhashchange' in window) { 9 :(scenario closure) 10 def main [ 11 default-space:space <- new location:type, 30 - 12 1:space/names:new-counter <- new-counter - 13 2:num/raw <- increment-counter 1:space/names:new-counter - 14 3:num/raw <- increment-counter 1:space/names:new-counter + 12 2:space/names:new-counter <- new-counter + 13 10:num/raw <- increment-counter 2:space/names:new-counter + 14 11:num/raw <- increment-counter 2:space/names:new-counter 15 ] 16 def new-counter [ 17 default-space:space <- new location:type, 30 18 x:num <- copy 23 - 19 y:num <- copy 3 # variable that will be incremented + 19 y:num <- copy 13 # variable that will be incremented 20 return default-space:space 21 ] 22 def increment-counter [ @@ -89,147 +89,162 @@ if ('onhashchange' in window) { 27 return y:num/space:1 28 ] 29 +name: lexically surrounding space for recipe increment-counter comes from new-counter - 30 +mem: storing 5 in location 3 + 30 +mem: storing 15 in location 11 31 32 //: To make this work, compute the recipe that provides names for the 33 //: surrounding space of each recipe. 34 35 :(before "End Globals") - 36 map<recipe_ordinal, recipe_ordinal> Surrounding_space; - 37 - 38 :(before "Transform.push_back(transform_names)") - 39 Transform.push_back(collect_surrounding_spaces); // idempotent - 40 - 41 :(code) - 42 void collect_surrounding_spaces(const recipe_ordinal r) { - 43 trace(9991, "transform") << "--- collect surrounding spaces for recipe " << get(Recipe, r).name << end(); - 44 for (int i = 0; i < SIZE(get(Recipe, r).steps); ++i) { - 45 const instruction& inst = get(Recipe, r).steps.at(i); - 46 if (inst.is_label) continue; - 47 for (int j = 0; j < SIZE(inst.products); ++j) { - 48 if (is_literal(inst.products.at(j))) continue; - 49 if (inst.products.at(j).name != "0") continue; - 50 if (!is_mu_space(inst.products.at(j))) { - 51 raise << "slot 0 should always have type address:array:location, but is '" << to_string(inst.products.at(j)) << "'\n" << end(); - 52 continue; - 53 } - 54 string_tree* s = property(inst.products.at(j), "names"); - 55 if (!s) { - 56 raise << "slot 0 requires a /names property in recipe '" << get(Recipe, r).name << "'\n" << end(); - 57 continue; - 58 } - 59 if (!s->atom) raise << "slot 0 should have a single value in /names, but got '" << to_string(inst.products.at(j)) << "'\n" << end(); - 60 const string& surrounding_recipe_name = s->value; - 61 if (surrounding_recipe_name.empty()) { - 62 raise << "slot 0 doesn't initialize its /names property in recipe '" << get(Recipe, r).name << "'\n" << end(); - 63 continue; - 64 } - 65 if (contains_key(Surrounding_space, r) - 66 && get(Surrounding_space, r) != get(Recipe_ordinal, surrounding_recipe_name)) { - 67 raise << "recipe '" << get(Recipe, r).name << "' can have only one 'surrounding' recipe but has '" << get(Recipe, get(Surrounding_space, r)).name << "' and '" << surrounding_recipe_name << "'\n" << end(); - 68 continue; - 69 } - 70 trace(9993, "name") << "lexically surrounding space for recipe " << get(Recipe, r).name << " comes from " << surrounding_recipe_name << end(); - 71 if (!contains_key(Recipe_ordinal, surrounding_recipe_name)) { - 72 raise << "can't find recipe providing surrounding space for '" << get(Recipe, r).name << "'; looking for '" << surrounding_recipe_name << "'\n" << end(); - 73 continue; - 74 } - 75 put(Surrounding_space, r, get(Recipe_ordinal, surrounding_recipe_name)); - 76 } - 77 } - 78 } - 79 - 80 //: Once surrounding spaces are available, transform_names uses them to handle - 81 //: /space properties. - 82 - 83 :(replace{} "int lookup_name(const reagent& r, const recipe_ordinal default_recipe)") - 84 int lookup_name(const reagent& x, const recipe_ordinal default_recipe) { - 85 if (!has_property(x, "space")) { - 86 if (Name[default_recipe].empty()) raise << "name not found: " << x.name << '\n' << end(); - 87 return Name[default_recipe][x.name]; - 88 } - 89 string_tree* p = property(x, "space"); - 90 if (!p || !p->atom) raise << "/space property should have exactly one (non-negative integer) value\n" << end(); - 91 int n = to_integer(p->value); - 92 assert(n >= 0); - 93 recipe_ordinal surrounding_recipe = lookup_surrounding_recipe(default_recipe, n); - 94 if (surrounding_recipe == -1) return -1; - 95 set<recipe_ordinal> done; - 96 vector<recipe_ordinal> path; - 97 return lookup_name(x, surrounding_recipe, done, path); - 98 } - 99 -100 // If the recipe we need to lookup this name in doesn't have names done yet, -101 // recursively call transform_names on it. -102 int lookup_name(const reagent& x, const recipe_ordinal r, set<recipe_ordinal>& done, vector<recipe_ordinal>& path) { -103 if (!Name[r].empty()) return Name[r][x.name]; -104 if (contains_key(done, r)) { -105 raise << "can't compute address of '" << to_string(x) << "' because\n" << end(); -106 for (int i = 1; i < SIZE(path); ++i) { -107 raise << path.at(i-1) << " requires computing names of " << path.at(i) << '\n' << end(); -108 } -109 raise << path.at(SIZE(path)-1) << " requires computing names of " << r << "..ad infinitum\n" << end(); -110 return -1; -111 } -112 done.insert(r); -113 path.push_back(r); -114 transform_names(r); // Not passing 'done' through. Might this somehow cause an infinite loop? -115 assert(!Name[r].empty()); -116 return Name[r][x.name]; -117 } -118 -119 recipe_ordinal lookup_surrounding_recipe(const recipe_ordinal r, int n) { -120 if (n == 0) return r; -121 if (!contains_key(Surrounding_space, r)) { -122 raise << "don't know surrounding recipe of '" << get(Recipe, r).name << "'\n" << end(); -123 return -1; -124 } -125 assert(contains_key(Surrounding_space, r)); -126 return lookup_surrounding_recipe(get(Surrounding_space, r), n-1); -127 } -128 -129 //: weaken use-before-set detection just a tad -130 :(replace{} "bool already_transformed(const reagent& r, const map<string, int>& names)") -131 bool already_transformed(const reagent& r, const map<string, int>& names) { -132 if (has_property(r, "space")) { -133 string_tree* p = property(r, "space"); -134 if (!p || !p->atom) { -135 raise << "/space property should have exactly one (non-negative integer) value in '" << r.original_string << "'\n" << end(); -136 return false; -137 } -138 if (p->value != "0") return true; -139 } -140 return contains_key(names, r.name); -141 } -142 -143 :(scenario missing_surrounding_space) -144 % Hide_errors = true; -145 def f [ -146 local-scope -147 x:num/space:1 <- copy 34 -148 ] -149 +error: don't know surrounding recipe of 'f' -150 +error: f: can't find a place to store 'x' -151 -152 //: extra test for try_reclaim_locals() from previous layers -153 :(scenario local_scope_ignores_nonlocal_spaces) -154 def new-scope [ -155 local-scope -156 x:&:num <- new number:type -157 *x:&:num <- copy 34 -158 return default-space:space -159 ] -160 def use-scope [ -161 local-scope -162 outer:space/names:new-scope <- next-ingredient -163 0:space/names:new-scope <- copy outer:space -164 return *x:&:num/space:1 -165 ] -166 def main [ -167 1:space/raw <- new-scope -168 2:num/raw <- use-scope 1:space/raw -169 ] -170 +mem: storing 34 in location 2 + 36 map<recipe_ordinal, recipe_ordinal> Surrounding_space; // internal to transform; no need to snapshot + 37 :(before "End Reset") + 38 Surrounding_space.clear(); + 39 + 40 :(before "Begin Type Modifying Transforms") + 41 Transform.push_back(collect_surrounding_spaces); // idempotent + 42 + 43 :(code) + 44 void collect_surrounding_spaces(const recipe_ordinal r) { + 45 trace(9991, "transform") << "--- collect surrounding spaces for recipe " << get(Recipe, r).name << end(); + 46 for (int i = 0; i < SIZE(get(Recipe, r).steps); ++i) { + 47 const instruction& inst = get(Recipe, r).steps.at(i); + 48 if (inst.is_label) continue; + 49 for (int j = 0; j < SIZE(inst.products); ++j) { + 50 if (is_literal(inst.products.at(j))) continue; + 51 if (inst.products.at(j).name != "0") continue; + 52 if (!is_mu_space(inst.products.at(j))) { + 53 raise << "slot 0 should always have type address:array:location, but is '" << to_string(inst.products.at(j)) << "'\n" << end(); + 54 continue; + 55 } + 56 string_tree* s = property(inst.products.at(j), "names"); + 57 if (!s) { + 58 raise << "slot 0 requires a /names property in recipe '" << get(Recipe, r).name << "'\n" << end(); + 59 continue; + 60 } + 61 if (!s->atom) raise << "slot 0 should have a single value in /names, but got '" << to_string(inst.products.at(j)) << "'\n" << end(); + 62 const string& surrounding_recipe_name = s->value; + 63 if (surrounding_recipe_name.empty()) { + 64 raise << "slot 0 doesn't initialize its /names property in recipe '" << get(Recipe, r).name << "'\n" << end(); + 65 continue; + 66 } + 67 if (contains_key(Surrounding_space, r) + 68 && get(Surrounding_space, r) != get(Recipe_ordinal, surrounding_recipe_name)) { + 69 raise << "recipe '" << get(Recipe, r).name << "' can have only one 'surrounding' recipe but has '" << get(Recipe, get(Surrounding_space, r)).name << "' and '" << surrounding_recipe_name << "'\n" << end(); + 70 continue; + 71 } + 72 trace(9993, "name") << "lexically surrounding space for recipe " << get(Recipe, r).name << " comes from " << surrounding_recipe_name << end(); + 73 if (!contains_key(Recipe_ordinal, surrounding_recipe_name)) { + 74 raise << "can't find recipe providing surrounding space for '" << get(Recipe, r).name << "'; looking for '" << surrounding_recipe_name << "'\n" << end(); + 75 continue; + 76 } + 77 put(Surrounding_space, r, get(Recipe_ordinal, surrounding_recipe_name)); + 78 } + 79 } + 80 } + 81 + 82 //: Once surrounding spaces are available, transform_names uses them to handle + 83 //: /space properties. + 84 + 85 :(replace{} "int lookup_name(const reagent& r, const recipe_ordinal default_recipe)") + 86 int lookup_name(const reagent& x, const recipe_ordinal default_recipe) { + 87 if (!has_property(x, "space")) { + 88 if (Name[default_recipe].empty()) raise << "name not found: " << x.name << '\n' << end(); + 89 return Name[default_recipe][x.name]; + 90 } + 91 string_tree* p = property(x, "space"); + 92 if (!p || !p->atom) raise << "/space property should have exactly one (non-negative integer) value\n" << end(); + 93 int n = to_integer(p->value); + 94 assert(n >= 0); + 95 recipe_ordinal surrounding_recipe = lookup_surrounding_recipe(default_recipe, n); + 96 if (surrounding_recipe == -1) return -1; + 97 set<recipe_ordinal> done; + 98 vector<recipe_ordinal> path; + 99 return lookup_name(x, surrounding_recipe, done, path); +100 } +101 +102 // If the recipe we need to lookup this name in doesn't have names done yet, +103 // recursively call transform_names on it. +104 int lookup_name(const reagent& x, const recipe_ordinal r, set<recipe_ordinal>& done, vector<recipe_ordinal>& path) { +105 if (!Name[r].empty()) return Name[r][x.name]; +106 if (contains_key(done, r)) { +107 raise << "can't compute address of '" << to_string(x) << "' because\n" << end(); +108 for (int i = 1; i < SIZE(path); ++i) { +109 raise << path.at(i-1) << " requires computing names of " << path.at(i) << '\n' << end(); +110 } +111 raise << path.at(SIZE(path)-1) << " requires computing names of " << r << "..ad infinitum\n" << end(); +112 return -1; +113 } +114 done.insert(r); +115 path.push_back(r); +116 transform_names(r); // Not passing 'done' through. Might this somehow cause an infinite loop? +117 assert(!Name[r].empty()); +118 return Name[r][x.name]; +119 } +120 +121 recipe_ordinal lookup_surrounding_recipe(const recipe_ordinal r, int n) { +122 if (n == 0) return r; +123 if (!contains_key(Surrounding_space, r)) { +124 raise << "don't know surrounding recipe of '" << get(Recipe, r).name << "'\n" << end(); +125 return -1; +126 } +127 assert(contains_key(Surrounding_space, r)); +128 return lookup_surrounding_recipe(get(Surrounding_space, r), n-1); +129 } +130 +131 //: weaken use-before-set detection just a tad +132 :(replace{} "bool already_transformed(const reagent& r, const map<string, int>& names)") +133 bool already_transformed(const reagent& r, const map<string, int>& names) { +134 if (has_property(r, "space")) { +135 string_tree* p = property(r, "space"); +136 if (!p || !p->atom) { +137 raise << "/space property should have exactly one (non-negative integer) value in '" << r.original_string << "'\n" << end(); +138 return false; +139 } +140 if (p->value != "0") return true; +141 } +142 return contains_key(names, r.name); +143 } +144 +145 :(scenario missing_surrounding_space) +146 % Hide_errors = true; +147 def f [ +148 local-scope +149 x:num/space:1 <- copy 34 +150 ] +151 +error: don't know surrounding recipe of 'f' +152 +error: f: can't find a place to store 'x' +153 +154 //: extra test for try_reclaim_locals() from previous layers +155 :(scenario local_scope_ignores_nonlocal_spaces) +156 def new-scope [ +157 local-scope +158 x:&:num <- new number:type +159 *x:&:num <- copy 34 +160 return default-space:space +161 ] +162 def use-scope [ +163 local-scope +164 outer:space/names:new-scope <- next-ingredient +165 0:space/names:new-scope <- copy outer:space +166 return *x:&:num/space:1 +167 ] +168 def main [ +169 1:space/raw <- new-scope +170 3:num/raw <- use-scope 1:space/raw +171 ] +172 +mem: storing 34 in location 3 +173 +174 :(scenario recursive_transform_names) +175 def foo [ +176 local-scope +177 x:num <- copy 0 +178 return default-space:space/names:foo +179 ] +180 def main [ +181 local-scope +182 0:space/names:foo <- foo +183 x:num/space:1 <- copy 34 +184 ] +185 $error: 0 -- cgit 1.4.1-2-gfad0