about summary refs log tree commit diff stats
path: root/058generic_container.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-10-30 13:00:16 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-10-30 13:00:16 -0700
commite3cb4d0905bdfb1c0b9d520c9c0089cffc09e339 (patch)
tree19f1776957ee763be6718771d05f1e2fce95d3e2 /058generic_container.cc
parent3a49e7e992b23d212b0c1df9e93c6564d4823ef2 (diff)
downloadmu-e3cb4d0905bdfb1c0b9d520c9c0089cffc09e339.tar.gz
2329 - hacky start to generic containers
Diffstat (limited to '058generic_container.cc')
-rw-r--r--058generic_container.cc99
1 files changed, 99 insertions, 0 deletions
diff --git a/058generic_container.cc b/058generic_container.cc
new file mode 100644
index 00000000..75b2188d
--- /dev/null
+++ b/058generic_container.cc
@@ -0,0 +1,99 @@
+//:: Container definitions can contain type parameters.
+//:
+//: Extremely hacky initial implementation:
+//:
+//: a) We still don't support the full complexity of type trees inside
+//: container definitions. So for example you can't have a container element
+//: with this type:
+//:   (map (array address character) (list number))
+//:
+//: b) We also can't include type parameters anywhere except at the top of the
+//: type of a container element.
+
+:(scenario size_of_generic_container)
+container foo:_t [
+  x:_t
+  y:number
+]
+recipe main [
+  1:foo:number <- merge 12, 13
+  3:foo:point <- merge 14, 15, 16
+]
++mem: storing 12 in location 1
++mem: storing 13 in location 2
++mem: storing 14 in location 3
++mem: storing 15 in location 4
++mem: storing 16 in location 5
+
+:(before "End Globals")
+// We'll use large type ordinals to mean "the following type of the variable".
+const int START_TYPE_INGREDIENTS = 2000;
+:(before "End Test Run Initialization")
+assert(Next_type_ordinal < START_TYPE_INGREDIENTS);
+
+:(before "End type_info Fields")
+map<string, type_ordinal> type_ingredient_names;
+
+:(before "End container Name Refinements")
+if (name.find(':') != string::npos) {
+  trace(9999, "parse") << "container has type ingredients; parsing" << end();
+  read_type_ingredients(name);
+}
+
+:(code)
+void read_type_ingredients(string& name) {
+  string save_name = name;
+  istringstream in(save_name);
+  name = slurp_until(in, ':');
+  if (Type_ordinal.find(name) == Type_ordinal.end() || Type_ordinal[name] == 0)
+    Type_ordinal[name] = Next_type_ordinal++;
+  type_info& info = Type[Type_ordinal[name]];
+  long long int next_type_ordinal = START_TYPE_INGREDIENTS;
+  while (!in.eof()) {
+    string curr = slurp_until(in, ':');
+    if (info.type_ingredient_names.find(curr) != info.type_ingredient_names.end()) {
+      raise_error << "can't repeat type ingredient names in a single container definition\n" << end();
+      return;
+    }
+    info.type_ingredient_names[curr] = next_type_ordinal++;
+  }
+}
+
+:(before "End insert_container Special Uses(type_name)")
+// check for use of type ingredients
+if (type_name.at(0) == '_') {
+  *curr_type = new type_tree(info.type_ingredient_names[type_name]);
+  trace(9999, "parse") << "  type: " << info.type_ingredient_names[type_name] << end();
+  continue;
+}
+
+:(before "End Container Type Checks")
+if (type->value >= START_TYPE_INGREDIENTS
+    && (type->value - START_TYPE_INGREDIENTS) < SIZE(Type[type->value].type_ingredient_names))
+  return;
+
+:(before "End size_of(type) Container Cases")
+if (t.elements.at(i)->value >= START_TYPE_INGREDIENTS) {
+  trace(9999, "type") << "checking size of type ingredient\n";
+  result += size_of_type_ingredient(t.elements.at(i)->value - START_TYPE_INGREDIENTS,
+                                    type->right);
+  continue;
+}
+
+:(code)
+// generic version of size_of
+long long int size_of_type_ingredient(long long int type_ingredient_index, const type_tree* rest_of_type) {
+  const type_tree* curr = rest_of_type;
+  while (type_ingredient_index > 0) {
+    assert(curr);
+    --type_ingredient_index;
+    curr = curr->right;
+  }
+  assert(curr);
+  assert(!curr->left);  // unimplemented
+  trace(9999, "type") << "type deduced to be " << Type[curr->value].name << "$\n";
+  type_tree tmp(curr->value);
+  if (curr->right)
+    tmp.right = new type_tree(*curr->right);
+  return size_of(&tmp);
+}