about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--cpp/.traces/maybe_convert31
-rw-r--r--cpp/.traces/maybe_convert_fail31
-rw-r--r--cpp/030container2
-rw-r--r--cpp/034exclusive_container48
4 files changed, 111 insertions, 1 deletions
diff --git a/cpp/.traces/maybe_convert b/cpp/.traces/maybe_convert
new file mode 100644
index 00000000..c87f4aec
--- /dev/null
+++ b/cpp/.traces/maybe_convert
@@ -0,0 +1,31 @@
+parse/0: instruction: 1
+parse/0:   ingredient: {name: "1", value: 0, type: 0, properties: ["1": "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: 24
+parse/0:   ingredient: {name: "12", value: 0, type: 8, properties: ["12": "integer-or-point"]}
+parse/0:   ingredient: {name: "1", value: 0, type: 0, properties: ["1": "variant"]}
+parse/0:   product: {name: "20", value: 0, type: 2-6, properties: ["20": "address":"point"]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: maybe-convert ...
+run/0: instruction main/0
+run/0: ingredient 0 is 1
+mem/0: storing 1 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
+mem/0: storing 13 in location 20
diff --git a/cpp/.traces/maybe_convert_fail b/cpp/.traces/maybe_convert_fail
new file mode 100644
index 00000000..33666c95
--- /dev/null
+++ b/cpp/.traces/maybe_convert_fail
@@ -0,0 +1,31 @@
+parse/0: instruction: 1
+parse/0:   ingredient: {name: "1", value: 0, type: 0, properties: ["1": "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: 24
+parse/0:   ingredient: {name: "12", value: 0, type: 8, properties: ["12": "integer-or-point"]}
+parse/0:   ingredient: {name: "0", value: 0, type: 0, properties: ["0": "variant"]}
+parse/0:   product: {name: "20", value: 0, type: 2-6, properties: ["20": "address":"point"]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: maybe-convert ...
+run/0: instruction main/0
+run/0: ingredient 0 is 1
+mem/0: storing 1 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 0
+mem/0: storing 0 in location 20
diff --git a/cpp/030container b/cpp/030container
index 7f333509..fa936d25 100644
--- a/cpp/030container
+++ b/cpp/030container
@@ -108,7 +108,7 @@ case GET: {
 }
 
 //: 'get' requires a literal in ingredient 1. We'll use a synonym called
-//: 'offset'
+//: 'offset'.
 :(before "End Mu Types Initialization")
 Type_number["offset"] = 0;
 
diff --git a/cpp/034exclusive_container b/cpp/034exclusive_container
index 07758694..e38433d6 100644
--- a/cpp/034exclusive_container
+++ b/cpp/034exclusive_container
@@ -53,7 +53,55 @@ if (t.kind == exclusive_container) {
   return result+1;
 }
 
+//: To access variants of an exclusive container, use 'maybe-convert'.
+//: It always returns an address (so that you can modify it) or null (to
+//: signal that the conversion failed (because the container contains a
+//: different variant).
+
+//: 'maybe-convert' requires a literal in ingredient 1. We'll use a synonym
+//: called 'variant'.
+:(before "End Mu Types Initialization")
+Type_number["variant"] = 0;
+
+:(scenario "maybe_convert")
+recipe main [
+  12:integer <- copy 1:literal
+  13:integer <- copy 35:literal
+  14:integer <- copy 36:literal
+  20:address:point <- maybe-convert 12:integer-or-point, 1:variant
+]
++mem: storing 13 in location 20
+
+:(scenario "maybe_convert_fail")
+recipe main [
+  12:integer <- copy 1:literal
+  13:integer <- copy 35:literal
+  14:integer <- copy 36:literal
+  20:address:point <- maybe-convert 12:integer-or-point, 0:variant
+]
++mem: storing 0 in location 20
+
 :(before "End Primitive Recipe Declarations")
 MAYBE_CONVERT,
 :(before "End Primitive Recipe Numbers")
 Recipe_number["maybe-convert"] = MAYBE_CONVERT;
+:(before "End Primitive Recipe Implementations")
+case MAYBE_CONVERT: {
+  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
+  reagent base = canonize(instructions[pc].ingredients[0]);
+  int base_address = base.value;
+  int base_type = base.types[0];
+  assert(Type[base_type].kind == exclusive_container);
+  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
+  assert(isa_literal(instructions[pc].ingredients[1]));
+  size_t tag = instructions[pc].ingredients[1].value;
+  vector<int> result;
+  if (tag == static_cast<size_t>(Memory[base_address])) {
+    result.push_back(base_address+1);
+  }
+  else {
+    result.push_back(0);
+  }
+  write_memory(instructions[pc].products[0], result);
+  break;
+}