about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--073deep_copy.cc74
1 files changed, 74 insertions, 0 deletions
diff --git a/073deep_copy.cc b/073deep_copy.cc
new file mode 100644
index 00000000..f564c81d
--- /dev/null
+++ b/073deep_copy.cc
@@ -0,0 +1,74 @@
+// To recursively copy containers and any addresses they contain, use
+// 'deep-copy'.
+//
+// Invariant: After a deep-copy its ingredient and result will point to no
+// common addresses.
+// Implications: Refcounts of all data pointed to by the original ingredient
+// will remain unchanged. Refcounts of all data pointed to by the (newly
+// created) result will be 1, in the absence of cycles.
+
+:(scenario deep_copy_number)
+def main [
+  local-scope
+  x:number <- copy 34
+  y:number <- deep-copy x
+  10:boolean/raw <- equal x y
+]
+# non-addresses are identical
++mem: storing 1 in location 10
+
+:(before "End Primitive Recipe Declarations")
+DEEP_COPY,
+:(before "End Primitive Recipe Numbers")
+put(Recipe_ordinal, "deep-copy", DEEP_COPY);
+:(before "End Primitive Recipe Checks")
+case DEEP_COPY: {
+  if (SIZE(inst.ingredients) != 1) {
+    raise << maybe(get(Recipe, r).name) << "'deep-copy' takes exactly one ingredient rather than '" << to_original_string(inst) << "'\n" << end();
+    break;
+  }
+  break;
+}
+:(before "End Primitive Recipe Implementations")
+case DEEP_COPY: {
+  const reagent& input = current_instruction().ingredients.at(0);
+  products.push_back(deep_copy(input));
+  break;
+}
+
+:(code)
+vector<double> deep_copy(reagent/*copy*/ in) {
+  canonize(in);
+  vector<double> result;
+  map<int, int> addresses_copied;
+  if (is_mu_address(in))
+    result.push_back(deep_copy_address(in.value, addresses_copied));
+  // TODO: handle arrays
+  else
+    deep_copy(in, addresses_copied, result);
+  return result;
+}
+
+// deep-copy an address and return a new address
+int deep_copy_address(int in_address, map<int, int>& addresses_copied) {
+  if (in_address == 0) return 0;
+  if (contains_key(addresses_copied, in_address)) return get(addresses_copied, in_address);
+  int out = 0;
+  // HERE
+  put(addresses_copied, in_address, out);
+  return out;
+}
+
+// deep-copy a container and return a container
+
+// deep-copy a container and return a vector of locations
+void deep_copy(const reagent& canonized_in, map<int, int>& addresses_copied, vector<double>& out) {
+  assert(!is_mu_address(canonized_in));
+  if (!contains_key(Container_metadata, canonized_in.type)) {
+    assert(get(Type, canonized_in.type->value).kind == PRIMITIVE);  // not a container
+    vector<double> result = read_memory(canonized_in);
+    assert(scalar(result));
+    out.push_back(result.at(0));
+    return;
+  }
+}