diff options
-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/010vm | 32 | ||||
-rw-r--r-- | cpp/018container (renamed from cpp/018record) | 29 | ||||
-rw-r--r-- | cpp/019address | 4 | ||||
-rw-r--r-- | cpp/020array | 2 | ||||
-rw-r--r-- | cpp/023call_reply | 4 | ||||
-rw-r--r-- | cpp/025name | 32 | ||||
-rw-r--r-- | cpp/090debug | 2 |
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; |