about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-04-16 10:35:49 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-04-16 10:35:49 -0700
commitdb5c9550e972d114aaabb95b14cfd1e3ea185349 (patch)
tree9217134d1154e45f5375f94c9b5788530fbf8cb7
parentd6852155e5308e2bb347402bf9e069c7153c2319 (diff)
downloadmu-db5c9550e972d114aaabb95b14cfd1e3ea185349.tar.gz
1069 - rename record/field to container/element
This seems more obvious to laypeople.

I've also come up with a design for sum types: I'm going to call them
exclusive containers. You call 'get' on containers, 'index' on arrays,
and 'maybe-convert' on exclusive containers (as well as tagged types,
but that's even later).
-rw-r--r--cpp/.traces/convert_names_handles_containers (renamed from cpp/.traces/convert_names_handles_records)0
-rw-r--r--cpp/.traces/convert_names_transforms_container_elements (renamed from cpp/.traces/convert_names_transforms_record_elements)4
-rw-r--r--cpp/.traces/copy_handles_nested_container_elements (renamed from cpp/.traces/copy_handles_nested_record_elements)0
-rw-r--r--cpp/.traces/get_handles_nested_container_elements (renamed from cpp/.traces/get_handles_nested_record_elements)0
-rw-r--r--cpp/.traces/reply_container (renamed from cpp/.traces/reply_record)0
-rw-r--r--cpp/010vm32
-rw-r--r--cpp/018container (renamed from cpp/018record)29
-rw-r--r--cpp/019address4
-rw-r--r--cpp/020array2
-rw-r--r--cpp/023call_reply4
-rw-r--r--cpp/025name32
-rw-r--r--cpp/090debug2
12 files changed, 61 insertions, 48 deletions
diff --git a/cpp/.traces/convert_names_handles_records b/cpp/.traces/convert_names_handles_containers
index 0073519a..0073519a 100644
--- a/cpp/.traces/convert_names_handles_records
+++ b/cpp/.traces/convert_names_handles_containers
diff --git a/cpp/.traces/convert_names_transforms_record_elements b/cpp/.traces/convert_names_transforms_container_elements
index 7711e827..0dd4f7e8 100644
--- a/cpp/.traces/convert_names_transforms_record_elements
+++ b/cpp/.traces/convert_names_transforms_container_elements
@@ -6,9 +6,9 @@ parse/0: instruction: 18
 parse/0:   ingredient: {name: "0", value: 0, type: 6, properties: ["0": "point"]}
 parse/0:   ingredient: {name: "x", value: 0, type: 0, properties: ["x": "offset"]}
 parse/0:   product: {name: "b", value: 0, type: 1, properties: ["b": "integer"]}
-name/0: field y of type point is at offset 1
+name/0: element y of type point is at offset 1
 name/0: assign a 1
-name/0: field x of type point is at offset 0
+name/0: element x of type point is at offset 0
 name/0: assign b 2
 after-brace/0: recipe main
 after-brace/0: get ...
diff --git a/cpp/.traces/copy_handles_nested_record_elements b/cpp/.traces/copy_handles_nested_container_elements
index 8ca9a547..8ca9a547 100644
--- a/cpp/.traces/copy_handles_nested_record_elements
+++ b/cpp/.traces/copy_handles_nested_container_elements
diff --git a/cpp/.traces/get_handles_nested_record_elements b/cpp/.traces/get_handles_nested_container_elements
index 4334fc26..4334fc26 100644
--- a/cpp/.traces/get_handles_nested_record_elements
+++ b/cpp/.traces/get_handles_nested_container_elements
diff --git a/cpp/.traces/reply_record b/cpp/.traces/reply_container
index 1a3541e6..1a3541e6 100644
--- a/cpp/.traces/reply_record
+++ b/cpp/.traces/reply_container
diff --git a/cpp/010vm b/cpp/010vm
index 032e1874..df84102b 100644
--- a/cpp/010vm
+++ b/cpp/010vm
@@ -89,6 +89,8 @@ void setup_types() {
   Type[boolean].name = "boolean";
   int character = Type_number["character"] = Next_type_number++;
   Type[character].name = "character";
+  // Array types are a special modifier to any other type. For example,
+  // array:integer or array:address:boolean.
   int array = Type_number["array"] = Next_type_number++;
   Type[array].name = "array";
   // End Mu Types Initialization
@@ -97,20 +99,30 @@ void setup_types() {
 setup_types();
 
 :(before "End Types")
-// You can construct arbitrary new types. Types are either 'records', containing
-// 'fields' of other types, or 'array's of a single type repeated over and over.
+// You can construct arbitrary new types. New types are either 'containers'
+// with multiple 'elements' of other types, or 'exclusive containers' containing
+// one of multiple 'variants'. (These are similar to C structs and unions,
+// respectively, though exclusive containers implicitly include a tag element
+// recording which variant they should be interpreted as.)
 //
-// For example:
-//  storing bank balance next to a person's name might require a record, and
-//  high scores in a game might need an array of numbers.
+// For example, storing bank balance and name for an account might require a
+// container, but if bank accounts may be either for individuals or groups,
+// with different properties for each, that may require an exclusive container
+// whose variants are individual-account and joint-account containers.
+enum kind_of_type {
+  primitive,
+  container,
+  exclusive_container
+};
+
 struct type_info {
   string name;
-  bool is_record;
-  size_t size;  // only if is_record; primitives and addresses have size 1 while arrays are dynamic
-  vector<vector<type_number> > elements;  // only if is_record
-  vector<string> element_names;  // only if is_record
+  kind_of_type kind;
+  size_t size;  // only if type is not primitive; primitives and addresses have size 1 (except arrays are dynamic)
+  vector<vector<type_number> > elements;
+  vector<string> element_names;
   // End type_info Fields
-  type_info() :is_record(false), size(0) {}
+  type_info() :kind(primitive), size(0) {}
 };
 
 :(before "End Globals")
diff --git a/cpp/018record b/cpp/018container
index 58188813..ef6b0057 100644
--- a/cpp/018record
+++ b/cpp/018container
@@ -1,9 +1,9 @@
-//: Records contain a fixed number of elements of different types.
+//: Containers contain a fixed number of elements of different types.
 :(before "End Mu Types Initialization")
-//: We'll use this record as a running example, with two integer elements
+//: We'll use this container as a running example, with two integer elements.
 int point = Type_number["point"] = Next_type_number++;
 Type[point].size = 2;
-Type[point].is_record = true;
+Type[point].kind = container;
 Type[point].name = "point";
 vector<type_number> i;
 i.push_back(integer);
@@ -11,7 +11,7 @@ Type[point].elements.push_back(i);
 Type[point].elements.push_back(i);
 
 :(scenario copy_multiple_locations)
-# Records can be copied around with a single instruction just like integers,
+# Containers can be copied around with a single instruction just like integers,
 # no matter how large they are.
 recipe main [
   1:integer <- copy 34:literal
@@ -25,10 +25,11 @@ recipe main [
 +mem: storing 35 in location 4
 
 :(before "End Mu Types Initialization")
-// A more complex record, containing another record.
+// A more complex container, containing another container as one of its
+// elements.
 int point_integer = Type_number["point-integer"] = Next_type_number++;
 Type[point_integer].size = 2;
-Type[point_integer].is_record = true;
+Type[point_integer].kind = container;
 Type[point_integer].name = "point-integer";
 vector<type_number> p2;
 p2.push_back(point);
@@ -37,7 +38,7 @@ vector<type_number> i2;
 i2.push_back(integer);
 Type[point_integer].elements.push_back(i2);
 
-:(scenario "copy_handles_nested_record_elements")
+:(scenario "copy_handles_nested_container_elements")
 recipe main [
   12:integer <- copy 34:literal
   13:integer <- copy 35:literal
@@ -48,7 +49,7 @@ recipe main [
 
 :(before "End size_of(types) Cases")
 type_info t = Type[types[0]];
-if (t.is_record) {
+if (t.kind == container) {
   size_t result = 0;
   for (size_t i = 0; i < t.elements.size(); ++i) {
     result += size_of(t.elements[i]);
@@ -56,7 +57,7 @@ if (t.is_record) {
   return result;
 }
 
-//: To access elements of a record, use 'get'
+//: To access elements of a container, use 'get'
 :(scenario "get")
 recipe main [
   12:integer <- copy 34:literal
@@ -84,7 +85,7 @@ case GET: {
   reagent base = instructions[pc].ingredients[0];
   int base_address = base.value;
   int base_type = base.types[0];
-  assert(Type[base_type].is_record);
+  assert(Type[base_type].kind == container);
   trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
   assert(isa_literal(instructions[pc].ingredients[1]));
   size_t offset = instructions[pc].ingredients[1].value;
@@ -93,7 +94,7 @@ case GET: {
     src += size_of(Type[base_type].elements[i]);
   }
   trace("run") << "address to copy is " << src;
-  assert(Type[base_type].is_record);
+  assert(Type[base_type].kind == container);
   assert(Type[base_type].elements.size() > offset);
   int src_type = Type[base_type].elements[offset][0];
   trace("run") << "its type is " << src_type;
@@ -111,7 +112,7 @@ case GET: {
 :(before "End Mu Types Initialization")
 Type_number["offset"] = 0;
 
-:(scenario "get_handles_nested_record_elements")
+:(scenario "get_handles_nested_container_elements")
 recipe main [
   12:integer <- copy 34:literal
   13:integer <- copy 35:literal
@@ -128,7 +129,7 @@ recipe main [
 +mem: storing 36 in location 15
 
 :(before "End Globals")
-// To write to fields of records, you need their address.
+// To write to elements of containers, you need their address.
 const int GET_ADDRESS = 19;
 :(before "End Primitive Recipe Numbers")
 Recipe_number["get-address"] = GET_ADDRESS;
@@ -140,7 +141,7 @@ case GET_ADDRESS: {
   reagent base = instructions[pc].ingredients[0];
   int base_address = base.value;
   int base_type = base.types[0];
-  assert(Type[base_type].is_record);
+  assert(Type[base_type].kind == container);
   trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
   assert(isa_literal(instructions[pc].ingredients[1]));
   size_t offset = instructions[pc].ingredients[1].value;
diff --git a/cpp/019address b/cpp/019address
index 58d852cd..22355fc6 100644
--- a/cpp/019address
+++ b/cpp/019address
@@ -73,7 +73,7 @@ reagent deref(reagent x) {
   return result;
 }
 
-//: 'get' can read from record address
+//: 'get' can read from container address
 :(scenario "get_indirect")
 recipe main [
   1:integer <- copy 2:literal
@@ -102,7 +102,7 @@ recipe main [
 base = canonize(base);
 
 :(scenario "get_address_indirect")
-# 'get' can read from record address
+# 'get' can read from container address
 recipe main [
   1:integer <- copy 2:literal
   2:integer <- copy 34:literal
diff --git a/cpp/020array b/cpp/020array
index 4a84af10..9c2f1439 100644
--- a/cpp/020array
+++ b/cpp/020array
@@ -117,7 +117,7 @@ recipe main [
 +mem: storing 2 in location 5
 
 :(before "End Globals")
-// To write to fields of records, you need their address.
+// To write to elements of containers, you need their address.
 const int INDEX_ADDRESS = 21;
 :(before "End Primitive Recipe Numbers")
 Recipe_number["index-address"] = INDEX_ADDRESS;
diff --git a/cpp/023call_reply b/cpp/023call_reply
index 4c9fe34c..feb549e6 100644
--- a/cpp/023call_reply
+++ b/cpp/023call_reply
@@ -39,8 +39,8 @@ case REPLY: {
   break;
 }
 
-//: Results can include records and arrays.
-:(scenario "reply_record")
+//: Results can include containers and exclusive containers, addresses and arrays.
+:(scenario "reply_container")
 recipe main [
   3:point <- f 2:literal
 ]
diff --git a/cpp/025name b/cpp/025name
index 1c73b16a..375f9854 100644
--- a/cpp/025name
+++ b/cpp/025name
@@ -90,17 +90,17 @@ type_number skip_addresses(const vector<type_number>& types) {
   for (size_t i = 0; i < types.size(); ++i) {
     if (types[i] != Type_number["address"]) return types[i];
   }
-  raise << "expected a record" << '\n' << die();
+  raise << "expected a container" << '\n' << die();
   return -1;
 }
 
 int find_element_name(const type_number t, const string& name) {
-  const type_info& record = Type[t];
-//?   cout << "looking for field " << name << " in type " << record.name << " with " << record.element_names.size() << " fields\n"; //? 1
-  for (size_t i = 0; i < record.element_names.size(); ++i) {
-    if (record.element_names[i] == name) return i;
+  const type_info& container = Type[t];
+//?   cout << "looking for element " << name << " in type " << container.name << " with " << container.element_names.size() << " elements\n"; //? 1
+  for (size_t i = 0; i < container.element_names.size(); ++i) {
+    if (container.element_names[i] == name) return i;
   }
-  raise << "unknown element " << name << " in record " << t << '\n' << die();
+  raise << "unknown element " << name << " in container " << t << '\n' << die();
   return -1;
 }
 
@@ -134,20 +134,20 @@ recipe main [
 ]
 -name: assign x 1
 
-//: update our running example record for the next test
+//: update our running example container for the next test
 :(before "End Mu Types Initialization")
 Type[point].element_names.push_back("x");
 Type[point].element_names.push_back("y");
-:(scenario "convert_names_transforms_record_elements")
+:(scenario "convert_names_transforms_container_elements")
 recipe main [
   a:integer <- get 0:point, y:offset
   b:integer <- get 0:point, x:offset
 ]
-+name: field y of type point is at offset 1
-+name: field x of type point is at offset 0
++name: element y of type point is at offset 1
++name: element x of type point is at offset 0
 
 :(after "Per-recipe Transforms")
-// replace element names of records with offsets
+// replace element names of containers with offsets
 if (inst.operation == Recipe_number["get"]
     || inst.operation == Recipe_number["get-address"]) {
   // at least 2 args, and second arg is offset
@@ -155,15 +155,15 @@ if (inst.operation == Recipe_number["get"]
 //?   cout << inst.ingredients[1].to_string() << '\n'; //? 1
   assert(isa_literal(inst.ingredients[1]));
   if (inst.ingredients[1].name.find_first_not_of("0123456789") == string::npos) continue;
-  // since first non-address in base type must be a record, we don't have to canonize
-  type_number record = skip_addresses(inst.ingredients[0].types);
-  inst.ingredients[1].set_value(find_element_name(record, inst.ingredients[1].name));
-  trace("name") << "field " << inst.ingredients[1].name << " of type " << Type[record].name << " is at offset " << inst.ingredients[1].value;
+  // since first non-address in base type must be a container, we don't have to canonize
+  type_number container = skip_addresses(inst.ingredients[0].types);
+  inst.ingredients[1].set_value(find_element_name(container, inst.ingredients[1].name));
+  trace("name") << "element " << inst.ingredients[1].name << " of type " << Type[container].name << " is at offset " << inst.ingredients[1].value;
 }
 
 //: this test is actually illegal so can't call run
 :(scenarios transform_test)
-:(scenario "convert_names_handles_records")
+:(scenario "convert_names_handles_containers")
 recipe main [
   a:point <- copy 0:literal
   b:integer <- copy 0:literal
diff --git a/cpp/090debug b/cpp/090debug
index a2a74d18..670b284f 100644
--- a/cpp/090debug
+++ b/cpp/090debug
@@ -1,5 +1,5 @@
 :(before "End Globals")
-// Operator to look at fields of records.
+// Operator to look at elements of containers.
 const int _PRINT = 99;
 :(before "End Primitive Recipe Numbers")
 Recipe_number["$print"] = _PRINT;