diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-06-28 22:44:15 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-06-28 22:44:15 -0700 |
commit | 1331848b2a5359e2b9d073266888bbda99151924 (patch) | |
tree | abe6cb99ad140b3c69455ee3c4392afae3a95638 | |
parent | f30b23eec16bd5625a24f5184b27ab45d339189e (diff) | |
download | mu-1331848b2a5359e2b9d073266888bbda99151924.tar.gz |
3072 - start of deep-copy implementation
Just simple non-address primitives so far.
-rw-r--r-- | 073deep_copy.cc | 74 |
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; + } +} |