about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-02-17 10:09:48 -0800
committerKartik K. Agaram <vc@akkartik.com>2016-02-17 10:09:48 -0800
commit3adc9e08715fb695b8a7f53d5cfb3db1bd434b05 (patch)
tree2336287ac111e0038fd01391ea9d4c57fe9a3f2b
parent89500176d9ff86eedcc99c2d2d11b1ac96022c97 (diff)
downloadmu-3adc9e08715fb695b8a7f53d5cfb3db1bd434b05.tar.gz
2667 - redo container data structure
I've been gradually Greenspunning reagents. Just go all the way.
-rw-r--r--010vm.cc10
-rw-r--r--030container.cc74
-rw-r--r--032array.cc19
-rw-r--r--033exclusive_container.cc20
-rw-r--r--042name.cc5
-rw-r--r--058shape_shifting_container.cc12
-rw-r--r--077hash.cc2
7 files changed, 57 insertions, 85 deletions
diff --git a/010vm.cc b/010vm.cc
index 758d8d26..970b88c5 100644
--- a/010vm.cc
+++ b/010vm.cc
@@ -148,10 +148,8 @@ void setup_types() {
 }
 void teardown_types() {
   for (map<type_ordinal, type_info>::iterator p = Type.begin(); p != Type.end(); ++p) {
-    for (long long int i = 0; i < SIZE(p->second.elements); ++i) {
-      delete p->second.elements.at(i);
-      delete p->second.element_type_names.at(i);
-    }
+    for (long long int i = 0; i < SIZE(p->second.elements); ++i)
+      p->second.elements.clear();
   }
   Type_ordinal.clear();
 }
@@ -180,9 +178,7 @@ struct type_info {
   string name;
   kind_of_type kind;
   long long int size;  // only if type is not primitive; primitives and addresses have size 1 (except arrays are dynamic)
-  vector<type_tree*> elements;
-  vector<string_tree*> element_type_names;
-  vector<string> element_names;
+  vector<reagent> elements;
   // End type_info Fields
   type_info() :kind(PRIMITIVE), size(0) {}
 };
diff --git a/030container.cc b/030container.cc
index ca5b1080..d4ccf32c 100644
--- a/030container.cc
+++ b/030container.cc
@@ -6,12 +6,8 @@ type_ordinal point = put(Type_ordinal, "point", Next_type_ordinal++);
 get_or_insert(Type, point).size = 2;
 get(Type, point).kind = CONTAINER;
 get(Type, point).name = "point";
-get(Type, point).element_type_names.push_back(new string_tree("number"));
-get(Type, point).elements.push_back(new type_tree(number));
-get(Type, point).element_names.push_back("x");
-get(Type, point).element_type_names.push_back(new string_tree("number"));
-get(Type, point).elements.push_back(new type_tree(number));
-get(Type, point).element_names.push_back("y");
+get(Type, point).elements.push_back(reagent("x:number"));
+get(Type, point).elements.push_back(reagent("y:number"));
 
 //: Containers can be copied around with a single instruction just like
 //: numbers, no matter how large they are.
@@ -43,12 +39,8 @@ type_ordinal point_number = put(Type_ordinal, "point-number", Next_type_ordinal+
 get_or_insert(Type, point_number).size = 2;
 get(Type, point_number).kind = CONTAINER;
 get(Type, point_number).name = "point-number";
-get(Type, point_number).elements.push_back(new type_tree(point));
-get(Type, point_number).element_type_names.push_back(new string_tree("point"));
-get(Type, point_number).element_names.push_back("xy");
-get(Type, point_number).elements.push_back(new type_tree(number));
-get(Type, point_number).element_type_names.push_back(new string_tree("number"));
-get(Type, point_number).element_names.push_back("z");
+get(Type, point_number).elements.push_back(reagent("xy:point"));
+get(Type, point_number).elements.push_back(reagent("z:number"));
 
 :(scenario copy_handles_nested_container_elements)
 recipe main [
@@ -101,12 +93,12 @@ if (t.kind == CONTAINER) {
   long long int result = 0;
   for (long long int i = 0; i < SIZE(t.elements); ++i) {
     // todo: strengthen assertion to disallow mutual type recursion
-    if (t.elements.at(i)->value == type->value) {
+    if (t.elements.at(i).type->value == type->value) {
       raise_error << "container " << t.name << " can't include itself as a member\n" << end();
       return 0;
     }
     // End size_of(type) Container Cases
-    result += size_of(t.elements.at(i));
+    result += size_of(t.elements.at(i).type);
   }
   return result;
 }
@@ -185,7 +177,7 @@ case GET: {
   long long int src = base_address;
   for (long long int i = 0; i < offset; ++i) {
     // End GET field Cases
-    src += size_of(get(Type, base_type).elements.at(i));
+    src += size_of(get(Type, base_type).elements.at(i).type);
   }
   trace(9998, "run") << "address to copy is " << src << end();
   reagent tmp = element_type(base, offset);
@@ -202,11 +194,7 @@ const reagent element_type(const reagent& canonized_base, long long int offset_v
   assert(!get(Type, canonized_base.type->value).name.empty());
   const type_info& info = get(Type, canonized_base.type->value);
   assert(info.kind == CONTAINER);
-  reagent element;
-  element.name = info.element_names.at(offset_value);
-  element.type = new type_tree(*info.elements.at(offset_value));
-  element.properties.resize(1);
-  element.properties.at(0).second = new string_tree(*info.element_type_names.at(offset_value));
+  reagent element = info.elements.at(offset_value);
   // End element_type Special-cases
   return element;
 }
@@ -330,7 +318,7 @@ case GET_ADDRESS: {
   long long int result = base_address;
   for (long long int i = 0; i < offset; ++i) {
     // End GET_ADDRESS field Cases
-    result += size_of(get(Type, base_type).elements.at(i));
+    result += size_of(get(Type, base_type).elements.at(i).type);
   }
   trace(9998, "run") << "address to copy is " << result << end();
   products.resize(1);
@@ -380,10 +368,8 @@ container foo [
   y:number
 ]
 +parse: --- defining container foo
-+parse: element name: x
-+parse: type: 1
-+parse: element name: y
-+parse: type: 1
++parse: element: x: number -- {"x": "number"}
++parse: element: y: number -- {"y": "number"}
 
 :(scenario container_use_before_definition)
 container foo [
@@ -397,12 +383,15 @@ container bar [
 ]
 +parse: --- defining container foo
 +parse: type number: 1000
-+parse:   element name: x
-+parse:   type: 1
-+parse:   element name: y
-+parse:   type: 1001
++parse:   element: x: number -- {"x": "number"}
+# todo: brittle
+# type bar is unknown at this point, but we assign it a number
++parse:   element: y: ?1001 -- {"y": "bar"}
+# later type bar gets a definition
 +parse: --- defining container bar
 +parse: type number: 1001
++parse:   element: x: number -- {"x": "number"}
++parse:   element: y: number -- {"y": "number"}
 
 :(before "End Command Handlers")
 else if (command == "container") {
@@ -429,16 +418,13 @@ void insert_container(const string& command, kind_of_type kind, istream& in) {
     skip_whitespace_and_comments(in);
     string element = next_word(in);
     if (element == "]") break;
-    istringstream inner(element);
-    info.element_names.push_back(slurp_until(inner, ':'));
-    trace(9993, "parse") << "  element name: " << info.element_names.back() << end();
-    info.element_type_names.push_back(parse_property_list(inner));
-    info.elements.push_back(new_type_tree_with_new_types_for_unknown(info.element_type_names.back(), info));
-    for (long long int i = 0; i < SIZE(info.elements); ++i)
-      trace(9993, "parse") << "  type: " << info.elements.at(i)->value << end();
+    info.elements.push_back(reagent(element));
+    // handle undefined types
+    delete info.elements.back().type;
+    info.elements.back().type = new_type_tree_with_new_types_for_unknown(info.elements.back().properties.at(0).second, info);
+    trace(9993, "parse") << "  element: " << debug_string(info.elements.back()) << end();
     // End Load Container Element Definition
   }
-  assert(SIZE(info.elements) == SIZE(info.element_names));
   info.size = SIZE(info.elements);
 }
 
@@ -499,10 +485,8 @@ for (long long int i = 0; i < SIZE(Recently_added_types); ++i) {
   if (!contains_key(Type, Recently_added_types.at(i))) continue;
   Type_ordinal.erase(get(Type, Recently_added_types.at(i)).name);
   // todo: why do I explicitly need to provide this?
-  for (long long int j = 0; j < SIZE(Type.at(Recently_added_types.at(i)).elements); ++j) {
-    delete Type.at(Recently_added_types.at(i)).elements.at(j);
-    delete Type.at(Recently_added_types.at(i)).element_type_names.at(j);
-  }
+  for (long long int j = 0; j < SIZE(Type.at(Recently_added_types.at(i)).elements); ++j)
+    Type.at(Recently_added_types.at(i)).elements.at(j).clear();
   Type.erase(Recently_added_types.at(i));
 }
 Recently_added_types.clear();
@@ -603,10 +587,8 @@ container foo [
   y:number
 ]
 +parse: --- defining container foo
-+parse: element name: x
-+parse: type: 1
-+parse: element name: y
-+parse: type: 1
++parse: element: x: number -- {"x": "number"}
++parse: element: y: number -- {"y": "number"}
 
 :(before "End Transform All")
 check_container_field_types();
@@ -617,7 +599,7 @@ void check_container_field_types() {
     const type_info& info = p->second;
     // Check Container Field Types(info)
     for (long long int i = 0; i < SIZE(info.elements); ++i)
-      check_invalid_types(info.elements.at(i), maybe(info.name), info.element_names.at(i));
+      check_invalid_types(info.elements.at(i).type, maybe(info.name), info.elements.at(i).name);
   }
 }
 
diff --git a/032array.cc b/032array.cc
index aace0a5a..b558d98f 100644
--- a/032array.cc
+++ b/032array.cc
@@ -134,14 +134,17 @@ container foo [
 +error: container 'foo' cannot determine size of element x
 
 :(before "End Load Container Element Definition")
-if (info.element_type_names.back()->value == "array") {
-  if (!info.element_type_names.back()->right) {
-    raise_error << "container '" << name << "' doesn't specify type of array elements for " << info.element_names.back() << '\n' << end();
-    continue;
-  }
-  if (!info.element_type_names.back()->right->right) {  // array has no length
-    raise_error << "container '" << name << "' cannot determine size of element " << info.element_names.back() << '\n' << end();
-    continue;
+{
+  const string_tree* type_name = info.elements.back().properties.at(0).second;
+  if (type_name->value == "array") {
+    if (!type_name->right) {
+      raise_error << "container '" << name << "' doesn't specify type of array elements for " << info.elements.back().name << '\n' << end();
+      continue;
+    }
+    if (!type_name->right->right) {  // array has no length
+      raise_error << "container '" << name << "' cannot determine size of element " << info.elements.back().name << '\n' << end();
+      continue;
+    }
   }
 }
 
diff --git a/033exclusive_container.cc b/033exclusive_container.cc
index 3b1dc201..26169637 100644
--- a/033exclusive_container.cc
+++ b/033exclusive_container.cc
@@ -11,12 +11,8 @@ type_ordinal tmp = put(Type_ordinal, "number-or-point", Next_type_ordinal++);
 get_or_insert(Type, tmp).size = 2;
 get(Type, tmp).kind = EXCLUSIVE_CONTAINER;
 get(Type, tmp).name = "number-or-point";
-get(Type, tmp).element_type_names.push_back(new string_tree("number"));
-get(Type, tmp).elements.push_back(new type_tree(number));
-get(Type, tmp).element_names.push_back("i");
-get(Type, tmp).element_type_names.push_back(new string_tree("point"));
-get(Type, tmp).elements.push_back(new type_tree(point));
-get(Type, tmp).element_names.push_back("p");
+get(Type, tmp).elements.push_back(reagent("i:number"));
+get(Type, tmp).elements.push_back(reagent("p:point"));
 }
 
 //: Tests in this layer often explicitly setup memory before reading it as an
@@ -41,7 +37,7 @@ if (t.kind == EXCLUSIVE_CONTAINER) {
   long long int result = 0;
   for (long long int i = 0; i < t.size; ++i) {
     // End size_of(type) Exclusive Container Cases
-    long long int size = size_of(t.elements.at(i));
+    long long int size = size_of(t.elements.at(i).type);
     if (size > result) result = size;
   }
   // ...+1 for its tag.
@@ -143,9 +139,7 @@ const reagent variant_type(const reagent& canonized_base, long long int tag) {
   assert(!get(Type, canonized_base.type->value).name.empty());
   const type_info& info = get(Type, canonized_base.type->value);
   assert(info.kind == EXCLUSIVE_CONTAINER);
-  reagent element;
-  element.type = new type_tree(*info.elements.at(tag));
-  element.properties.at(0).second = new string_tree(*info.element_type_names.at(tag));
+  reagent element = info.elements.at(tag);
   // End variant_type Special-cases
   return element;
 }
@@ -169,10 +163,8 @@ exclusive-container foo [
   y:number
 ]
 +parse: --- defining exclusive-container foo
-+parse:   element name: x
-+parse:   type: 1
-+parse:   element name: y
-+parse:   type: 1
++parse: element: x: number -- {"x": "number"}
++parse: element: y: number -- {"y": "number"}
 
 :(before "End Command Handlers")
 else if (command == "exclusive-container") {
diff --git a/042name.cc b/042name.cc
index a8268b4a..bdaf50e9 100644
--- a/042name.cc
+++ b/042name.cc
@@ -104,9 +104,8 @@ type_ordinal skip_addresses(type_tree* type, const string& recipe_name) {
 
 int find_element_name(const type_ordinal t, const string& name, const string& recipe_name) {
   const type_info& container = get(Type, t);
-  for (long long int i = 0; i < SIZE(container.element_names); ++i) {
-    if (container.element_names.at(i) == name) return i;
-  }
+  for (long long int i = 0; i < SIZE(container.elements); ++i)
+    if (container.elements.at(i).name == name) return i;
   raise_error << maybe(recipe_name) << "unknown element " << name << " in container " << get(Type, t).name << '\n' << end();
   return -1;
 }
diff --git a/058shape_shifting_container.cc b/058shape_shifting_container.cc
index e4822cc0..476468b7 100644
--- a/058shape_shifting_container.cc
+++ b/058shape_shifting_container.cc
@@ -71,9 +71,9 @@ if (type->value >= START_TYPE_INGREDIENTS
   return;
 
 :(before "End size_of(type) Container Cases")
-if (t.elements.at(i)->value >= START_TYPE_INGREDIENTS) {
+if (t.elements.at(i).type->value >= START_TYPE_INGREDIENTS) {
   trace(9999, "type") << "checking size of type ingredient\n" << end();
-  long long int size = size_of_type_ingredient(t.elements.at(i), type->right);
+  long long int size = size_of_type_ingredient(t.elements.at(i).type, type->right);
   if (!size)
     raise_error << "illegal type '" << debug_string(type) << "' seems to be missing a type ingredient or three\n" << end();
   result += size;
@@ -100,9 +100,9 @@ recipe main [
 $mem: 7
 
 :(before "End size_of(type) Exclusive Container Cases")
-if (t.elements.at(i)->value >= START_TYPE_INGREDIENTS) {
+if (t.elements.at(i).type->value >= START_TYPE_INGREDIENTS) {
   trace(9999, "type") << "checking size of type ingredient\n" << end();
-  long long int size = size_of_type_ingredient(t.elements.at(i), type->right);
+  long long int size = size_of_type_ingredient(t.elements.at(i).type, type->right);
   if (!size)
     raise_error << "illegal type '" << debug_string(type) << "' seems to be missing a type ingredient or three\n" << end();
   if (size > result) result = size;
@@ -147,7 +147,7 @@ recipe main [
 +mem: storing 16 in location 2
 
 :(before "End GET field Cases")
-const type_tree* type = get(Type, base_type).elements.at(i);
+const type_tree* type = get(Type, base_type).elements.at(i).type;
 if (type->value >= START_TYPE_INGREDIENTS) {
   long long int size = size_of_type_ingredient(type, base.type->right);
   if (!size)
@@ -267,7 +267,7 @@ recipe main [
 +mem: storing 12 in location 1
 
 :(before "End GET_ADDRESS field Cases")
-const type_tree* type = get(Type, base_type).elements.at(i);
+const type_tree* type = get(Type, base_type).elements.at(i).type;
 if (type->value >= START_TYPE_INGREDIENTS) {
   long long int size = size_of_type_ingredient(type, base.type->right);
   if (!size)
diff --git a/077hash.cc b/077hash.cc
index ea185cfa..f2cc403d 100644
--- a/077hash.cc
+++ b/077hash.cc
@@ -104,7 +104,7 @@ size_t hash_mu_container(size_t h, const reagent& r) {
     element.set_value(address+offset);
     h = hash(h, element);
 //?     cerr << i << ": " << h << '\n';
-    offset += size_of(info.elements.at(i));
+    offset += size_of(info.elements.at(i).type);
   }
   return h;
 }