From 6e1eeeebfb453fa7c871869c19375ce60fbd7413 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 27 Jul 2019 16:01:55 -0700 Subject: 5485 - promote SubX to top-level --- html/042name.cc.html | 409 --------------------------------------------------- 1 file changed, 409 deletions(-) delete mode 100644 html/042name.cc.html (limited to 'html/042name.cc.html') diff --git a/html/042name.cc.html b/html/042name.cc.html deleted file mode 100644 index ebea1c91..00000000 --- a/html/042name.cc.html +++ /dev/null @@ -1,409 +0,0 @@ - - - - -Mu - 042name.cc - - - - - - - - - - -https://github.com/akkartik/mu/blob/master/042name.cc -
-  1 //: A big convenience high-level languages provide is the ability to name memory
-  2 //: locations. In Mu, a transform called 'transform_names' provides this
-  3 //: convenience.
-  4 
-  5 :(scenario transform_names)
-  6 def main [
-  7   x:num <- copy 0
-  8 ]
-  9 +name: assign x 2
- 10 +mem: storing 0 in location 2
- 11 
- 12 :(scenarios transform)
- 13 :(scenario transform_names_fails_on_use_before_define)
- 14 % Hide_errors = true;
- 15 def main [
- 16   x:num <- copy y:num
- 17 ]
- 18 +error: main: tried to read ingredient 'y' in 'x:num <- copy y:num' but it hasn't been written to yet
- 19 # todo: detect conditional defines
- 20 
- 21 :(after "End Type Modifying Transforms")
- 22 Transform.push_back(transform_names);  // idempotent
- 23 
- 24 :(before "End Globals")
- 25 map<recipe_ordinal, map<string, int> > Name;
- 26 
- 27 //: the Name map is a global, so save it before tests and reset it for every
- 28 //: test, just to be safe.
- 29 :(before "End Globals")
- 30 map<recipe_ordinal, map<string, int> > Name_snapshot;
- 31 :(before "End save_snapshots")
- 32 Name_snapshot = Name;
- 33 :(before "End restore_snapshots")
- 34 Name = Name_snapshot;
- 35 
- 36 :(code)
- 37 void transform_names(const recipe_ordinal r) {
- 38   recipe& caller = get(Recipe, r);
- 39   trace(9991, "transform") << "--- transform names for recipe " << caller.name << end();
- 40   bool names_used = false;
- 41   bool numeric_locations_used = false;
- 42   map<string, int>& names = Name[r];
- 43   // record the indices 'used' so far in the map
- 44   int& curr_idx = names[""];
- 45   // reserve indices 0 and 1 for the chaining slot in a later layer.
- 46   // transform_names may get called multiple times in later layers, so
- 47   // curr_idx may already be set.
- 48   if (curr_idx < 2) curr_idx = 2;
- 49   for (int i = 0;  i < SIZE(caller.steps);  ++i) {
- 50     instruction& inst = caller.steps.at(i);
- 51     // End transform_names(inst) Special-cases
- 52     // map names to addresses
- 53     for (int in = 0;  in < SIZE(inst.ingredients);  ++in) {
- 54       reagent& ingredient = inst.ingredients.at(in);
- 55       if (is_disqualified(ingredient, inst, caller.name)) continue;
- 56       if (is_numeric_location(ingredient)) numeric_locations_used = true;
- 57       if (is_named_location(ingredient)) names_used = true;
- 58       if (is_integer(ingredient.name)) continue;
- 59       if (!already_transformed(ingredient, names)) {
- 60         raise << maybe(caller.name) << "tried to read ingredient '" << ingredient.name << "' in '" << to_original_string(inst) << "' but it hasn't been written to yet\n" << end();
- 61         // use-before-set Error
- 62         return;
- 63       }
- 64       int v = lookup_name(ingredient, r);
- 65       if (v >= 0) {
- 66         ingredient.set_value(v);
- 67         // Done Placing Ingredient(ingredient, inst, caller)
- 68       }
- 69       else {
- 70         raise << maybe(caller.name) << "can't find a place to store '" << ingredient.name << "'\n" << end();
- 71         return;
- 72       }
- 73     }
- 74     for (int out = 0;  out < SIZE(inst.products);  ++out) {
- 75       reagent& product = inst.products.at(out);
- 76       if (is_disqualified(product, inst, caller.name)) continue;
- 77       if (is_numeric_location(product)) numeric_locations_used = true;
- 78       if (is_named_location(product)) names_used = true;
- 79       if (is_integer(product.name)) continue;
- 80       if (names.find(product.name) == names.end()) {
- 81         trace(9993, "name") << "assign " << product.name << " " << curr_idx << end();
- 82         names[product.name] = curr_idx;
- 83         curr_idx += size_of(product);
- 84       }
- 85       int v = lookup_name(product, r);
- 86       if (v >= 0) {
- 87         product.set_value(v);
- 88         // Done Placing Product(product, inst, caller)
- 89       }
- 90       else {
- 91         raise << maybe(caller.name) << "can't find a place to store '" << product.name << "'\n" << end();
- 92         return;
- 93       }
- 94     }
- 95   }
- 96   if (names_used && numeric_locations_used)
- 97     raise << maybe(caller.name) << "mixing variable names and numeric addresses\n" << end();
- 98 }
- 99 
-100 bool is_disqualified(/*mutable*/ reagent& x, const instruction& inst, const string& recipe_name) {
-101   if (!x.type) {
-102     raise << maybe(recipe_name) << "missing type for '" << x.original_string << "' in '" << to_original_string(inst) << "'\n" << end();
-103     // missing-type Error 1
-104     return true;
-105   }
-106   if (is_raw(x)) return true;
-107   if (is_literal(x)) return true;
-108   // End is_disqualified Special-cases
-109   if (x.initialized) return true;
-110   return false;
-111 }
-112 
-113 bool already_transformed(const reagent& r, const map<string, int>& names) {
-114   return contains_key(names, r.name);
-115 }
-116 
-117 int lookup_name(const reagent& r, const recipe_ordinal default_recipe) {
-118   return Name[default_recipe][r.name];
-119 }
-120 
-121 type_ordinal skip_addresses(type_tree* type) {
-122   while (type && is_compound_type_starting_with(type, "address"))
-123     type = type->right;
-124   if (!type) return -1;  // error handled elsewhere
-125   if (type->atom) return type->value;
-126   const type_tree* base_type = type;
-127   // Update base_type in skip_addresses
-128   if (base_type->atom)
-129     return base_type->value;
-130   assert(base_type->left->atom);
-131   return base_type->left->value;
-132 }
-133 
-134 bool is_compound_type_starting_with(const type_tree* type, const string& expected_name) {
-135   if (!type) return false;
-136   if (type->atom) return false;
-137   if (!type->left->atom) return false;
-138   return type->left->value == get(Type_ordinal, expected_name);
-139 }
-140 
-141 int find_element_offset(const type_ordinal t, const string& name, const string& recipe_name) {
-142   const type_info& container = get(Type, t);
-143   for (int i = 0;  i < SIZE(container.elements);  ++i)
-144     if (container.elements.at(i).name == name) return i;
-145   raise << maybe(recipe_name) << "unknown element '" << name << "' in container '" << get(Type, t).name << "'\n" << end();
-146   return -1;
-147 }
-148 int find_element_location(int base_address, const string& name, const type_tree* type, const string& recipe_name) {
-149   int offset = find_element_offset(get_base_type(type)->value, name, recipe_name);
-150   if (offset == -1) return offset;
-151   int result = base_address;
-152   for (int i = 0; i < offset; ++i)
-153     result += size_of(element_type(type, i));
-154   return result;
-155 }
-156 
-157 bool is_numeric_location(const reagent& x) {
-158   if (is_literal(x)) return false;
-159   if (is_raw(x)) return false;
-160   if (x.name == "0") return false;  // used for chaining lexical scopes
-161   return is_integer(x.name);
-162 }
-163 
-164 bool is_named_location(const reagent& x) {
-165   if (is_literal(x)) return false;
-166   if (is_raw(x)) return false;
-167   if (is_special_name(x.name)) return false;
-168   return !is_integer(x.name);
-169 }
-170 
-171 // all names here should either be disqualified or also in bind_special_scenario_names
-172 bool is_special_name(const string& s) {
-173   if (s == "_") return true;
-174   if (s == "0") return true;
-175   // End is_special_name Special-cases
-176   return false;
-177 }
-178 
-179 bool is_raw(const reagent& r) {
-180   return has_property(r, "raw");
-181 }
-182 
-183 :(scenario transform_names_supports_containers)
-184 def main [
-185   x:point <- merge 34, 35
-186   y:num <- copy 3
-187 ]
-188 +name: assign x 2
-189 # skip location 2 because x occupies two locations
-190 +name: assign y 4
-191 
-192 :(scenario transform_names_supports_static_arrays)
-193 def main [
-194   x:@:num:3 <- create-array
-195   y:num <- copy 3
-196 ]
-197 +name: assign x 2
-198 # skip locations 2, 3, 4 because x occupies four locations
-199 +name: assign y 6
-200 
-201 :(scenario transform_names_passes_dummy)
-202 # _ is just a dummy result that never gets consumed
-203 def main [
-204   _, x:num <- copy 0, 1
-205 ]
-206 +name: assign x 2
-207 -name: assign _ 2
-208 
-209 //: an escape hatch to suppress name conversion that we'll use later
-210 :(scenarios run)
-211 :(scenario transform_names_passes_raw)
-212 % Hide_errors = true;
-213 def main [
-214   x:num/raw <- copy 0
-215 ]
-216 -name: assign x 2
-217 +error: can't write to location 0 in 'x:num/raw <- copy 0'
-218 
-219 :(scenarios transform)
-220 :(scenario transform_names_fails_when_mixing_names_and_numeric_locations)
-221 % Hide_errors = true;
-222 def main [
-223   x:num <- copy 1:num
-224 ]
-225 +error: main: mixing variable names and numeric addresses
-226 
-227 :(scenario transform_names_fails_when_mixing_names_and_numeric_locations_2)
-228 % Hide_errors = true;
-229 def main [
-230   x:num <- copy 1
-231   1:num <- copy x:num
-232 ]
-233 +error: main: mixing variable names and numeric addresses
-234 
-235 :(scenario transform_names_does_not_fail_when_mixing_names_and_raw_locations)
-236 def main [
-237   x:num <- copy 1:num/raw
-238 ]
-239 -error: main: mixing variable names and numeric addresses
-240 $error: 0
-241 
-242 :(scenario transform_names_does_not_fail_when_mixing_names_and_literals)
-243 def main [
-244   x:num <- copy 1
-245 ]
-246 -error: main: mixing variable names and numeric addresses
-247 $error: 0
-248 
-249 //:: Support element names for containers in 'get' and 'get-location' and 'put'.
-250 //: (get-location is implemented later)
-251 
-252 :(before "End update GET offset_value in Check")
-253 else {
-254   if (!offset.initialized) {
-255     raise << maybe(get(Recipe, r).name) << "uninitialized offset '" << offset.name << "' in '" << to_original_string(inst) << "'\n" << end();
-256     break;
-257   }
-258   offset_value = offset.value;
-259 }
-260 
-261 :(scenario transform_names_transforms_container_elements)
-262 def main [
-263   p:&:point <- copy null
-264   a:num <- get *p:&:point, y:offset
-265   b:num <- get *p:&:point, x:offset
-266 ]
-267 +name: element y of type point is at offset 1
-268 +name: element x of type point is at offset 0
-269 
-270 :(before "End transform_names(inst) Special-cases")
-271 // replace element names of containers with offsets
-272 if (inst.name == "get" || inst.name == "get-location" || inst.name == "put") {
-273   //: avoid raising any errors here; later layers will support overloading new
-274   //: instructions with the same names (static dispatch), which could lead to
-275   //: spurious errors
-276   if (SIZE(inst.ingredients) < 2)
-277     break;  // error raised elsewhere
-278   if (!is_literal(inst.ingredients.at(1)))
-279     break;  // error raised elsewhere
-280   if (inst.ingredients.at(1).name.find_first_not_of("0123456789") != string::npos) {
-281     // since first non-address in base type must be a container, we don't have to canonize
-282     type_ordinal base_type = skip_addresses(inst.ingredients.at(0).type);
-283     if (contains_key(Type, base_type)) {  // otherwise we'll raise an error elsewhere
-284       inst.ingredients.at(1).set_value(find_element_offset(base_type, inst.ingredients.at(1).name, get(Recipe, r).name));
-285       trace(9993, "name") << "element " << inst.ingredients.at(1).name << " of type " << get(Type, base_type).name << " is at offset " << no_scientific(inst.ingredients.at(1).value) << end();
-286     }
-287   }
-288 }
-289 
-290 :(scenario missing_type_in_get)
-291 % Hide_errors = true;
-292 def main [
-293   get a, x:offset
-294 ]
-295 +error: main: missing type for 'a' in 'get a, x:offset'
-296 
-297 :(scenario transform_names_handles_containers)
-298 def main [
-299   a:point <- merge 0, 0
-300   b:num <- copy 0
-301 ]
-302 +name: assign a 2
-303 +name: assign b 4
-304 
-305 //:: Support variant names for exclusive containers in 'maybe-convert'.
-306 
-307 :(scenarios run)
-308 :(scenario transform_names_handles_exclusive_containers)
-309 def main [
-310   12:num <- copy 1
-311   13:num <- copy 35
-312   14:num <- copy 36
-313   20:point, 22:bool <- maybe-convert 12:number-or-point/unsafe, p:variant
-314 ]
-315 +name: variant p of type number-or-point has tag 1
-316 +mem: storing 1 in location 22
-317 +mem: storing 35 in location 20
-318 +mem: storing 36 in location 21
-319 
-320 :(before "End transform_names(inst) Special-cases")
-321 // convert variant names of exclusive containers
-322 if (inst.name == "maybe-convert") {
-323   if (SIZE(inst.ingredients) != 2) {
-324     raise << maybe(get(Recipe, r).name) << "exactly 2 ingredients expected in '" << to_original_string(inst) << "'\n" << end();
-325     break;
-326   }
-327   assert(is_literal(inst.ingredients.at(1)));
-328   if (inst.ingredients.at(1).name.find_first_not_of("0123456789") != string::npos) {
-329     // since first non-address in base type must be an exclusive container, we don't have to canonize
-330     type_ordinal base_type = skip_addresses(inst.ingredients.at(0).type);
-331     if (contains_key(Type, base_type)) {  // otherwise we'll raise an error elsewhere
-332       inst.ingredients.at(1).set_value(find_element_offset(base_type, inst.ingredients.at(1).name, get(Recipe, r).name));
-333       trace(9993, "name") << "variant " << inst.ingredients.at(1).name << " of type " << get(Type, base_type).name << " has tag " << no_scientific(inst.ingredients.at(1).value) << end();
-334     }
-335   }
-336 }
-337 
-338 :(scenario missing_type_in_maybe_convert)
-339 % Hide_errors = true;
-340 def main [
-341   maybe-convert a, x:variant
-342 ]
-343 +error: main: missing type for 'a' in 'maybe-convert a, x:variant'
-
- - - -- cgit 1.4.1-2-gfad0