From db5c9550e972d114aaabb95b14cfd1e3ea185349 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Thu, 16 Apr 2015 10:35:49 -0700 Subject: 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). --- cpp/.traces/convert_names_handles_containers | 11 ++ cpp/.traces/convert_names_handles_records | 11 -- .../convert_names_transforms_container_elements | 31 ++++ .../convert_names_transforms_record_elements | 31 ---- cpp/.traces/copy_handles_nested_container_elements | 34 +++++ cpp/.traces/copy_handles_nested_record_elements | 34 ----- cpp/.traces/get_handles_nested_container_elements | 35 +++++ cpp/.traces/get_handles_nested_record_elements | 35 ----- cpp/.traces/reply_container | 29 ++++ cpp/.traces/reply_record | 29 ---- cpp/010vm | 32 ++-- cpp/018container | 170 +++++++++++++++++++++ cpp/018record | 169 -------------------- cpp/019address | 4 +- cpp/020array | 2 +- cpp/023call_reply | 4 +- cpp/025name | 32 ++-- cpp/090debug | 2 +- 18 files changed, 354 insertions(+), 341 deletions(-) create mode 100644 cpp/.traces/convert_names_handles_containers delete mode 100644 cpp/.traces/convert_names_handles_records create mode 100644 cpp/.traces/convert_names_transforms_container_elements delete mode 100644 cpp/.traces/convert_names_transforms_record_elements create mode 100644 cpp/.traces/copy_handles_nested_container_elements delete mode 100644 cpp/.traces/copy_handles_nested_record_elements create mode 100644 cpp/.traces/get_handles_nested_container_elements delete mode 100644 cpp/.traces/get_handles_nested_record_elements create mode 100644 cpp/.traces/reply_container delete mode 100644 cpp/.traces/reply_record create mode 100644 cpp/018container delete mode 100644 cpp/018record (limited to 'cpp') diff --git a/cpp/.traces/convert_names_handles_containers b/cpp/.traces/convert_names_handles_containers new file mode 100644 index 00000000..0073519a --- /dev/null +++ b/cpp/.traces/convert_names_handles_containers @@ -0,0 +1,11 @@ +parse/0: instruction: 1 +parse/0: ingredient: {name: "0", value: 0, type: 0, properties: ["0": "literal"]} +parse/0: product: {name: "a", value: 0, type: 6, properties: ["a": "point"]} +parse/0: instruction: 1 +parse/0: ingredient: {name: "0", value: 0, type: 0, properties: ["0": "literal"]} +parse/0: product: {name: "b", value: 0, type: 1, properties: ["b": "integer"]} +name/0: assign a 1 +name/0: assign b 3 +after-brace/0: recipe main +after-brace/0: copy ... +after-brace/0: copy ... diff --git a/cpp/.traces/convert_names_handles_records b/cpp/.traces/convert_names_handles_records deleted file mode 100644 index 0073519a..00000000 --- a/cpp/.traces/convert_names_handles_records +++ /dev/null @@ -1,11 +0,0 @@ -parse/0: instruction: 1 -parse/0: ingredient: {name: "0", value: 0, type: 0, properties: ["0": "literal"]} -parse/0: product: {name: "a", value: 0, type: 6, properties: ["a": "point"]} -parse/0: instruction: 1 -parse/0: ingredient: {name: "0", value: 0, type: 0, properties: ["0": "literal"]} -parse/0: product: {name: "b", value: 0, type: 1, properties: ["b": "integer"]} -name/0: assign a 1 -name/0: assign b 3 -after-brace/0: recipe main -after-brace/0: copy ... -after-brace/0: copy ... diff --git a/cpp/.traces/convert_names_transforms_container_elements b/cpp/.traces/convert_names_transforms_container_elements new file mode 100644 index 00000000..0dd4f7e8 --- /dev/null +++ b/cpp/.traces/convert_names_transforms_container_elements @@ -0,0 +1,31 @@ +parse/0: instruction: 18 +parse/0: ingredient: {name: "0", value: 0, type: 6, properties: ["0": "point"]} +parse/0: ingredient: {name: "y", value: 0, type: 0, properties: ["y": "offset"]} +parse/0: product: {name: "a", value: 0, type: 1, properties: ["a": "integer"]} +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: element y of type point is at offset 1 +name/0: assign a 1 +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 ... +after-brace/0: get ... +run/0: instruction main/0 +run/0: ingredient 0 is 0 +run/0: ingredient 1 is y +run/0: address to copy is 1 +run/0: its type is 1 +mem/0: location 1 is 0 +run/0: product 0 is 0 +mem/0: storing 0 in location 1 +run/0: instruction main/1 +run/0: ingredient 0 is 0 +run/0: ingredient 1 is x +run/0: address to copy is 0 +run/0: its type is 1 +mem/0: location 0 is 0 +run/0: product 0 is 0 +mem/0: storing 0 in location 2 diff --git a/cpp/.traces/convert_names_transforms_record_elements b/cpp/.traces/convert_names_transforms_record_elements deleted file mode 100644 index 7711e827..00000000 --- a/cpp/.traces/convert_names_transforms_record_elements +++ /dev/null @@ -1,31 +0,0 @@ -parse/0: instruction: 18 -parse/0: ingredient: {name: "0", value: 0, type: 6, properties: ["0": "point"]} -parse/0: ingredient: {name: "y", value: 0, type: 0, properties: ["y": "offset"]} -parse/0: product: {name: "a", value: 0, type: 1, properties: ["a": "integer"]} -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: assign a 1 -name/0: field x of type point is at offset 0 -name/0: assign b 2 -after-brace/0: recipe main -after-brace/0: get ... -after-brace/0: get ... -run/0: instruction main/0 -run/0: ingredient 0 is 0 -run/0: ingredient 1 is y -run/0: address to copy is 1 -run/0: its type is 1 -mem/0: location 1 is 0 -run/0: product 0 is 0 -mem/0: storing 0 in location 1 -run/0: instruction main/1 -run/0: ingredient 0 is 0 -run/0: ingredient 1 is x -run/0: address to copy is 0 -run/0: its type is 1 -mem/0: location 0 is 0 -run/0: product 0 is 0 -mem/0: storing 0 in location 2 diff --git a/cpp/.traces/copy_handles_nested_container_elements b/cpp/.traces/copy_handles_nested_container_elements new file mode 100644 index 00000000..8ca9a547 --- /dev/null +++ b/cpp/.traces/copy_handles_nested_container_elements @@ -0,0 +1,34 @@ +parse/0: instruction: 1 +parse/0: ingredient: {name: "34", value: 0, type: 0, properties: ["34": "literal"]} +parse/0: product: {name: "12", value: 0, type: 1, properties: ["12": "integer"]} +parse/0: instruction: 1 +parse/0: ingredient: {name: "35", value: 0, type: 0, properties: ["35": "literal"]} +parse/0: product: {name: "13", value: 0, type: 1, properties: ["13": "integer"]} +parse/0: instruction: 1 +parse/0: ingredient: {name: "36", value: 0, type: 0, properties: ["36": "literal"]} +parse/0: product: {name: "14", value: 0, type: 1, properties: ["14": "integer"]} +parse/0: instruction: 1 +parse/0: ingredient: {name: "12", value: 0, type: 7, properties: ["12": "point-integer"]} +parse/0: product: {name: "15", value: 0, type: 7, properties: ["15": "point-integer"]} +after-brace/0: recipe main +after-brace/0: copy ... +after-brace/0: copy ... +after-brace/0: copy ... +after-brace/0: copy ... +run/0: instruction main/0 +run/0: ingredient 0 is 34 +mem/0: storing 34 in location 12 +run/0: instruction main/1 +run/0: ingredient 0 is 35 +mem/0: storing 35 in location 13 +run/0: instruction main/2 +run/0: ingredient 0 is 36 +mem/0: storing 36 in location 14 +run/0: instruction main/3 +run/0: ingredient 0 is 12 +mem/0: location 12 is 34 +mem/0: location 13 is 35 +mem/0: location 14 is 36 +mem/0: storing 34 in location 15 +mem/0: storing 35 in location 16 +mem/0: storing 36 in location 17 diff --git a/cpp/.traces/copy_handles_nested_record_elements b/cpp/.traces/copy_handles_nested_record_elements deleted file mode 100644 index 8ca9a547..00000000 --- a/cpp/.traces/copy_handles_nested_record_elements +++ /dev/null @@ -1,34 +0,0 @@ -parse/0: instruction: 1 -parse/0: ingredient: {name: "34", value: 0, type: 0, properties: ["34": "literal"]} -parse/0: product: {name: "12", value: 0, type: 1, properties: ["12": "integer"]} -parse/0: instruction: 1 -parse/0: ingredient: {name: "35", value: 0, type: 0, properties: ["35": "literal"]} -parse/0: product: {name: "13", value: 0, type: 1, properties: ["13": "integer"]} -parse/0: instruction: 1 -parse/0: ingredient: {name: "36", value: 0, type: 0, properties: ["36": "literal"]} -parse/0: product: {name: "14", value: 0, type: 1, properties: ["14": "integer"]} -parse/0: instruction: 1 -parse/0: ingredient: {name: "12", value: 0, type: 7, properties: ["12": "point-integer"]} -parse/0: product: {name: "15", value: 0, type: 7, properties: ["15": "point-integer"]} -after-brace/0: recipe main -after-brace/0: copy ... -after-brace/0: copy ... -after-brace/0: copy ... -after-brace/0: copy ... -run/0: instruction main/0 -run/0: ingredient 0 is 34 -mem/0: storing 34 in location 12 -run/0: instruction main/1 -run/0: ingredient 0 is 35 -mem/0: storing 35 in location 13 -run/0: instruction main/2 -run/0: ingredient 0 is 36 -mem/0: storing 36 in location 14 -run/0: instruction main/3 -run/0: ingredient 0 is 12 -mem/0: location 12 is 34 -mem/0: location 13 is 35 -mem/0: location 14 is 36 -mem/0: storing 34 in location 15 -mem/0: storing 35 in location 16 -mem/0: storing 36 in location 17 diff --git a/cpp/.traces/get_handles_nested_container_elements b/cpp/.traces/get_handles_nested_container_elements new file mode 100644 index 00000000..4334fc26 --- /dev/null +++ b/cpp/.traces/get_handles_nested_container_elements @@ -0,0 +1,35 @@ +parse/0: instruction: 1 +parse/0: ingredient: {name: "34", value: 0, type: 0, properties: ["34": "literal"]} +parse/0: product: {name: "12", value: 0, type: 1, properties: ["12": "integer"]} +parse/0: instruction: 1 +parse/0: ingredient: {name: "35", value: 0, type: 0, properties: ["35": "literal"]} +parse/0: product: {name: "13", value: 0, type: 1, properties: ["13": "integer"]} +parse/0: instruction: 1 +parse/0: ingredient: {name: "36", value: 0, type: 0, properties: ["36": "literal"]} +parse/0: product: {name: "14", value: 0, type: 1, properties: ["14": "integer"]} +parse/0: instruction: 18 +parse/0: ingredient: {name: "12", value: 0, type: 7, properties: ["12": "point-integer"]} +parse/0: ingredient: {name: "1", value: 0, type: 0, properties: ["1": "offset"]} +parse/0: product: {name: "15", value: 0, type: 1, properties: ["15": "integer"]} +after-brace/0: recipe main +after-brace/0: copy ... +after-brace/0: copy ... +after-brace/0: copy ... +after-brace/0: get ... +run/0: instruction main/0 +run/0: ingredient 0 is 34 +mem/0: storing 34 in location 12 +run/0: instruction main/1 +run/0: ingredient 0 is 35 +mem/0: storing 35 in location 13 +run/0: instruction main/2 +run/0: ingredient 0 is 36 +mem/0: storing 36 in location 14 +run/0: instruction main/3 +run/0: ingredient 0 is 12 +run/0: ingredient 1 is 1 +run/0: address to copy is 14 +run/0: its type is 1 +mem/0: location 14 is 36 +run/0: product 0 is 36 +mem/0: storing 36 in location 15 diff --git a/cpp/.traces/get_handles_nested_record_elements b/cpp/.traces/get_handles_nested_record_elements deleted file mode 100644 index 4334fc26..00000000 --- a/cpp/.traces/get_handles_nested_record_elements +++ /dev/null @@ -1,35 +0,0 @@ -parse/0: instruction: 1 -parse/0: ingredient: {name: "34", value: 0, type: 0, properties: ["34": "literal"]} -parse/0: product: {name: "12", value: 0, type: 1, properties: ["12": "integer"]} -parse/0: instruction: 1 -parse/0: ingredient: {name: "35", value: 0, type: 0, properties: ["35": "literal"]} -parse/0: product: {name: "13", value: 0, type: 1, properties: ["13": "integer"]} -parse/0: instruction: 1 -parse/0: ingredient: {name: "36", value: 0, type: 0, properties: ["36": "literal"]} -parse/0: product: {name: "14", value: 0, type: 1, properties: ["14": "integer"]} -parse/0: instruction: 18 -parse/0: ingredient: {name: "12", value: 0, type: 7, properties: ["12": "point-integer"]} -parse/0: ingredient: {name: "1", value: 0, type: 0, properties: ["1": "offset"]} -parse/0: product: {name: "15", value: 0, type: 1, properties: ["15": "integer"]} -after-brace/0: recipe main -after-brace/0: copy ... -after-brace/0: copy ... -after-brace/0: copy ... -after-brace/0: get ... -run/0: instruction main/0 -run/0: ingredient 0 is 34 -mem/0: storing 34 in location 12 -run/0: instruction main/1 -run/0: ingredient 0 is 35 -mem/0: storing 35 in location 13 -run/0: instruction main/2 -run/0: ingredient 0 is 36 -mem/0: storing 36 in location 14 -run/0: instruction main/3 -run/0: ingredient 0 is 12 -run/0: ingredient 1 is 1 -run/0: address to copy is 14 -run/0: its type is 1 -mem/0: location 14 is 36 -run/0: product 0 is 36 -mem/0: storing 36 in location 15 diff --git a/cpp/.traces/reply_container b/cpp/.traces/reply_container new file mode 100644 index 00000000..1a3541e6 --- /dev/null +++ b/cpp/.traces/reply_container @@ -0,0 +1,29 @@ +parse/0: instruction: 1001 +parse/0: ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]} +parse/0: product: {name: "3", value: 0, type: 6, properties: ["3": "point"]} +parse/0: instruction: 22 +parse/0: product: {name: "12", value: 0, type: 1, properties: ["12": "integer"]} +parse/0: instruction: 1 +parse/0: ingredient: {name: "35", value: 0, type: 0, properties: ["35": "literal"]} +parse/0: product: {name: "13", value: 0, type: 1, properties: ["13": "integer"]} +parse/0: instruction: 23 +parse/0: ingredient: {name: "12", value: 0, type: 6, properties: ["12": "point"]} +after-brace/0: recipe f +after-brace/0: next-ingredient ... +after-brace/0: copy ... +after-brace/0: reply ... +after-brace/0: recipe main +after-brace/0: f ... +run/0: instruction main/0 +run/0: instruction f/0 +run/0: product 0 is 2 +mem/0: storing 2 in location 12 +run/0: instruction f/1 +run/0: ingredient 0 is 35 +mem/0: storing 35 in location 13 +run/0: instruction f/2 +mem/0: location 12 is 2 +mem/0: location 13 is 35 +run/0: result 0 is [2, 35] +mem/0: storing 2 in location 3 +mem/0: storing 35 in location 4 diff --git a/cpp/.traces/reply_record b/cpp/.traces/reply_record deleted file mode 100644 index 1a3541e6..00000000 --- a/cpp/.traces/reply_record +++ /dev/null @@ -1,29 +0,0 @@ -parse/0: instruction: 1001 -parse/0: ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]} -parse/0: product: {name: "3", value: 0, type: 6, properties: ["3": "point"]} -parse/0: instruction: 22 -parse/0: product: {name: "12", value: 0, type: 1, properties: ["12": "integer"]} -parse/0: instruction: 1 -parse/0: ingredient: {name: "35", value: 0, type: 0, properties: ["35": "literal"]} -parse/0: product: {name: "13", value: 0, type: 1, properties: ["13": "integer"]} -parse/0: instruction: 23 -parse/0: ingredient: {name: "12", value: 0, type: 6, properties: ["12": "point"]} -after-brace/0: recipe f -after-brace/0: next-ingredient ... -after-brace/0: copy ... -after-brace/0: reply ... -after-brace/0: recipe main -after-brace/0: f ... -run/0: instruction main/0 -run/0: instruction f/0 -run/0: product 0 is 2 -mem/0: storing 2 in location 12 -run/0: instruction f/1 -run/0: ingredient 0 is 35 -mem/0: storing 35 in location 13 -run/0: instruction f/2 -mem/0: location 12 is 2 -mem/0: location 13 is 35 -run/0: result 0 is [2, 35] -mem/0: storing 2 in location 3 -mem/0: storing 35 in location 4 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 > elements; // only if is_record - vector 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 > elements; + vector 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/018container b/cpp/018container new file mode 100644 index 00000000..ef6b0057 --- /dev/null +++ b/cpp/018container @@ -0,0 +1,170 @@ +//: Containers contain a fixed number of elements of different types. +:(before "End Mu Types Initialization") +//: 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].kind = container; +Type[point].name = "point"; +vector i; +i.push_back(integer); +Type[point].elements.push_back(i); +Type[point].elements.push_back(i); + +:(scenario copy_multiple_locations) +# 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 + 2:integer <- copy 35:literal + 3:point <- copy 1:point +] ++run: ingredient 0 is 1 ++mem: location 1 is 34 ++mem: location 2 is 35 ++mem: storing 34 in location 3 ++mem: storing 35 in location 4 + +:(before "End Mu Types Initialization") +// 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].kind = container; +Type[point_integer].name = "point-integer"; +vector p2; +p2.push_back(point); +Type[point_integer].elements.push_back(p2); +vector i2; +i2.push_back(integer); +Type[point_integer].elements.push_back(i2); + +:(scenario "copy_handles_nested_container_elements") +recipe main [ + 12:integer <- copy 34:literal + 13:integer <- copy 35:literal + 14:integer <- copy 36:literal + 15:point-integer <- copy 12:point-integer +] ++mem: storing 36 in location 17 + +:(before "End size_of(types) Cases") +type_info t = Type[types[0]]; +if (t.kind == container) { + size_t result = 0; + for (size_t i = 0; i < t.elements.size(); ++i) { + result += size_of(t.elements[i]); + } + return result; +} + +//: To access elements of a container, use 'get' +:(scenario "get") +recipe main [ + 12:integer <- copy 34:literal + 13:integer <- copy 35:literal + 15:integer <- get 12:point, 1:offset +] ++run: instruction main/2 ++run: ingredient 0 is 12 ++run: ingredient 1 is 1 ++run: address to copy is 13 ++run: its type is 1 ++mem: location 13 is 35 ++run: product 0 is 35 ++mem: storing 35 in location 15 + +:(before "End Globals") +const int GET = 18; +:(before "End Primitive Recipe Numbers") +Recipe_number["get"] = GET; +assert(Next_recipe_number == GET); +Next_recipe_number++; +:(before "End Primitive Recipe Implementations") +case GET: { + trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name; + reagent base = instructions[pc].ingredients[0]; + int base_address = base.value; + int base_type = base.types[0]; + 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; + int src = base_address; + for (size_t i = 0; i < offset; ++i) { + src += size_of(Type[base_type].elements[i]); + } + trace("run") << "address to copy is " << src; + 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; + reagent tmp; + tmp.set_value(src); + tmp.types.push_back(src_type); + vector result(read_memory(tmp)); + trace("run") << "product 0 is " << result[0]; + write_memory(instructions[pc].products[0], result); + break; +} + +//: 'get' requires a literal in ingredient 1. We'll use a synonym called +//: 'offset' +:(before "End Mu Types Initialization") +Type_number["offset"] = 0; + +:(scenario "get_handles_nested_container_elements") +recipe main [ + 12:integer <- copy 34:literal + 13:integer <- copy 35:literal + 14:integer <- copy 36:literal + 15:integer <- get 12:point-integer, 1:offset +] ++run: instruction main/2 ++run: ingredient 0 is 12 ++run: ingredient 1 is 1 ++run: address to copy is 14 ++run: its type is 1 ++mem: location 14 is 36 ++run: product 0 is 36 ++mem: storing 36 in location 15 + +:(before "End Globals") +// 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; +assert(Next_recipe_number == GET_ADDRESS); +Next_recipe_number++; +:(before "End Primitive Recipe Implementations") +case GET_ADDRESS: { + trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name; + reagent base = instructions[pc].ingredients[0]; + int base_address = base.value; + int base_type = base.types[0]; + 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; + int src = base_address; + for (size_t i = 0; i < offset; ++i) { + src += size_of(Type[base_type].elements[i]); + } + trace("run") << "address to copy is " << src; + vector result; + result.push_back(src); + trace("run") << "product 0 is " << result[0]; + write_memory(instructions[pc].products[0], result); + break; +} + +:(scenario "get_address") +recipe main [ + 12:integer <- copy 34:literal + 13:integer <- copy 35:literal + 15:address:integer <- get-address 12:point, 1:offset +] ++run: instruction main/2 ++run: ingredient 0 is 12 ++run: ingredient 1 is 1 ++run: address to copy is 13 ++mem: storing 13 in location 15 diff --git a/cpp/018record b/cpp/018record deleted file mode 100644 index 58188813..00000000 --- a/cpp/018record +++ /dev/null @@ -1,169 +0,0 @@ -//: Records 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 -int point = Type_number["point"] = Next_type_number++; -Type[point].size = 2; -Type[point].is_record = true; -Type[point].name = "point"; -vector i; -i.push_back(integer); -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, -# no matter how large they are. -recipe main [ - 1:integer <- copy 34:literal - 2:integer <- copy 35:literal - 3:point <- copy 1:point -] -+run: ingredient 0 is 1 -+mem: location 1 is 34 -+mem: location 2 is 35 -+mem: storing 34 in location 3 -+mem: storing 35 in location 4 - -:(before "End Mu Types Initialization") -// A more complex record, containing another record. -int point_integer = Type_number["point-integer"] = Next_type_number++; -Type[point_integer].size = 2; -Type[point_integer].is_record = true; -Type[point_integer].name = "point-integer"; -vector p2; -p2.push_back(point); -Type[point_integer].elements.push_back(p2); -vector i2; -i2.push_back(integer); -Type[point_integer].elements.push_back(i2); - -:(scenario "copy_handles_nested_record_elements") -recipe main [ - 12:integer <- copy 34:literal - 13:integer <- copy 35:literal - 14:integer <- copy 36:literal - 15:point-integer <- copy 12:point-integer -] -+mem: storing 36 in location 17 - -:(before "End size_of(types) Cases") -type_info t = Type[types[0]]; -if (t.is_record) { - size_t result = 0; - for (size_t i = 0; i < t.elements.size(); ++i) { - result += size_of(t.elements[i]); - } - return result; -} - -//: To access elements of a record, use 'get' -:(scenario "get") -recipe main [ - 12:integer <- copy 34:literal - 13:integer <- copy 35:literal - 15:integer <- get 12:point, 1:offset -] -+run: instruction main/2 -+run: ingredient 0 is 12 -+run: ingredient 1 is 1 -+run: address to copy is 13 -+run: its type is 1 -+mem: location 13 is 35 -+run: product 0 is 35 -+mem: storing 35 in location 15 - -:(before "End Globals") -const int GET = 18; -:(before "End Primitive Recipe Numbers") -Recipe_number["get"] = GET; -assert(Next_recipe_number == GET); -Next_recipe_number++; -:(before "End Primitive Recipe Implementations") -case GET: { - trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name; - reagent base = instructions[pc].ingredients[0]; - int base_address = base.value; - int base_type = base.types[0]; - assert(Type[base_type].is_record); - 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; - int src = base_address; - for (size_t i = 0; i < offset; ++i) { - 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].elements.size() > offset); - int src_type = Type[base_type].elements[offset][0]; - trace("run") << "its type is " << src_type; - reagent tmp; - tmp.set_value(src); - tmp.types.push_back(src_type); - vector result(read_memory(tmp)); - trace("run") << "product 0 is " << result[0]; - write_memory(instructions[pc].products[0], result); - break; -} - -//: 'get' requires a literal in ingredient 1. We'll use a synonym called -//: 'offset' -:(before "End Mu Types Initialization") -Type_number["offset"] = 0; - -:(scenario "get_handles_nested_record_elements") -recipe main [ - 12:integer <- copy 34:literal - 13:integer <- copy 35:literal - 14:integer <- copy 36:literal - 15:integer <- get 12:point-integer, 1:offset -] -+run: instruction main/2 -+run: ingredient 0 is 12 -+run: ingredient 1 is 1 -+run: address to copy is 14 -+run: its type is 1 -+mem: location 14 is 36 -+run: product 0 is 36 -+mem: storing 36 in location 15 - -:(before "End Globals") -// To write to fields of records, you need their address. -const int GET_ADDRESS = 19; -:(before "End Primitive Recipe Numbers") -Recipe_number["get-address"] = GET_ADDRESS; -assert(Next_recipe_number == GET_ADDRESS); -Next_recipe_number++; -:(before "End Primitive Recipe Implementations") -case GET_ADDRESS: { - trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name; - reagent base = instructions[pc].ingredients[0]; - int base_address = base.value; - int base_type = base.types[0]; - assert(Type[base_type].is_record); - 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; - int src = base_address; - for (size_t i = 0; i < offset; ++i) { - src += size_of(Type[base_type].elements[i]); - } - trace("run") << "address to copy is " << src; - vector result; - result.push_back(src); - trace("run") << "product 0 is " << result[0]; - write_memory(instructions[pc].products[0], result); - break; -} - -:(scenario "get_address") -recipe main [ - 12:integer <- copy 34:literal - 13:integer <- copy 35:literal - 15:address:integer <- get-address 12:point, 1:offset -] -+run: instruction main/2 -+run: ingredient 0 is 12 -+run: ingredient 1 is 1 -+run: address to copy is 13 -+mem: storing 13 in location 15 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& 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; -- cgit 1.4.1-2-gfad0