about summary refs log tree commit diff stats
path: root/cpp/014types
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-04-17 19:48:04 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-04-17 20:01:08 -0700
commit7f931ef0f27f2815ca435bd63f3aa77329c2f096 (patch)
treef8d5643e54094315927083a9159de1c9bcb05906 /cpp/014types
parentcaec3c16d0b0ae0568aa2b6de16510cc8fb89bb2 (diff)
downloadmu-7f931ef0f27f2815ca435bd63f3aa77329c2f096.tar.gz
1087 - mu files can now define containers and exclusive containers
Diffstat (limited to 'cpp/014types')
-rw-r--r--cpp/014types89
1 files changed, 89 insertions, 0 deletions
diff --git a/cpp/014types b/cpp/014types
new file mode 100644
index 00000000..867cb28d
--- /dev/null
+++ b/cpp/014types
@@ -0,0 +1,89 @@
+//: Textual form for types.
+
+:(scenario "container")
+container foo [
+  x:integer
+  y:integer
+]
++parse: reading container foo
++parse:   element name: x
++parse:   type: 1
++parse:   element name: y
++parse:   type: 1
+
+:(before "End Command Handlers")
+else if (command == "container") {
+  insert_container(command, container, in);
+}
+
+:(code)
+void insert_container(const string& command, kind_of_type kind, istream& in) {
+  skip_whitespace(in);
+  string name = next_word(in);
+  trace("parse") << "reading " << command << ' ' << name;
+//?   cout << name << '\n'; //? 1
+  assert(Type_number.find(name) == Type_number.end());
+  Type_number[name] = Next_type_number++;
+  skip_bracket(in, "'container' must begin with '['");
+  assert(Type.find(Type_number[name]) == Type.end());
+  type_info& t = Type[Type_number[name]];
+  recently_added_types.push_back(Type_number[name]);
+  t.name = name;
+  t.kind = kind;
+  while (!in.eof()) {
+    skip_comments_and_newlines(in);
+    skip_whitespace(in);
+    string element = next_word(in);
+    skip_comments_and_newlines(in);
+    if (element == "]") break;
+    istringstream inner(element);
+    t.element_names.push_back(slurp_until(inner, ':'));
+    trace("parse") << "  element name: " << t.element_names.back();
+    vector<type_number> types;
+    while (!inner.eof()) {
+      string type_name = slurp_until(inner, ':');
+      if (Type_number.find(type_name) == Type_number.end())
+        raise << "unknown type " << type_name << '\n';
+      types.push_back(Type_number[type_name]);
+      trace("parse") << "  type: " << types.back();
+    }
+    t.elements.push_back(types);
+  }
+  assert(t.elements.size() == t.element_names.size());
+  t.size = t.elements.size();
+}
+
+//: Similarly for exclusive_container.
+
+:(scenario "exclusive_container")
+exclusive-container foo [
+  x:integer
+  y:integer
+]
++parse: reading exclusive-container foo
++parse:   element name: x
++parse:   type: 1
++parse:   element name: y
++parse:   type: 1
+
+:(before "End Command Handlers")
+else if (command == "exclusive-container") {
+  insert_container(command, exclusive_container, in);
+}
+
+//: ensure types created in one scenario don't leak outside it.
+:(before "End Globals")
+vector<type_number> recently_added_types;
+:(before "End Setup")
+for (size_t i = 0; i < recently_added_types.size(); ++i) {
+//?   cout << "erasing " << Type[recently_added_types[i]].name << '\n'; //? 1
+  Type_number.erase(Type[recently_added_types[i]].name);
+  Type.erase(recently_added_types[i]);
+}
+recently_added_types.clear();
+Next_type_number = 1000;
+:(before "End One-time Setup")
+assert(Next_type_number < 1000);
+Next_type_number = 1000;
+
+//: lastly, ensure scenarios are consistent by always starting