about summary refs log tree commit diff stats
path: root/058shape_shifting_container.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-02-21 20:30:02 -0800
committerKartik K. Agaram <vc@akkartik.com>2016-02-21 20:40:06 -0800
commitc4e143d6ea0635cdb164cec1c62afd7461e605ad (patch)
tree06fbb672ce95f1d5152c113cdb40685148b57d0c /058shape_shifting_container.cc
parentf22250a174d5ad5abf8bf99ad140ced52563aee2 (diff)
downloadmu-c4e143d6ea0635cdb164cec1c62afd7461e605ad.tar.gz
2681 - drop reagent types from reagent properties
All my attempts at staging this change failed with this humongous commit
that took all day and involved debugging three monstrous bugs. Two of
the bugs had to do with forgetting to check the type name in the
implementation of shape-shifting recipes. Bug #2 in particular would
cause core tests in layer 59 to fail -- only when I loaded up edit/! It
got me to just hack directly on mu.cc until I figured out the cause
(snapshot saved in mu.cc.modified). The problem turned out to be that I
accidentally saved a type ingredient in the Type table during
specialization. Now I know that that can be very bad.

I've checked the traces for any stray type numbers (rather than names).

I also found what might be a bug from last November (labeled TODO), but
we'll verify after this commit.
Diffstat (limited to '058shape_shifting_container.cc')
-rw-r--r--058shape_shifting_container.cc53
1 files changed, 20 insertions, 33 deletions
diff --git a/058shape_shifting_container.cc b/058shape_shifting_container.cc
index 33b81333..74f97016 100644
--- a/058shape_shifting_container.cc
+++ b/058shape_shifting_container.cc
@@ -97,14 +97,24 @@ void read_type_ingredients(string& name) {
 
 :(before "End insert_container Special-cases")
 // check for use of type ingredients
-else if (!properties->value.empty() && properties->value.at(0) == '_') {
-  result->value = get(info.type_ingredient_names, properties->value);
+else if (is_type_ingredient_name(type->name)) {
+  type->value = get(info.type_ingredient_names, type->name);
+}
+:(code)
+bool is_type_ingredient_name(const string& type) {
+  return !type.empty() && type.at(0) == '_';
 }
 
 :(before "End Container Type Checks")
 if (type->value >= START_TYPE_INGREDIENTS
     && (type->value - START_TYPE_INGREDIENTS) < SIZE(get(Type, type->value).type_ingredient_names))
   return;
+:(code)
+//? //: TODO: is this necessary?
+//? :(before "End Container Type Checks2")
+//? if (type->value >= START_TYPE_INGREDIENTS
+//?     && (type->value - START_TYPE_INGREDIENTS) < SIZE(get(Type, type->value).type_ingredient_names))
+//?   return;
 
 :(scenario size_of_shape_shifting_exclusive_container)
 exclusive-container foo:_t [
@@ -226,8 +236,8 @@ recipe main [
 :(before "End element_type Special-cases")
 if (contains_type_ingredient(element)) {
   if (!canonized_base.type->right)
-    raise_error << "illegal type '" << to_string(canonized_base.type) << "' seems to be missing a type ingredient or three\n" << end();
-  replace_type_ingredients(element.type, element.properties.at(0).second, canonized_base.type->right, canonized_base.properties.at(0).second ? canonized_base.properties.at(0).second->right : NULL, info);
+    raise_error << "illegal type " << names_to_string(canonized_base.type) << " seems to be missing a type ingredient or three\n" << end();
+  replace_type_ingredients(element.type, canonized_base.type->right, info);
 }
 
 :(code)
@@ -242,23 +252,22 @@ bool contains_type_ingredient(const type_tree* type) {
 }
 
 // todo: too complicated and likely incomplete; maybe avoid replacing in place? Maybe process element_type and element_type_name in separate functions?
-void replace_type_ingredients(type_tree* element_type, string_tree* element_type_name, const type_tree* callsite_type, const string_tree* callsite_type_name, const type_info& container_info) {
+void replace_type_ingredients(type_tree* element_type, const type_tree* callsite_type, const type_info& container_info) {
   if (!callsite_type) return;  // error but it's already been raised above
   if (!element_type) return;
 
   // A. recurse first to avoid nested replaces (which I can't reason about yet)
-  replace_type_ingredients(element_type->left, element_type_name ? element_type_name->left : NULL, callsite_type, callsite_type_name, container_info);
-  replace_type_ingredients(element_type->right, element_type_name ? element_type_name->right : NULL, callsite_type, callsite_type_name, container_info);
+  replace_type_ingredients(element_type->left, callsite_type, container_info);
+  replace_type_ingredients(element_type->right, callsite_type, container_info);
   if (element_type->value < START_TYPE_INGREDIENTS) return;
 
   const long long int type_ingredient_index = element_type->value-START_TYPE_INGREDIENTS;
   if (!has_nth_type(callsite_type, type_ingredient_index)) {
-    raise_error << "illegal type '" << to_string(callsite_type) << "' seems to be missing a type ingredient or three\n" << end();
+    raise_error << "illegal type " << names_to_string(callsite_type) << " seems to be missing a type ingredient or three\n" << end();
     return;
   }
 
   // B. replace the current location
-  // B1. update value/left/right of element_type
   const type_tree* replacement = NULL;
   bool splice_right = true ;
   {
@@ -287,28 +296,6 @@ void replace_type_ingredients(type_tree* element_type, string_tree* element_type
     element_type->right = replacement->right ? new type_tree(*replacement->right) : NULL;
     append(element_type->right, old_right);
   }
-
-  // B2. update value/left/right of element_type_name
-  if (!callsite_type_name || !element_type_name) return;
-  const string_tree* replacement_name = NULL;
-  // could compute splice_right again here, but why bother
-  {
-    const string_tree* curr = callsite_type_name;
-    for (long long int i = 0; i < type_ingredient_index; ++i)
-      curr = curr->right;
-    if (curr && curr->left)
-      replacement_name = curr->left;
-    else
-      replacement_name = curr;
-  }
-  element_type_name->value = replacement_name->value;
-  assert(!element_type_name->left);  // since value is set
-  element_type_name->left = replacement_name->left ? new string_tree(*replacement_name->left) : NULL;
-  if (splice_right) {
-    string_tree* old_right = element_type_name->right;
-    element_type_name->right = replacement_name->right ? new string_tree(*replacement_name->right) : NULL;
-    append(element_type_name->right, old_right);
-  }
 }
 
 bool final_type_ingredient(long long int type_ingredient_index, const type_info& container_info) {
@@ -464,7 +451,7 @@ recipe main [
   10:foo:point <- merge 14, 15, 16
   1:number <- get 10:foo, 1:offset
 ]
-+error: illegal type 'foo' seems to be missing a type ingredient or three
++error: illegal type "foo" seems to be missing a type ingredient or three
 
 //: get-address similarly
 
@@ -576,5 +563,5 @@ recipe main [
 if (contains_type_ingredient(element)) {
   if (!canonized_base.type->right)
     raise_error << "illegal type '" << to_string(canonized_base.type) << "' seems to be missing a type ingredient or three\n" << end();
-  replace_type_ingredients(element.type, element.properties.at(0).second, canonized_base.type->right, canonized_base.properties.at(0).second ? canonized_base.properties.at(0).second->right : NULL, info);
+  replace_type_ingredients(element.type, canonized_base.type->right, info);
 }