about summary refs log blame commit diff stats
path: root/src/main.c
blob: d2392a2bbf545893b20d587fe1346ea23061ee67 (plain) (tree)
>(); // HACK: write_memory interface isn't ideal for this situation; we need // a temporary location to help copy the payload. trace(9991, "run") << "deep-copy: writing temporary " << tmp.value << ": " << out << end(); put(Memory, tmp.value, out); payload.set_value(tmp.value); // now modified for output vector<double> old_data = read_memory(payload); trace(9991, "run") << "deep-copy: really writing to " << payload.value << ' ' << to_string(payload) << " (old value " << to_string(old_data) << " new value " << to_string(data) << ")" << end(); write_memory(payload, data); trace(9991, "run") << "deep-copy: output is " << to_string(data) << end(); return out; } // deep-copy a non-address and return a vector of locations void deep_copy(const reagent& canonized_in, map<int, int>& addresses_copied, const reagent& tmp, vector<double>& out) { assert(!is_mu_address(canonized_in)); vector<double> data = read_memory(canonized_in); out.insert(out.end(), data.begin(), data.end()); if (!contains_key(Container_metadata, canonized_in.type)) return; trace(9991, "run") << "deep-copy: scanning for addresses in " << to_string(data) << end(); const container_metadata& metadata = get(Container_metadata, canonized_in.type); for (map<set<tag_condition_info>, set<address_element_info> >::const_iterator p = metadata.address.begin(); p != metadata.address.end(); ++p) { if (!all_match(data, p->first)) continue; for (set<address_element_info>::const_iterator info = p->second.begin(); info != p->second.end(); ++info) { // construct a fake reagent that reads directly from the appropriate // field of the container reagent curr; curr.type = new type_tree(new type_tree("address"), new type_tree(*info->payload_type)); curr.set_value(canonized_in.value + info->offset); curr.properties.push_back(pair<string, string_tree*>("raw", NULL)); trace(9991, "run") << "deep-copy: copying address " << curr.value << end(); out.at(info->offset) = deep_copy_address(curr, addresses_copied, tmp); } } } int payload_address(reagent/*copy*/ x) { x.properties.push_back(pair<string, string_tree*>("lookup", NULL)); canonize(x); return x.value; } //: moar tests, just because I can't believe it all works :(scenario deep_copy_stress_test_1) container foo1 [ p:&:num ] container foo2 [ p:&:foo1 ] exclusive-container foo3 [ p:&:foo1 q:&:foo2 ] def main [ local-scope x:&:num <- new number:type *x <- copy 34 a:&:foo1 <- new foo1:type *a <- merge x b:&:foo2 <- new foo2:type *b <- merge a c:foo3 <- merge 1/q, b d:foo3 <- deep-copy c e:&:foo2, z:bool <- maybe-convert d, q:variant f:&:foo1 <- get *e, p:offset g:&:num <- get *f, p:offset 1:num/raw <- copy *g ] +mem: storing 34 in location 1 :(scenario deep_copy_stress_test_2) container foo1 [ p:&:num ] container foo2 [ p:&:foo1 ] exclusive-container foo3 [ p:&:foo1 q:&:foo2 ] container foo4 [ p:num q:&:foo3 ] def main [ local-scope x:&:num <- new number:type *x <- copy 34 a:&:foo1 <- new foo1:type *a <- merge x b:&:foo2 <- new foo2:type *b <- merge a c:&:foo3 <- new foo3:type *c <- merge 1/q, b d:foo4 <- merge 35, c e:foo4 <- deep-copy d f:&:foo3 <- get e, q:offset g:&:foo2, z:bool <- maybe-convert *f, q:variant h:&:foo1 <- get *g, p:offset y:&:num <- get *h, p:offset 1:num/raw <- copy *y ] +mem: storing 34 in location 1 :(scenario deep_copy_cycles) container foo [ p:num q:&:foo ] def main [ local-scope x:&:foo <- new foo:type *x <- put *x, p:offset, 34 *x <- put *x, q:offset, x # create a cycle y:&:foo <- deep-copy x 1:num/raw <- get *y, p:offset y2:&:foo <- get *y, q:offset stash y [vs] y2 2:bool/raw <- equal y, y2 # is it still a cycle? 3:bool/raw <- equal x, y # is it the same cycle? ] +mem: storing 34 in location 1 # deep copy also contains a cycle +mem: storing 1 in location 2 # but it's a completely different (disjoint) cycle +mem: storing 0 in location 3