From e5c11a5137d538b7713dd8708ca767c208824c06 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Mon, 26 Dec 2016 01:17:01 -0800 Subject: 3709 - line numbers in html Each line number also gets an anchor name, but I'm not hyperlinking them for now because I don't want to encourage bookmarking these links just yet. They aren't permalinks because every revision may change what's at any given line number. --- html/045closure_name.cc.html | 368 +++++++++++++++++++++++-------------------- 1 file changed, 196 insertions(+), 172 deletions(-) (limited to 'html/045closure_name.cc.html') diff --git a/html/045closure_name.cc.html b/html/045closure_name.cc.html index a81f9c4b..8613f1da 100644 --- a/html/045closure_name.cc.html +++ b/html/045closure_name.cc.html @@ -6,7 +6,7 @@ - + - +
-//: Writing to a literal (not computed) address of 0 in a recipe chains two
-//: spaces together. When a variable has a property of /space:1, it looks up
-//: the variable in the chained/surrounding space. /space:2 looks up the
-//: surrounding space of the surrounding space, etc.
-
-:(scenario closure)
-def main [
-  default-space:space <- new location:type, 30
-  1:space/names:new-counter <- new-counter
-  2:num/raw <- increment-counter 1:space/names:new-counter
-  3:num/raw <- increment-counter 1:space/names:new-counter
-]
-def new-counter [
-  default-space:space <- new location:type, 30
-  x:num <- copy 23
-  y:num <- copy 3  # variable that will be incremented
-  return default-space:space
-]
-def increment-counter [
-  default-space:space <- new location:type, 30
-  0:space/names:new-counter <- next-ingredient  # outer space must be created by 'new-counter' above
-  y:num/space:1 <- add y:num/space:1, 1  # increment
-  y:num <- copy 234  # dummy
-  return y:num/space:1
-]
-+name: lexically surrounding space for recipe increment-counter comes from new-counter
-+mem: storing 5 in location 3
-
-//: To make this work, compute the recipe that provides names for the
-//: surrounding space of each recipe.
-
-:(before "End Globals")
-map<recipe_ordinal, recipe_ordinal> Surrounding_space;
-
-:(before "Transform.push_back(transform_names)")
-Transform.push_back(collect_surrounding_spaces);  // idempotent
-
-:(code)
-void collect_surrounding_spaces(const recipe_ordinal r) {
-  trace(9991, "transform") << "--- collect surrounding spaces for recipe " << get(Recipe, r).name << end();
-  for (int i = 0;  i < SIZE(get(Recipe, r).steps);  ++i) {
-    const instruction& inst = get(Recipe, r).steps.at(i);
-    if (inst.is_label) continue;
-    for (int j = 0;  j < SIZE(inst.products);  ++j) {
-      if (is_literal(inst.products.at(j))) continue;
-      if (inst.products.at(j).name != "0") continue;
-      if (!is_space(inst.products.at(j))) {
-        raise << "slot 0 should always have type address:array:location, but is '" << to_string(inst.products.at(j)) << "'\n" << end();
-        continue;
-      }
-      string_tree* s = property(inst.products.at(j), "names");
-      if (!s) {
-        raise << "slot 0 requires a /names property in recipe '" << get(Recipe, r).name << "'\n" << end();
-        continue;
-      }
-      if (!s->atom) raise << "slot 0 should have a single value in /names, but got '" << to_string(inst.products.at(j)) << "'\n" << end();
-      const string& surrounding_recipe_name = s->value;
-      if (surrounding_recipe_name.empty()) {
-        raise << "slot 0 doesn't initialize its /names property in recipe '" << get(Recipe, r).name << "'\n" << end();
-        continue;
-      }
-      if (contains_key(Surrounding_space, r)
-          && get(Surrounding_space, r) != get(Recipe_ordinal, surrounding_recipe_name)) {
-        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();
-        continue;
-      }
-      trace(9993, "name") << "lexically surrounding space for recipe " << get(Recipe, r).name << " comes from " << surrounding_recipe_name << end();
-      if (!contains_key(Recipe_ordinal, surrounding_recipe_name)) {
-        raise << "can't find recipe providing surrounding space for '" << get(Recipe, r).name << "'; looking for '" << surrounding_recipe_name << "'\n" << end();
-        continue;
-      }
-      put(Surrounding_space, r, get(Recipe_ordinal, surrounding_recipe_name));
-    }
-  }
-}
-
-//: Once surrounding spaces are available, transform_names uses them to handle
-//: /space properties.
-
-:(replace{} "int lookup_name(const reagent& r, const recipe_ordinal default_recipe)")
-int lookup_name(const reagent& x, const recipe_ordinal default_recipe) {
-  if (!has_property(x, "space")) {
-    if (Name[default_recipe].empty()) raise << "name not found: " << x.name << '\n' << end();
-    return Name[default_recipe][x.name];
-  }
-  string_tree* p = property(x, "space");
-  if (!p || !p->atom) raise << "/space property should have exactly one (non-negative integer) value\n" << end();
-  int n = to_integer(p->value);
-  assert(n >= 0);
-  recipe_ordinal surrounding_recipe = lookup_surrounding_recipe(default_recipe, n);
-  if (surrounding_recipe == -1) return -1;
-  set<recipe_ordinal> done;
-  vector<recipe_ordinal> path;
-  return lookup_name(x, surrounding_recipe, done, path);
-}
-
-// If the recipe we need to lookup this name in doesn't have names done yet,
-// recursively call transform_names on it.
-int lookup_name(const reagent& x, const recipe_ordinal r, set<recipe_ordinal>& done, vector<recipe_ordinal>& path) {
-  if (!Name[r].empty()) return Name[r][x.name];
-  if (contains_key(done, r)) {
-    raise << "can't compute address of '" << to_string(x) << "' because\n" << end();
-    for (int i = 1;  i < SIZE(path);  ++i) {
-      raise << path.at(i-1) << " requires computing names of " << path.at(i) << '\n' << end();
-    }
-    raise << path.at(SIZE(path)-1) << " requires computing names of " << r << "..ad infinitum\n" << end();
-    return -1;
-  }
-  done.insert(r);
-  path.push_back(r);
-  transform_names(r);  // Not passing 'done' through. Might this somehow cause an infinite loop?
-  assert(!Name[r].empty());
-  return Name[r][x.name];
-}
-
-recipe_ordinal lookup_surrounding_recipe(const recipe_ordinal r, int n) {
-  if (n == 0) return r;
-  if (!contains_key(Surrounding_space, r)) {
-    raise << "don't know surrounding recipe of '" << get(Recipe, r).name << "'\n" << end();
-    return -1;
-  }
-  assert(contains_key(Surrounding_space, r));
-  return lookup_surrounding_recipe(get(Surrounding_space, r), n-1);
-}
-
-//: weaken use-before-set detection just a tad
-:(replace{} "bool already_transformed(const reagent& r, const map<string, int>& names)")
-bool already_transformed(const reagent& r, const map<string, int>& names) {
-  if (has_property(r, "space")) {
-    string_tree* p = property(r, "space");
-    if (!p || !p->atom) {
-      raise << "/space property should have exactly one (non-negative integer) value in '" << r.original_string << "'\n" << end();
-      return false;
-    }
-    if (p->value != "0") return true;
-  }
-  return contains_key(names, r.name);
-}
-
-:(scenario missing_surrounding_space)
-% Hide_errors = true;
-def f [
-  local-scope
-  x:num/space:1 <- copy 34
-]
-+error: don't know surrounding recipe of 'f'
-+error: f: can't find a place to store 'x'
-
-//: extra test for try_reclaim_locals() from previous layers
-:(scenario local_scope_ignores_nonlocal_spaces)
-def new-scope [
-  new-default-space
-  x:&:num <- new number:type
-  *x:&:num <- copy 34
-  return default-space:space
-]
-def use-scope [
-  local-scope
-  outer:space <- next-ingredient
-  0:space/names:new-scope <- copy outer:space
-  return *x:&:num/space:1
-]
-def main [
-  1:space/raw <- new-scope
-  2:num/raw <- use-scope 1:space/raw
-]
-+mem: storing 34 in location 2
+  1 //: Writing to a literal (not computed) address of 0 in a recipe chains two
+  2 //: spaces together. When a variable has a property of /space:1, it looks up
+  3 //: the variable in the chained/surrounding space. /space:2 looks up the
+  4 //: surrounding space of the surrounding space, etc.
+  5 
+  6 :(scenario closure)
+  7 def main [
+  8   default-space:space <- new location:type, 30
+  9   1:space/names:new-counter <- new-counter
+ 10   2:num/raw <- increment-counter 1:space/names:new-counter
+ 11   3:num/raw <- increment-counter 1:space/names:new-counter
+ 12 ]
+ 13 def new-counter [
+ 14   default-space:space <- new location:type, 30
+ 15   x:num <- copy 23
+ 16   y:num <- copy 3  # variable that will be incremented
+ 17   return default-space:space
+ 18 ]
+ 19 def increment-counter [
+ 20   default-space:space <- new location:type, 30
+ 21   0:space/names:new-counter <- next-ingredient  # outer space must be created by 'new-counter' above
+ 22   y:num/space:1 <- add y:num/space:1, 1  # increment
+ 23   y:num <- copy 234  # dummy
+ 24   return y:num/space:1
+ 25 ]
+ 26 +name: lexically surrounding space for recipe increment-counter comes from new-counter
+ 27 +mem: storing 5 in location 3
+ 28 
+ 29 //: To make this work, compute the recipe that provides names for the
+ 30 //: surrounding space of each recipe.
+ 31 
+ 32 :(before "End Globals")
+ 33 map<recipe_ordinal, recipe_ordinal> Surrounding_space;
+ 34 
+ 35 :(before "Transform.push_back(transform_names)")
+ 36 Transform.push_back(collect_surrounding_spaces);  // idempotent
+ 37 
+ 38 :(code)
+ 39 void collect_surrounding_spaces(const recipe_ordinal r) {
+ 40   trace(9991, "transform") << "--- collect surrounding spaces for recipe " << get(Recipe, r).name << end();
+ 41   for (int i = 0;  i < SIZE(get(Recipe, r).steps);  ++i) {
+ 42     const instruction& inst = get(Recipe, r).steps.at(i);
+ 43     if (inst.is_label) continue;
+ 44     for (int j = 0;  j < SIZE(inst.products);  ++j) {
+ 45       if (is_literal(inst.products.at(j))) continue;
+ 46       if (inst.products.at(j).name != "0") continue;
+ 47       if (!is_space(inst.products.at(j))) {
+ 48         raise << "slot 0 should always have type address:array:location, but is '" << to_string(inst.products.at(j)) << "'\n" << end();
+ 49         continue;
+ 50       }
+ 51       string_tree* s = property(inst.products.at(j), "names");
+ 52       if (!s) {
+ 53         raise << "slot 0 requires a /names property in recipe '" << get(Recipe, r).name << "'\n" << end();
+ 54         continue;
+ 55       }
+ 56       if (!s->atom) raise << "slot 0 should have a single value in /names, but got '" << to_string(inst.products.at(j)) << "'\n" << end();
+ 57       const string& surrounding_recipe_name = s->value;
+ 58       if (surrounding_recipe_name.empty()) {
+ 59         raise << "slot 0 doesn't initialize its /names property in recipe '" << get(Recipe, r).name << "'\n" << end();
+ 60         continue;
+ 61       }
+ 62       if (contains_key(Surrounding_space, r)
+ 63           && get(Surrounding_space, r) != get(Recipe_ordinal, surrounding_recipe_name)) {
+ 64         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();
+ 65         continue;
+ 66       }
+ 67       trace(9993, "name") << "lexically surrounding space for recipe " << get(Recipe, r).name << " comes from " << surrounding_recipe_name << end();
+ 68       if (!contains_key(Recipe_ordinal, surrounding_recipe_name)) {
+ 69         raise << "can't find recipe providing surrounding space for '" << get(Recipe, r).name << "'; looking for '" << surrounding_recipe_name << "'\n" << end();
+ 70         continue;
+ 71       }
+ 72       put(Surrounding_space, r, get(Recipe_ordinal, surrounding_recipe_name));
+ 73     }
+ 74   }
+ 75 }
+ 76 
+ 77 //: Once surrounding spaces are available, transform_names uses them to handle
+ 78 //: /space properties.
+ 79 
+ 80 :(replace{} "int lookup_name(const reagent& r, const recipe_ordinal default_recipe)")
+ 81 int lookup_name(const reagent& x, const recipe_ordinal default_recipe) {
+ 82   if (!has_property(x, "space")) {
+ 83     if (Name[default_recipe].empty()) raise << "name not found: " << x.name << '\n' << end();
+ 84     return Name[default_recipe][x.name];
+ 85   }
+ 86   string_tree* p = property(x, "space");
+ 87   if (!p || !p->atom) raise << "/space property should have exactly one (non-negative integer) value\n" << end();
+ 88   int n = to_integer(p->value);
+ 89   assert(n >= 0);
+ 90   recipe_ordinal surrounding_recipe = lookup_surrounding_recipe(default_recipe, n);
+ 91   if (surrounding_recipe == -1) return -1;
+ 92   set<recipe_ordinal> done;
+ 93   vector<recipe_ordinal> path;
+ 94   return lookup_name(x, surrounding_recipe, done, path);
+ 95 }
+ 96 
+ 97 // If the recipe we need to lookup this name in doesn't have names done yet,
+ 98 // recursively call transform_names on it.
+ 99 int lookup_name(const reagent& x, const recipe_ordinal r, set<recipe_ordinal>& done, vector<recipe_ordinal>& path) {
+100   if (!Name[r].empty()) return Name[r][x.name];
+101   if (contains_key(done, r)) {
+102     raise << "can't compute address of '" << to_string(x) << "' because\n" << end();
+103     for (int i = 1;  i < SIZE(path);  ++i) {
+104       raise << path.at(i-1) << " requires computing names of " << path.at(i) << '\n' << end();
+105     }
+106     raise << path.at(SIZE(path)-1) << " requires computing names of " << r << "..ad infinitum\n" << end();
+107     return -1;
+108   }
+109   done.insert(r);
+110   path.push_back(r);
+111   transform_names(r);  // Not passing 'done' through. Might this somehow cause an infinite loop?
+112   assert(!Name[r].empty());
+113   return Name[r][x.name];
+114 }
+115 
+116 recipe_ordinal lookup_surrounding_recipe(const recipe_ordinal r, int n) {
+117   if (n == 0) return r;
+118   if (!contains_key(Surrounding_space, r)) {
+119     raise << "don't know surrounding recipe of '" << get(Recipe, r).name << "'\n" << end();
+120     return -1;
+121   }
+122   assert(contains_key(Surrounding_space, r));
+123   return lookup_surrounding_recipe(get(Surrounding_space, r), n-1);
+124 }
+125 
+126 //: weaken use-before-set detection just a tad
+127 :(replace{} "bool already_transformed(const reagent& r, const map<string, int>& names)")
+128 bool already_transformed(const reagent& r, const map<string, int>& names) {
+129   if (has_property(r, "space")) {
+130     string_tree* p = property(r, "space");
+131     if (!p || !p->atom) {
+132       raise << "/space property should have exactly one (non-negative integer) value in '" << r.original_string << "'\n" << end();
+133       return false;
+134     }
+135     if (p->value != "0") return true;
+136   }
+137   return contains_key(names, r.name);
+138 }
+139 
+140 :(scenario missing_surrounding_space)
+141 % Hide_errors = true;
+142 def f [
+143   local-scope
+144   x:num/space:1 <- copy 34
+145 ]
+146 +error: don't know surrounding recipe of 'f'
+147 +error: f: can't find a place to store 'x'
+148 
+149 //: extra test for try_reclaim_locals() from previous layers
+150 :(scenario local_scope_ignores_nonlocal_spaces)
+151 def new-scope [
+152   new-default-space
+153   x:&:num <- new number:type
+154   *x:&:num <- copy 34
+155   return default-space:space
+156 ]
+157 def use-scope [
+158   local-scope
+159   outer:space <- next-ingredient
+160   0:space/names:new-scope <- copy outer:space
+161   return *x:&:num/space:1
+162 ]
+163 def main [
+164   1:space/raw <- new-scope
+165   2:num/raw <- use-scope 1:space/raw
+166 ]
+167 +mem: storing 34 in location 2
 
-- cgit 1.4.1-2-gfad0