diff options
-rw-r--r-- | 036refcount.cc | 495 | ||||
-rw-r--r-- | 055shape_shifting_container.cc | 74 | ||||
-rw-r--r-- | 071deep_copy.cc | 468 | ||||
-rw-r--r-- | 073scheduler.cc | 3 | ||||
-rw-r--r-- | 075channel.mu | 18 | ||||
-rw-r--r-- | html/010vm.cc.html | 6 | ||||
-rw-r--r-- | html/036refcount.cc.html | 554 | ||||
-rw-r--r-- | html/055shape_shifting_container.cc.html | 266 | ||||
-rw-r--r-- | html/061text.mu.html | 12 | ||||
-rw-r--r-- | html/063array.mu.html | 8 | ||||
-rw-r--r-- | html/068random.mu.html | 14 | ||||
-rw-r--r-- | html/070table.mu.html | 16 | ||||
-rw-r--r-- | html/073scheduler.cc.html | 885 | ||||
-rw-r--r-- | html/075channel.mu.html | 1012 | ||||
-rw-r--r-- | html/081print.mu.html | 10 | ||||
-rw-r--r-- | html/084console.mu.html | 4 | ||||
-rw-r--r-- | html/088file.mu.html | 48 | ||||
-rw-r--r-- | html/090scenario_filesystem_test.mu.html | 34 | ||||
-rw-r--r-- | html/092socket.mu.html | 30 | ||||
-rw-r--r-- | html/channel.mu.html | 16 | ||||
-rw-r--r-- | html/chessboard.mu.html | 60 | ||||
-rw-r--r-- | html/filesystem.mu.html | 6 | ||||
-rw-r--r-- | html/http-client.mu.html | 2 | ||||
-rw-r--r-- | html/http-server.mu.html | 6 | ||||
-rw-r--r-- | html/real-files.mu.html | 2 | ||||
-rwxr-xr-x | update_html | 2 |
26 files changed, 1231 insertions, 2820 deletions
diff --git a/036refcount.cc b/036refcount.cc index f9668be4..e388e5c8 100644 --- a/036refcount.cc +++ b/036refcount.cc @@ -4,501 +4,6 @@ int payload_size(reagent/*copy*/ x) { return size_of(x); } -:(before "End type_tree Definition") -struct address_element_info { - // Where inside a container type (after flattening nested containers!) the - // address lies - int offset; - - // All the information we need to compute sizes of items inside an address - // inside a container. 'payload_type' doesn't need to be a full-scale - // reagent because an address inside a container can never be an array, and - // because arrays are the only type that need to know their location to - // compute their size. - const type_tree* payload_type; - - address_element_info(int o, const type_tree* p); - address_element_info(const address_element_info& other); - ~address_element_info(); - address_element_info& operator=(const address_element_info& other); -}; -:(code) -address_element_info::address_element_info(int o, const type_tree* p) { - offset = o; - payload_type = p; -} -address_element_info::address_element_info(const address_element_info& other) { - offset = other.offset; - payload_type = copy(other.payload_type); -} -address_element_info::~address_element_info() { - if (payload_type) { - delete payload_type; - payload_type = NULL; - } -} -address_element_info& address_element_info::operator=(const address_element_info& other) { - offset = other.offset; - if (payload_type) delete payload_type; - payload_type = copy(other.payload_type); - return *this; -} - -:(before "End type_tree Definition") -// For exclusive containers we might sometimes have an address at some offset -// if some other offset has a specific tag. This struct encapsulates such -// guards. -struct tag_condition_info { - int offset; - int tag; - tag_condition_info(int o, int t) :offset(o), tag(t) {} -}; - -:(before "End container_metadata Fields") -// a list of facts of the form: -// -// IF offset o1 has tag t2 AND offset o2 has tag t2 AND .., THEN -// for all address_element_infos: -// there is an address at 'offset' pointing to a payload of type payload_type -map<set<tag_condition_info>, set<address_element_info> > address; -:(code) -bool operator<(const set<tag_condition_info>& a, const set<tag_condition_info>& b) { - if (a.size() != b.size()) return a.size() < b.size(); - for (set<tag_condition_info>::const_iterator pa = a.begin(), pb = b.begin(); pa != a.end(); ++pa, ++pb) { - if (pa->offset != pb->offset) return pa->offset < pb->offset; - if (pa->tag != pb->tag) return pa->tag < pb->tag; - } - return false; // equal -} -bool operator<(const tag_condition_info& a, const tag_condition_info& b) { - if (a.offset != b.offset) return a.offset < b.offset; - if (a.tag != b.tag) return a.tag < b.tag; - return false; // equal -} -bool operator<(const set<address_element_info>& a, const set<address_element_info>& b) { - if (a.size() != b.size()) return a.size() < b.size(); - for (set<address_element_info>::const_iterator pa = a.begin(), pb = b.begin(); pa != a.end(); ++pa, ++pb) { - if (pa->offset != pb->offset) return pa->offset < pb->offset; - } - return false; // equal -} -bool operator<(const address_element_info& a, const address_element_info& b) { - if (a.offset != b.offset) return a.offset < b.offset; - return false; // equal -} - -//: populate metadata.address in a separate transform, because it requires -//: already knowing the sizes of all types - -:(after "Transform.push_back(compute_container_sizes)") -Transform.push_back(compute_container_address_offsets); // idempotent -:(code) -void compute_container_address_offsets(const recipe_ordinal r) { - recipe& caller = get(Recipe, r); - trace(9992, "transform") << "--- compute address offsets for " << caller.name << end(); - for (int i = 0; i < SIZE(caller.steps); ++i) { - instruction& inst = caller.steps.at(i); - trace(9993, "transform") << "- compute address offsets for " << to_string(inst) << end(); - for (int i = 0; i < SIZE(inst.ingredients); ++i) - compute_container_address_offsets(inst.ingredients.at(i), " in '"+inst.original_string+"'"); - for (int i = 0; i < SIZE(inst.products); ++i) - compute_container_address_offsets(inst.products.at(i), " in '"+inst.original_string+"'"); - } -} - -void compute_container_address_offsets(reagent& r, const string& location_for_error_messages) { - if (is_literal(r) || is_dummy(r)) return; - compute_container_address_offsets(r.type, location_for_error_messages); - if (contains_key(Container_metadata, r.type)) - r.metadata = get(Container_metadata, r.type); -} - -// the recursive structure of this function needs to exactly match -// compute_container_sizes -void compute_container_address_offsets(const type_tree* type, const string& location_for_error_messages) { - if (!type) return; - if (!type->atom) { - if (!type->left->atom) { - raise << "invalid type " << to_string(type) << location_for_error_messages << '\n' << end(); - return; - } - if (type->left->name == "address") - compute_container_address_offsets(payload_type(type), location_for_error_messages); - else if (type->left->name == "array") - compute_container_address_offsets(array_element(type), location_for_error_messages); - // End compute_container_address_offsets Non-atom Special-cases - } - const type_tree* base_type = type; - // Update base_type in compute_container_address_offsets - if (!contains_key(Type, base_type->value)) return; // error raised elsewhere - type_info& info = get(Type, base_type->value); - if (info.kind == CONTAINER) { - compute_container_address_offsets(info, type, location_for_error_messages); - } - if (info.kind == EXCLUSIVE_CONTAINER) { - compute_exclusive_container_address_offsets(info, type, location_for_error_messages); - } -} - -void compute_container_address_offsets(const type_info& container_info, const type_tree* full_type, const string& location_for_error_messages) { - container_metadata& metadata = get(Container_metadata, full_type); - if (!metadata.address.empty()) return; - trace(9994, "transform") << "compute address offsets for container " << container_info.name << end(); - append_addresses(0, full_type, metadata.address, set<tag_condition_info>(), location_for_error_messages); -} - -void compute_exclusive_container_address_offsets(const type_info& exclusive_container_info, const type_tree* full_type, const string& location_for_error_messages) { - container_metadata& metadata = get(Container_metadata, full_type); - trace(9994, "transform") << "compute address offsets for exclusive container " << exclusive_container_info.name << end(); - for (int tag = 0; tag < SIZE(exclusive_container_info.elements); ++tag) { - set<tag_condition_info> key; - key.insert(tag_condition_info(/*tag is at offset*/0, tag)); - append_addresses(/*skip tag offset*/1, variant_type(full_type, tag).type, metadata.address, key, location_for_error_messages); - } -} - -void append_addresses(int base_offset, const type_tree* type, map<set<tag_condition_info>, set<address_element_info> >& out, const set<tag_condition_info>& key, const string& location_for_error_messages) { - if (is_mu_address(type)) { - get_or_insert(out, key).insert(address_element_info(base_offset, new type_tree(*payload_type(type)))); - return; - } - const type_tree* base_type = type; - // Update base_type in append_container_address_offsets - const type_info& info = get(Type, base_type->value); - if (info.kind == CONTAINER) { - for (int curr_index = 0, curr_offset = base_offset; curr_index < SIZE(info.elements); ++curr_index) { - trace(9993, "transform") << "checking container " << base_type->name << ", element " << curr_index << end(); - reagent/*copy*/ element = element_type(type, curr_index); // not base_type - // Compute Container Address Offset(element) - if (is_mu_address(element)) { - trace(9993, "transform") << "address at offset " << curr_offset << end(); - get_or_insert(out, key).insert(address_element_info(curr_offset, new type_tree(*payload_type(element.type)))); - ++curr_offset; - } - else if (is_mu_array(element)) { - curr_offset += /*array length*/1; - const type_tree* array_element_type = array_element(element.type); - int array_element_size = size_of(array_element_type); - for (int i = 0; i < static_array_length(element.type); ++i) { - append_addresses(curr_offset, array_element_type, out, key, location_for_error_messages); - curr_offset += array_element_size; - } - } - else if (is_mu_container(element)) { - append_addresses(curr_offset, element.type, out, key, location_for_error_messages); - curr_offset += size_of(element); - } - else if (is_mu_exclusive_container(element)) { - const type_tree* element_base_type = element.type; - // Update element_base_type For Exclusive Container in append_addresses - const type_info& element_info = get(Type, element_base_type->value); - for (int tag = 0; tag < SIZE(element_info.elements); ++tag) { - set<tag_condition_info> new_key = key; - new_key.insert(tag_condition_info(curr_offset, tag)); - if (!contains_key(out, new_key)) - append_addresses(curr_offset+/*skip tag*/1, variant_type(element.type, tag).type, out, new_key, location_for_error_messages); - } - curr_offset += size_of(element); - } - else { - // non-address primitive - ++curr_offset; - } - } - } - else if (info.kind == EXCLUSIVE_CONTAINER) { - for (int tag = 0; tag < SIZE(info.elements); ++tag) { - set<tag_condition_info> new_key = key; - new_key.insert(tag_condition_info(base_offset, tag)); - if (!contains_key(out, new_key)) - append_addresses(base_offset+/*skip tag*/1, variant_type(type, tag).type, out, new_key, location_for_error_messages); - } - } -} - -//: for the following unit tests we'll do the work of the transform by hand - -:(before "End Unit Tests") -void test_container_address_offsets_empty() { - int old_size = SIZE(Container_metadata); - // define a container with no addresses - reagent r("x:point"); - compute_container_sizes(r, ""); // need to first pre-populate the metadata - // scan - compute_container_address_offsets(r, ""); - // global metadata contains just the entry for foo - // no entries for non-container types or other junk - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - // the reagent we scanned knows it has no addresses - CHECK(r.metadata.address.empty()); - // the global table contains an identical entry - CHECK(contains_key(Container_metadata, r.type)); - CHECK(get(Container_metadata, r.type).address.empty()); - // compute_container_address_offsets creates no new entries - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); -} - -void test_container_address_offsets() { - int old_size = SIZE(Container_metadata); - // define a container with an address at offset 0 that we have the size for - run("container foo [\n" - " x:address:num\n" - "]\n"); - reagent r("x:foo"); - compute_container_sizes(r, ""); // need to first pre-populate the metadata - // scan - compute_container_address_offsets(r, ""); - // global metadata contains just the entry for foo - // no entries for non-container types or other junk - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - // the reagent we scanned knows it has an address at offset 0 - CHECK_EQ(SIZE(r.metadata.address), 1); - CHECK(contains_key(r.metadata.address, set<tag_condition_info>())); - const set<address_element_info>& address_offsets = get(r.metadata.address, set<tag_condition_info>()); // unconditional for containers - CHECK_EQ(SIZE(address_offsets), 1); - CHECK_EQ(address_offsets.begin()->offset, 0); - CHECK(address_offsets.begin()->payload_type->atom); - CHECK_EQ(address_offsets.begin()->payload_type->name, "number"); - // the global table contains an identical entry - CHECK(contains_key(Container_metadata, r.type)); - const set<address_element_info>& address_offsets2 = get(get(Container_metadata, r.type).address, set<tag_condition_info>()); - CHECK_EQ(SIZE(address_offsets2), 1); - CHECK_EQ(address_offsets2.begin()->offset, 0); - CHECK(address_offsets2.begin()->payload_type->atom); - CHECK_EQ(address_offsets2.begin()->payload_type->name, "number"); - // compute_container_address_offsets creates no new entries - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); -} - -void test_container_address_offsets_2() { - int old_size = SIZE(Container_metadata); - // define a container with an address at offset 1 that we have the size for - run("container foo [\n" - " x:num\n" - " y:address:num\n" - "]\n"); - reagent r("x:foo"); - compute_container_sizes(r, ""); // need to first pre-populate the metadata - // global metadata contains just the entry for foo - // no entries for non-container types or other junk - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - // scan - compute_container_address_offsets(r, ""); - // compute_container_address_offsets creates no new entries - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - // the reagent we scanned knows it has an address at offset 1 - CHECK_EQ(SIZE(r.metadata.address), 1); - CHECK(contains_key(r.metadata.address, set<tag_condition_info>())); - const set<address_element_info>& address_offsets = get(r.metadata.address, set<tag_condition_info>()); - CHECK_EQ(SIZE(address_offsets), 1); - CHECK_EQ(address_offsets.begin()->offset, 1); // - CHECK(address_offsets.begin()->payload_type->atom); - CHECK_EQ(address_offsets.begin()->payload_type->name, "number"); - // the global table contains an identical entry - CHECK(contains_key(Container_metadata, r.type)); - const set<address_element_info>& address_offsets2 = get(get(Container_metadata, r.type).address, set<tag_condition_info>()); - CHECK_EQ(SIZE(address_offsets2), 1); - CHECK_EQ(address_offsets2.begin()->offset, 1); // - CHECK(address_offsets2.begin()->payload_type->atom); - CHECK_EQ(address_offsets2.begin()->payload_type->name, "number"); -} - -void test_container_address_offsets_nested() { - int old_size = SIZE(Container_metadata); - // define a container with a nested container containing an address - run("container foo [\n" - " x:address:num\n" - " y:num\n" - "]\n" - "container bar [\n" - " p:point\n" - " f:foo\n" // nested container containing address - "]\n"); - reagent r("x:bar"); - compute_container_sizes(r, ""); // need to first pre-populate the metadata - // global metadata contains entries for bar and included types: point and foo - // no entries for non-container types or other junk - CHECK_EQ(SIZE(Container_metadata)-old_size, 3); - // scan - compute_container_address_offsets(r, ""); - // the reagent we scanned knows it has an address at offset 2 - CHECK_EQ(SIZE(r.metadata.address), 1); - CHECK(contains_key(r.metadata.address, set<tag_condition_info>())); - const set<address_element_info>& address_offsets = get(r.metadata.address, set<tag_condition_info>()); - CHECK_EQ(SIZE(address_offsets), 1); - CHECK_EQ(address_offsets.begin()->offset, 2); // - CHECK(address_offsets.begin()->payload_type->atom); - CHECK_EQ(address_offsets.begin()->payload_type->name, "number"); - // the global table also knows its address offset - CHECK(contains_key(Container_metadata, r.type)); - const set<address_element_info>& address_offsets2 = get(get(Container_metadata, r.type).address, set<tag_condition_info>()); - CHECK_EQ(SIZE(address_offsets2), 1); - CHECK_EQ(address_offsets2.begin()->offset, 2); // - CHECK(address_offsets2.begin()->payload_type->atom); - CHECK_EQ(address_offsets2.begin()->payload_type->name, "number"); - // compute_container_address_offsets creates no new entries - CHECK_EQ(SIZE(Container_metadata)-old_size, 3); -} - -void test_container_address_offsets_from_address() { - int old_size = SIZE(Container_metadata); - // define a container with an address at offset 0 - run("container foo [\n" - " x:address:num\n" - "]\n"); - reagent r("x:address:foo"); - compute_container_sizes(r, ""); // need to first pre-populate the metadata - // global metadata contains just the entry for foo - // no entries for non-container types or other junk - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - // scan an address to the container - compute_container_address_offsets(r, ""); - // compute_container_address_offsets creates no new entries - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - // scanning precomputed metadata for the container - reagent container("x:foo"); - CHECK(contains_key(Container_metadata, container.type)); - const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); - CHECK_EQ(SIZE(address_offsets2), 1); - CHECK_EQ(address_offsets2.begin()->offset, 0); - CHECK(address_offsets2.begin()->payload_type->atom); - CHECK_EQ(address_offsets2.begin()->payload_type->name, "number"); -} - -void test_container_address_offsets_from_array() { - int old_size = SIZE(Container_metadata); - // define a container with an address at offset 0 - run("container foo [\n" - " x:address:num\n" - "]\n"); - reagent r("x:array:foo"); - compute_container_sizes(r, ""); // need to first pre-populate the metadata - // global metadata contains just the entry for foo - // no entries for non-container types or other junk - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - // scan an array of the container - compute_container_address_offsets(r, ""); - // compute_container_address_offsets creates no new entries - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - // scanning precomputed metadata for the container - reagent container("x:foo"); - CHECK(contains_key(Container_metadata, container.type)); - const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); - CHECK_EQ(SIZE(address_offsets2), 1); - CHECK_EQ(address_offsets2.begin()->offset, 0); - CHECK(address_offsets2.begin()->payload_type->atom); - CHECK_EQ(address_offsets2.begin()->payload_type->name, "number"); -} - -void test_container_address_offsets_from_address_to_array() { - int old_size = SIZE(Container_metadata); - // define a container with an address at offset 0 - run("container foo [\n" - " x:address:num\n" - "]\n"); - reagent r("x:address:array:foo"); - compute_container_sizes(r, ""); // need to first pre-populate the metadata - // global metadata contains just the entry for foo - // no entries for non-container types or other junk - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - // scan an address to an array of the container - compute_container_address_offsets(r, ""); - // compute_container_address_offsets creates no new entries - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - // scanning precomputed metadata for the container - reagent container("x:foo"); - CHECK(contains_key(Container_metadata, container.type)); - const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); - CHECK_EQ(SIZE(address_offsets2), 1); - CHECK_EQ(address_offsets2.begin()->offset, 0); - CHECK(address_offsets2.begin()->payload_type->atom); - CHECK_EQ(address_offsets2.begin()->payload_type->name, "number"); -} - -void test_container_address_offsets_from_static_array() { - int old_size = SIZE(Container_metadata); - // define a container with an address at offset 0 - run("container foo [\n" - " x:address:num\n" - "]\n"); - reagent r("x:array:foo:10"); - compute_container_sizes(r, ""); // need to first pre-populate the metadata - // global metadata contains just the entry for foo - // no entries for non-container types or other junk - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - // scan a static array of the container - compute_container_address_offsets(r, ""); - // compute_container_address_offsets creates no new entries - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - // scanning precomputed metadata for the container - reagent container("x:foo"); - CHECK(contains_key(Container_metadata, container.type)); - const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); - CHECK_EQ(SIZE(address_offsets2), 1); - CHECK_EQ(address_offsets2.begin()->offset, 0); - CHECK(address_offsets2.begin()->payload_type->atom); - CHECK_EQ(address_offsets2.begin()->payload_type->name, "number"); -} - -void test_container_address_offsets_from_address_to_static_array() { - int old_size = SIZE(Container_metadata); - // define a container with an address at offset 0 - run("container foo [\n" - " x:address:num\n" - "]\n"); - reagent r("x:address:array:foo:10"); - compute_container_sizes(r, ""); // need to first pre-populate the metadata - // global metadata contains just the entry for foo - // no entries for non-container types or other junk - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - // scan an address to a static array of the container - compute_container_address_offsets(r, ""); - // compute_container_address_offsets creates no new entries - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - // scanning precomputed metadata for the container - reagent container("x:foo"); - CHECK(contains_key(Container_metadata, container.type)); - const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); - CHECK_EQ(SIZE(address_offsets2), 1); - CHECK_EQ(address_offsets2.begin()->offset, 0); - CHECK(address_offsets2.begin()->payload_type->atom); - CHECK_EQ(address_offsets2.begin()->payload_type->name, "number"); -} - -void test_container_address_offsets_from_repeated_address_and_array_types() { - int old_size = SIZE(Container_metadata); - // define a container with an address at offset 0 - run("container foo [\n" - " x:address:num\n" - "]\n"); - // scan a deep nest of 'address' and 'array' types modifying a container - reagent r("x:address:array:address:address:array:foo:10"); - compute_container_sizes(r, ""); // need to first pre-populate the metadata - // global metadata contains just the entry for foo - // no entries for non-container types or other junk - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - compute_container_address_offsets(r, ""); - // compute_container_address_offsets creates no new entries - CHECK_EQ(SIZE(Container_metadata)-old_size, 1); - // scanning precomputed metadata for the container - reagent container("x:foo"); - CHECK(contains_key(Container_metadata, container.type)); - const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); - CHECK_EQ(SIZE(address_offsets2), 1); - CHECK_EQ(address_offsets2.begin()->offset, 0); - CHECK(address_offsets2.begin()->payload_type->atom); - CHECK_EQ(address_offsets2.begin()->payload_type->name, "number"); -} - -:(code) -bool all_match(const vector<double>& data, const set<tag_condition_info>& conditions) { - for (set<tag_condition_info>::const_iterator p = conditions.begin(); p != conditions.end(); ++p) { - if (data.at(p->offset) != p->tag) - return false; - } - return true; -} - bool is_mu_container(const reagent& r) { return is_mu_container(r.type); } diff --git a/055shape_shifting_container.cc b/055shape_shifting_container.cc index 10c44155..e56b9020 100644 --- a/055shape_shifting_container.cc +++ b/055shape_shifting_container.cc @@ -22,12 +22,12 @@ base_type = get_base_type(base_type); base_type = get_base_type(base_type); :(after "Update base_type in element_type") base_type = get_base_type(base_type); -:(after "Update base_type in compute_container_address_offsets") -base_type = get_base_type(base_type); -:(after "Update base_type in append_container_address_offsets") -base_type = get_base_type(base_type); -:(after "Update element_base_type For Exclusive Container in append_addresses") -element_base_type = get_base_type(element_base_type); +//? :(after "Update base_type in compute_container_address_offsets") +//? base_type = get_base_type(base_type); +//? :(after "Update base_type in append_container_address_offsets") +//? base_type = get_base_type(base_type); +//? :(after "Update element_base_type For Exclusive Container in append_addresses") +//? element_base_type = get_base_type(element_base_type); :(after "Update base_type in skip_addresses") base_type = get_base_type(base_type); :(replace{} "const type_tree* get_base_type(const type_tree* t)") @@ -320,9 +320,9 @@ replace_type_ingredients(element, type, info, " while computing element type of replace_type_ingredients(element, full_type, container_info, location_for_error_messages); :(before "Compute Exclusive Container Size(element, full_type)") replace_type_ingredients(element, full_type, exclusive_container_info, location_for_error_messages); -:(before "Compute Container Address Offset(element)") -replace_type_ingredients(element, type, info, location_for_error_messages); -if (contains_type_ingredient(element)) return; // error raised elsewhere +//? :(before "Compute Container Address Offset(element)") +//? replace_type_ingredients(element, type, info, location_for_error_messages); +//? if (contains_type_ingredient(element)) return; // error raised elsewhere :(after "Compute size_of Container") assert(!contains_type_ingredient(type)); @@ -615,62 +615,6 @@ void test_container_sizes_recursive_shape_shifting_container() { CHECK_EQ(r2.metadata.size, 2); } -:(before "End compute_container_address_offsets Non-atom Special-cases") -const type_tree* root = get_base_type(type); -if (!contains_key(Type, root->value)) return; // error raised elsewhere -type_info& info = get(Type, root->value); -if (info.kind == CONTAINER) { - compute_container_address_offsets(info, type, location_for_error_messages); - return; -} -if (info.kind == EXCLUSIVE_CONTAINER) { - compute_exclusive_container_address_offsets(info, type, location_for_error_messages); - return; -} - -:(before "End Unit Tests") -void test_container_address_offsets_in_shape_shifting_container() { - run("container foo:_t [\n" - " x:num\n" - " y:_t\n" - "]\n"); - reagent r("x:foo:&:num"); - compute_container_sizes(r, ""); - compute_container_address_offsets(r, ""); - CHECK_EQ(SIZE(r.metadata.address), 1); - CHECK(contains_key(r.metadata.address, set<tag_condition_info>())); - set<address_element_info>& offset_info = get(r.metadata.address, set<tag_condition_info>()); - CHECK_EQ(SIZE(offset_info), 1); - CHECK_EQ(offset_info.begin()->offset, 1); // - CHECK(offset_info.begin()->payload_type->atom); - CHECK_EQ(offset_info.begin()->payload_type->name, "number"); -} - -void test_container_address_offsets_in_nested_shape_shifting_container() { - run("container foo:_t [\n" - " x:num\n" - " y:_t\n" - "]\n" - "container bar:_t [\n" - " x:_t\n" - " y:foo:_t\n" - "]\n"); - reagent r("x:bar:&:num"); - CLEAR_TRACE; - compute_container_sizes(r, ""); - compute_container_address_offsets(r, ""); - CHECK_EQ(SIZE(r.metadata.address), 1); - CHECK(contains_key(r.metadata.address, set<tag_condition_info>())); - set<address_element_info>& offset_info = get(r.metadata.address, set<tag_condition_info>()); - CHECK_EQ(SIZE(offset_info), 2); - CHECK_EQ(offset_info.begin()->offset, 0); // - CHECK(offset_info.begin()->payload_type->atom); - CHECK_EQ(offset_info.begin()->payload_type->name, "number"); - CHECK_EQ((++offset_info.begin())->offset, 2); // - CHECK((++offset_info.begin())->payload_type->atom); - CHECK_EQ((++offset_info.begin())->payload_type->name, "number"); -} - :(scenario typos_in_container_definitions) % Hide_errors = true; container foo:_t [ diff --git a/071deep_copy.cc b/071deep_copy.cc deleted file mode 100644 index f5f0f1eb..00000000 --- a/071deep_copy.cc +++ /dev/null @@ -1,468 +0,0 @@ -// 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. -// -// We do handle cycles in the ingredient, however. All cycles are translated -// to new cycles in the product. - -:(scenario deep_copy_number) -def main [ - local-scope - x:num <- copy 34 - y:num <- deep-copy x - 10:bool/raw <- equal x, y -] -# non-address primitives are identical -+mem: storing 1 in location 10 - -:(scenario deep_copy_null_pointer) -def main [ - local-scope - x:&:num <- copy 0 - y:&:num <- deep-copy x - 10:bool/raw <- equal x, y -] -# null addresses are identical -+mem: storing 1 in location 10 - -:(scenario deep_copy_container_without_address) -container foo [ - x:num - y:num -] -def main [ - local-scope - a:foo <- merge 34, 35 - b:foo <- deep-copy a - 10:bool/raw <- equal a, b -] -# containers are identical as long as they don't contain addresses -+mem: storing 1 in location 10 - -:(scenario deep_copy_address) -% Memory_allocated_until = 200; -def main [ - # avoid all memory allocations except the implicit ones inside deep-copy, so - # that the result is deterministic - 1:&:num <- copy 100/unsafe # pretend allocation - *1:&:num <- copy 34 - 2:&:num <- deep-copy 1:&:num - 10:bool <- equal 1:&:num, 2:&:num - 11:bool <- equal *1:&:num, *2:&:num - 2:&:num <- copy 0 -] -# the result of deep-copy is a new address -+mem: storing 0 in location 10 -# however, the contents are identical -+mem: storing 1 in location 11 - -:(scenario deep_copy_address_to_container) -% Memory_allocated_until = 200; -def main [ - # avoid all memory allocations except the implicit ones inside deep-copy, so - # that the result is deterministic - 1:&:point <- copy 100/unsafe # pretend allocation - *1:&:point <- merge 34, 35 - 2:&:point <- deep-copy 1:&:point - 10:bool <- equal 1:&:point, 2:&:point - 11:bool <- equal *1:&:point, *2:&:point -] -# the result of deep-copy is a new address -+mem: storing 0 in location 10 -# however, the contents are identical -+mem: storing 1 in location 11 - -:(scenario deep_copy_address_to_address) -% Memory_allocated_until = 200; -def main [ - # avoid all memory allocations except the implicit ones inside deep-copy, so - # that the result is deterministic - 1:&:&:num <- copy 100/unsafe # pretend allocation - *1:&:&:num <- copy 150/unsafe - **1:&:&:num <- copy 34 - 2:&:&:num <- deep-copy 1:&:&:num - 10:bool <- equal 1:&:&:num, 2:&:&:num - 11:bool <- equal *1:&:&:num, *2:&:&:num - 12:bool <- equal **1:&:&:num, **2:&:&:num -] -# the result of deep-copy is a new address -+mem: storing 0 in location 10 -# any addresses in it or pointed to it are also new -+mem: storing 0 in location 11 -# however, the non-address contents are identical -+mem: storing 1 in location 12 - -:(scenario deep_copy_array) -% Memory_allocated_until = 200; -def main [ - # avoid all memory allocations except the implicit ones inside deep-copy, so - # that the result is deterministic - 100:num <- copy 3 # pretend array length - 1:&:@:num <- copy 100/unsafe # pretend allocation - put-index *1:&:@:num, 0, 34 - put-index *1:&:@:num, 1, 35 - put-index *1:&:@:num, 2, 36 - stash [old:], *1:&:@:num - 2:&:@:num <- deep-copy 1:&:@:num - stash 2:&:@:num - stash [new:], *2:&:@:num - 10:bool <- equal 1:&:@:num, 2:&:@:num - 11:bool <- equal *1:&:@:num, *2:&:@:num -] -+app: old: 3 34 35 36 -+app: new: 3 34 35 36 -# the result of deep-copy is a new address -+mem: storing 0 in location 10 -# however, the contents are identical -+mem: storing 1 in location 11 - -:(scenario deep_copy_container_with_address) -container foo [ - x:num - y:&:num -] -def main [ - local-scope - y0:&:num <- new number:type - *y0 <- copy 35 - a:foo <- merge 34, y0 - b:foo <- deep-copy a - 10:bool/raw <- equal a, b - y1:&:num <- get b, y:offset - 11:bool/raw <- equal y0, y1 - 12:num/raw <- copy *y1 -] -# containers containing addresses are not identical to their deep copies -+mem: storing 0 in location 10 -# the addresses they contain are not identical either -+mem: storing 0 in location 11 -+mem: storing 35 in location 12 - -:(scenario deep_copy_exclusive_container_with_address) -exclusive-container foo [ - x:num - y:&:num -] -def main [ - local-scope - y0:&:num <- new number:type - *y0 <- copy 34 - a:foo <- merge 1/y, y0 - b:foo <- deep-copy a - 10:bool/raw <- equal a, b - y1:&:num, z:bool <- maybe-convert b, y:variant - 11:bool/raw <- equal y0, y1 - 12:num/raw <- copy *y1 -] -# exclusive containers containing addresses are not identical to their deep copies -+mem: storing 0 in location 10 -# the addresses they contain are not identical either -+mem: storing 0 in location 11 -+mem: storing 34 in location 12 - -:(scenario deep_copy_exclusive_container_with_container_with_address) -exclusive-container foo [ - x:num - y:bar # inline -] -container bar [ - x:&:num -] -def main [ - local-scope - y0:&:num <- new number:type - *y0 <- copy 34 - a:bar <- merge y0 - b:foo <- merge 1/y, a - c:foo <- deep-copy b - 10:bool/raw <- equal b, c - d:bar, z:bool <- maybe-convert c, y:variant - y1:&:num <- get d, x:offset - 11:bool/raw <- equal y0, y1 - 12:num/raw <- copy *y1 -] -# exclusive containers containing addresses are not identical to their deep copies -+mem: storing 0 in location 10 -# sub-containers containing addresses are not identical either -+mem: storing 0 in location 11 -+mem: storing 34 in location 12 - -:(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; - } - if (SIZE(inst.products) != 1) { - raise << maybe(get(Recipe, r).name) << "'deep-copy' takes exactly one ingredient rather than '" << to_original_string(inst) << "'\n" << end(); - break; - } - if (!types_strictly_match(inst.ingredients.at(0), inst.products.at(0))) { - raise << maybe(get(Recipe, r).name) << "'deep-copy' requires its ingredient and product to be the same type, but got '" << to_original_string(inst) << "'\n" << end(); - break; - } - break; -} -:(before "End Primitive Recipe Implementations") -case DEEP_COPY: { - products.push_back(deep_copy(current_instruction().ingredients.at(0))); - break; -} - -:(code) -vector<double> deep_copy(const reagent& in) { - // allocate a tiny bit of temporary space for deep_copy() - trace(9991, "run") << "deep-copy: allocating space for temporary" << end(); - reagent tmp("tmp:address:number"); - tmp.set_value(allocate(1)); - map<int, int> addresses_copied; - vector<double> result = deep_copy(in, addresses_copied, tmp); - // reclaim Mu memory allocated for tmp - trace(9991, "run") << "deep-copy: reclaiming temporary" << end(); - abandon(tmp.value, payload_size(tmp)); - // reclaim host memory allocated for tmp.type when tmp goes out of scope - return result; -} - -vector<double> deep_copy(reagent/*copy*/ in, map<int, int>& addresses_copied, const reagent& tmp) { - canonize(in); - if (is_mu_address(in)) { - // hack: skip primitive containers that do their own locking; they're designed to be shared between routines - type_tree* payload = in.type->right; - if (payload->left->name == "channel" || payload->left->name == "screen" || payload->left->name == "console" || payload->left->name == "resources") - return read_memory(in); - } - vector<double> result; - if (is_mu_address(in)) - result.push_back(deep_copy_address(in, addresses_copied, tmp)); - else - deep_copy(in, addresses_copied, tmp, result); - return result; -} - -// deep-copy an address and return a new address -int deep_copy_address(const reagent& canonized_in, map<int, int>& addresses_copied, const reagent& tmp) { - if (address_value(canonized_in) == 0) return 0; - int in_address = payload_address(canonized_in); - trace(9991, "run") << "deep-copy: copying address " << in_address << end(); - if (contains_key(addresses_copied, in_address)) { - int out = get(addresses_copied, in_address); - trace(9991, "run") << "deep-copy: copy already exists: " << out << end(); - return out; - } - int out = allocate(payload_size(canonized_in)); - trace(9991, "run") << "deep-copy: new address is " << out << end(); - put(addresses_copied, in_address, out); - reagent/*copy*/ payload = canonized_in; - payload.properties.push_back(pair<string, string_tree*>("lookup", NULL)); - trace(9991, "run") << "recursing on payload " << payload.value << ' ' << to_string(payload) << end(); - vector<double> data = deep_copy(payload, addresses_copied, tmp); - trace(9991, "run") << "deep-copy: writing result " << out << ": " << to_string(data) << end(); - // 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) { - // hack: skip primitive containers that do their own locking; they're designed to be shared between routines - if (!info->payload_type->atom && info->payload_type->left->name == "channel") - continue; - if (info->payload_type->name == "screen" || info->payload_type->name == "console" || info->payload_type->name == "resources") - continue; - // construct a fake reagent that reads directly from the appropriate - // field of the container - reagent curr; - if (info->payload_type->atom) - curr.type = new type_tree(new type_tree("address"), new type_tree(new type_tree(info->payload_type->name), NULL)); - else - 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; -} - -int address_value(const reagent& x) { - assert(is_mu_address(x)); - vector<double> result = read_memory(x); - assert(SIZE(result) == 1); - return static_cast<int>(result.at(0)); -} - -:(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 - 2:bool/raw <- equal y, y2 # is it still a cycle? - 3:bool/raw <- equal x, y # is it the same cycle? - # not bothering cleaning up; both cycles leak memory -] -+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 - -//: todo: version of deep_copy_cycles that breaks cycles at end and verifies no memory leaks -//: needs approximate matching over scenario traces - -:(scenario deep_copy_skips_channel) -# ugly! dummy 'channel' type if we happen to be building without that layer -% if (!contains_key(Type_ordinal, "channel")) get_or_insert(Type, put(Type_ordinal, "channel", Next_type_ordinal++)).name = "channel"; -def main [ - local-scope - x:&:channel:num <- new {(channel num): type} - y:&:channel:num <- deep-copy x - 10:bool/raw <- equal x, y -] -# channels are never deep-copied -+mem: storing 1 in location 10 - -:(scenario deep_copy_skips_nested_channel) -# ugly! dummy 'channel' type if we happen to be building without that layer -% if (!contains_key(Type_ordinal, "channel")) get_or_insert(Type, put(Type_ordinal, "channel", Next_type_ordinal++)).name = "channel"; -container foo [ - c:&:channel:num -] -def main [ - local-scope - x:&:foo <- new foo:type - y:&:foo <- deep-copy x - xc:&:channel:num <- get *x, c:offset - yc:&:channel:num <- get *y, c:offset - 10:bool/raw <- equal xc, yc -] -# channels are never deep-copied -+mem: storing 1 in location 10 - -:(scenario deep_copy_skips_resources) -# ugly! dummy 'resources' type if we happen to be building without that layer -% if (!contains_key(Type_ordinal, "resources")) get_or_insert(Type, put(Type_ordinal, "resources", Next_type_ordinal++)).name = "resources"; -def main [ - local-scope - x:&:resources <- new resources:type - y:&:resources <- deep-copy x - 10:bool/raw <- equal x, y -] -# resources are never deep-copied -+mem: storing 1 in location 10 - -:(scenario deep_copy_skips_nested_resources) -# ugly! dummy 'resources' type if we happen to be building without that layer -% if (!contains_key(Type_ordinal, "resources")) get_or_insert(Type, put(Type_ordinal, "resources", Next_type_ordinal++)).name = "resources"; -container foo [ - c:&:resources -] -def main [ - local-scope - x:&:foo <- new foo:type - y:&:foo <- deep-copy x - xc:&:resources <- get *x, c:offset - yc:&:resources <- get *y, c:offset - 10:bool/raw <- equal xc, yc -] -# resources are never deep-copied -+mem: storing 1 in location 10 diff --git a/073scheduler.cc b/073scheduler.cc index 75a17d33..d9f85131 100644 --- a/073scheduler.cc +++ b/073scheduler.cc @@ -178,10 +178,9 @@ case START_RUNNING: { new_routine->parent_index = Current_routine_index; // populate ingredients for (int i = /*skip callee*/1; i < SIZE(current_instruction().ingredients); ++i) { + new_routine->calls.front().ingredient_atoms.push_back(ingredients.at(i)); reagent/*copy*/ ingredient = current_instruction().ingredients.at(i); new_routine->calls.front().ingredients.push_back(ingredient); - vector<double> new_ingredient_atoms = deep_copy(ingredient); - new_routine->calls.front().ingredient_atoms.push_back(new_ingredient_atoms); // End Populate start-running Ingredient } Routines.push_back(new_routine); diff --git a/075channel.mu b/075channel.mu index 1f8248ef..422b2ab8 100644 --- a/075channel.mu +++ b/075channel.mu @@ -1,18 +1,11 @@ # Mu synchronizes between routines using channels rather than locks, like # Erlang and Go. # -# Key properties of channels: +# The key property of channels: Writing to a full channel or reading from an +# empty one will put the current routine in 'waiting' state until the +# operation can be completed. # -# a) Writing to a full channel or reading from an empty one will put the -# current routine in 'waiting' state until the operation can be completed. -# -# b) Writing to a channel implicitly performs a deep copy. This prevents -# addresses from being shared between routines, and therefore eliminates all -# possibility of race conditions. -# -# There's still a narrow window for race conditions: the inputs passed in -# to 'start-running'. Pass only channels into routines and you should be fine. -# Any other mutable inputs will require locks. +# Beware of addresses passed into channels. They can cause race conditions. scenario channel [ run [ @@ -92,8 +85,7 @@ def write out:&:sink:_elem, val:_elem -> out:&:sink:_elem [ # store a deep copy of val circular-buffer:&:@:_elem <- get *chan, data:offset free:num <- get *chan, first-free:offset - val-copy:_elem <- deep-copy val # on this instruction rests all Mu's concurrency-safety - *circular-buffer <- put-index *circular-buffer, free, val-copy + *circular-buffer <- put-index *circular-buffer, free, val # mark its slot as filled free <- add free, 1 { diff --git a/html/010vm.cc.html b/html/010vm.cc.html index 096cc89f..a22385f6 100644 --- a/html/010vm.cc.html +++ b/html/010vm.cc.html @@ -408,7 +408,7 @@ if ('onhashchange' in window) { <span id="L345" class="LineNr">345 </span> <span class="Normal">int</span> value = <span class="Constant">0</span><span class="Delimiter">;</span> <span id="L346" class="LineNr">346 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type_name<span class="Delimiter">))</span> <span id="L347" class="LineNr">347 </span> value = get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type_name<span class="Delimiter">);</span> -<span id="L348" class="LineNr">348 </span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>type_name<span class="Delimiter">))</span> <span class="Comment">// sometimes types will contain non-type tags, like numbers for the size of an array</span> +<span id="L348" class="LineNr">348 </span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>type_name<span class="Delimiter">))</span> <span class="Comment">// sometimes types will contain literal integers, like for the size of an array</span> <span id="L349" class="LineNr">349 </span> value = <span class="Constant">0</span><span class="Delimiter">;</span> <span id="L350" class="LineNr">350 </span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>properties<span class="Delimiter">-></span>value == <span class="Constant">"->"</span><span class="Delimiter">)</span> <span class="Comment">// used in recipe types</span> <span id="L351" class="LineNr">351 </span> value = <span class="Constant">0</span><span class="Delimiter">;</span> @@ -464,7 +464,7 @@ if ('onhashchange' in window) { <span id="L401" class="LineNr">401 </span><span class="Comment">// only constraint we care about: if a < b then !(b < a)</span> <span id="L402" class="LineNr">402 </span><span class="Normal">bool</span> type_tree::<span class="Normal">operator</span><<span class="Delimiter">(</span><span class="Normal">const</span> type_tree& other<span class="Delimiter">)</span> <span class="Normal">const</span> <span class="Delimiter">{</span> <span id="L403" class="LineNr">403 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>atom != other<span class="Delimiter">.</span>atom<span class="Delimiter">)</span> <span class="Identifier">return</span> atom > other<span class="Delimiter">.</span>atom<span class="Delimiter">;</span> <span class="Comment">// atoms before non-atoms</span> -<span id="L404" class="LineNr">404 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>atom<span class="Delimiter">)</span> <span class="Identifier">return</span> name < other<span class="Delimiter">.</span>name<span class="Delimiter">;</span> <span class="Comment">// sort atoms in lexical order</span> +<span id="L404" class="LineNr">404 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>atom<span class="Delimiter">)</span> <span class="Identifier">return</span> value < other<span class="Delimiter">.</span>value<span class="Delimiter">;</span> <span id="L405" class="LineNr">405 </span> <span class="Comment">// first location in one that's missing in the other makes that side 'smaller'</span> <span id="L406" class="LineNr">406 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>left && !other<span class="Delimiter">.</span>left<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span id="L407" class="LineNr">407 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!left && other<span class="Delimiter">.</span>left<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> @@ -518,7 +518,7 @@ if ('onhashchange' in window) { <span id="L455" class="LineNr">455 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>!<span class="Delimiter">(</span>*b<span class="Delimiter">.</span>type < *a<span class="Delimiter">.</span>type<span class="Delimiter">));</span> <span id="L456" class="LineNr">456 </span><span class="Delimiter">}</span> <span id="L457" class="LineNr">457 </span><span class="Normal">void</span> test_compare_list_with_smaller_left_but_larger_right<span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span id="L458" class="LineNr">458 </span> reagent a<span class="Delimiter">(</span><span class="Constant">"a:<a href='043space.cc.html#L80'>address</a>:number"</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">"b:character:array"</span><span class="Delimiter">);</span> +<span id="L458" class="LineNr">458 </span> reagent a<span class="Delimiter">(</span><span class="Constant">"a:number:character"</span><span class="Delimiter">),</span> b<span class="Delimiter">(</span><span class="Constant">"b:boolean:array"</span><span class="Delimiter">);</span> <span id="L459" class="LineNr">459 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>*a<span class="Delimiter">.</span>type < *b<span class="Delimiter">.</span>type<span class="Delimiter">);</span> <span id="L460" class="LineNr">460 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>!<span class="Delimiter">(</span>*b<span class="Delimiter">.</span>type < *a<span class="Delimiter">.</span>type<span class="Delimiter">));</span> <span id="L461" class="LineNr">461 </span><span class="Delimiter">}</span> diff --git a/html/036refcount.cc.html b/html/036refcount.cc.html index ffc58fb3..c5635881 100644 --- a/html/036refcount.cc.html +++ b/html/036refcount.cc.html @@ -22,7 +22,6 @@ a:hover { text-decoration: underline; } .LineNr { color: #444444; } .Identifier { color: #c0a020; } .Normal { color: #aaaaaa; background-color: #080808; padding-bottom: 1px; } -.cSpecial { color: #008000; } --> </style> @@ -57,530 +56,35 @@ if ('onhashchange' in window) { </head> <body onload='JumpToLine();'> <pre id='vimCodeElement'> -<span id="L1" class="LineNr"> 1 </span><span class="Normal">int</span> <a href='036refcount.cc.html#L1'>payload_size</a><span class="Delimiter">(</span>reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> x<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L2" class="LineNr"> 2 </span> x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> string_tree*><span class="Delimiter">(</span><span class="Constant">"lookup"</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> -<span id="L3" class="LineNr"> 3 </span> lookup_memory_core<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">check_for_null</span><span class="Comment">*/</span><span class="Constant">false</span><span class="Delimiter">);</span> -<span id="L4" class="LineNr"> 4 </span> <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>x<span class="Delimiter">);</span> -<span id="L5" class="LineNr"> 5 </span><span class="Delimiter">}</span> -<span id="L6" class="LineNr"> 6 </span> -<span id="L7" class="LineNr"> 7 </span><span class="Delimiter">:(before "End type_tree Definition")</span> -<span id="L8" class="LineNr"> 8 </span><span class="Normal">struct</span> address_element_info <span class="Delimiter">{</span> -<span id="L9" class="LineNr"> 9 </span> <span class="Comment">// Where inside a container type (after flattening nested containers!) the</span> -<span id="L10" class="LineNr"> 10 </span> <span class="Comment">// address lies</span> -<span id="L11" class="LineNr"> 11 </span> <span class="Normal">int</span> offset<span class="Delimiter">;</span> -<span id="L12" class="LineNr"> 12 </span> -<span id="L13" class="LineNr"> 13 </span> <span class="Comment">// All the information we need to compute sizes of items inside an address</span> -<span id="L14" class="LineNr"> 14 </span> <span class="Comment">// inside a container. 'payload_type' doesn't need to be a full-scale</span> -<span id="L15" class="LineNr"> 15 </span> <span class="Comment">// reagent because an address inside a container can never be an array, and</span> -<span id="L16" class="LineNr"> 16 </span> <span class="Comment">// because arrays are the only type that need to know their location to</span> -<span id="L17" class="LineNr"> 17 </span> <span class="Comment">// compute their size.</span> -<span id="L18" class="LineNr"> 18 </span> <span class="Normal">const</span> type_tree* <a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">;</span> -<span id="L19" class="LineNr"> 19 </span> -<span id="L20" class="LineNr"> 20 </span> address_element_info<span class="Delimiter">(</span><span class="Normal">int</span> o<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* p<span class="Delimiter">);</span> -<span id="L21" class="LineNr"> 21 </span> address_element_info<span class="Delimiter">(</span><span class="Normal">const</span> address_element_info& other<span class="Delimiter">);</span> -<span id="L22" class="LineNr"> 22 </span> <a href='036refcount.cc.html#L34'>~address_element_info</a><span class="Delimiter">();</span> -<span id="L23" class="LineNr"> 23 </span> address_element_info& <span class="Normal">operator</span>=<span class="Delimiter">(</span><span class="Normal">const</span> address_element_info& other<span class="Delimiter">);</span> -<span id="L24" class="LineNr"> 24 </span><span class="Delimiter">};</span> -<span id="L25" class="LineNr"> 25 </span><span class="Delimiter">:(code)</span> -<span id="L26" class="LineNr"> 26 </span>address_element_info::address_element_info<span class="Delimiter">(</span><span class="Normal">int</span> o<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* p<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L27" class="LineNr"> 27 </span> offset = o<span class="Delimiter">;</span> -<span id="L28" class="LineNr"> 28 </span> <a href='030container.cc.html#L238'>payload_type</a> = p<span class="Delimiter">;</span> -<span id="L29" class="LineNr"> 29 </span><span class="Delimiter">}</span> -<span id="L30" class="LineNr"> 30 </span>address_element_info::address_element_info<span class="Delimiter">(</span><span class="Normal">const</span> address_element_info& other<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L31" class="LineNr"> 31 </span> offset = other<span class="Delimiter">.</span>offset<span class="Delimiter">;</span> -<span id="L32" class="LineNr"> 32 </span> <a href='030container.cc.html#L238'>payload_type</a> = copy<span class="Delimiter">(</span>other<span class="Delimiter">.</span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">);</span> -<span id="L33" class="LineNr"> 33 </span><span class="Delimiter">}</span> -<span id="L34" class="LineNr"> 34 </span>address_element_info::<a href='036refcount.cc.html#L34'>~address_element_info</a><span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span id="L35" class="LineNr"> 35 </span> <span class="Normal">if</span> <span class="Delimiter">(</span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L36" class="LineNr"> 36 </span> <span class="Normal">delete</span> <a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">;</span> -<span id="L37" class="LineNr"> 37 </span> <a href='030container.cc.html#L238'>payload_type</a> = <span class="Constant">NULL</span><span class="Delimiter">;</span> -<span id="L38" class="LineNr"> 38 </span> <span class="Delimiter">}</span> -<span id="L39" class="LineNr"> 39 </span><span class="Delimiter">}</span> -<span id="L40" class="LineNr"> 40 </span>address_element_info& address_element_info::<span class="Normal">operator</span>=<span class="Delimiter">(</span><span class="Normal">const</span> address_element_info& other<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L41" class="LineNr"> 41 </span> offset = other<span class="Delimiter">.</span>offset<span class="Delimiter">;</span> -<span id="L42" class="LineNr"> 42 </span> <span class="Normal">if</span> <span class="Delimiter">(</span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">)</span> <span class="Normal">delete</span> <a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">;</span> -<span id="L43" class="LineNr"> 43 </span> <a href='030container.cc.html#L238'>payload_type</a> = copy<span class="Delimiter">(</span>other<span class="Delimiter">.</span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">);</span> -<span id="L44" class="LineNr"> 44 </span> <span class="Identifier">return</span> *<span class="Normal">this</span><span class="Delimiter">;</span> -<span id="L45" class="LineNr"> 45 </span><span class="Delimiter">}</span> -<span id="L46" class="LineNr"> 46 </span> -<span id="L47" class="LineNr"> 47 </span><span class="Delimiter">:(before "End type_tree Definition")</span> -<span id="L48" class="LineNr"> 48 </span><span class="Comment">// For exclusive containers we might sometimes have an address at some offset</span> -<span id="L49" class="LineNr"> 49 </span><span class="Comment">// if some other offset has a specific tag. This struct encapsulates such</span> -<span id="L50" class="LineNr"> 50 </span><span class="Comment">// guards.</span> -<span id="L51" class="LineNr"> 51 </span><span class="Normal">struct</span> tag_condition_info <span class="Delimiter">{</span> -<span id="L52" class="LineNr"> 52 </span> <span class="Normal">int</span> offset<span class="Delimiter">;</span> -<span id="L53" class="LineNr"> 53 </span> <span class="Normal">int</span> tag<span class="Delimiter">;</span> -<span id="L54" class="LineNr"> 54 </span> tag_condition_info<span class="Delimiter">(</span><span class="Normal">int</span> o<span class="Delimiter">,</span> <span class="Normal">int</span> t<span class="Delimiter">)</span> :offset<span class="Delimiter">(</span>o<span class="Delimiter">),</span> tag<span class="Delimiter">(</span>t<span class="Delimiter">)</span> <span class="Delimiter">{}</span> -<span id="L55" class="LineNr"> 55 </span><span class="Delimiter">};</span> -<span id="L56" class="LineNr"> 56 </span> -<span id="L57" class="LineNr"> 57 </span><span class="Delimiter">:(before "End container_metadata Fields")</span> -<span id="L58" class="LineNr"> 58 </span><span class="Comment">// a list of facts of the form:</span> -<span id="L59" class="LineNr"> 59 </span><span class="Comment">//</span> -<span id="L60" class="LineNr"> 60 </span><span class="Comment">// IF offset o1 has tag t2 AND offset o2 has tag t2 AND .., THEN</span> -<span id="L61" class="LineNr"> 61 </span><span class="Comment">// for all address_element_infos:</span> -<span id="L62" class="LineNr"> 62 </span><span class="Comment">// there is an address at 'offset' pointing to a payload of type payload_type</span> -<span id="L63" class="LineNr"> 63 </span>map<set<tag_condition_info><span class="Delimiter">,</span> set<address_element_info> > <a href='043space.cc.html#L80'>address</a><span class="Delimiter">;</span> -<span id="L64" class="LineNr"> 64 </span><span class="Delimiter">:(code)</span> -<span id="L65" class="LineNr"> 65 </span><span class="Normal">bool</span> <span class="Normal">operator</span><<span class="Delimiter">(</span><span class="Normal">const</span> set<tag_condition_info>& a<span class="Delimiter">,</span> <span class="Normal">const</span> set<tag_condition_info>& b<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L66" class="LineNr"> 66 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">.</span>size<span class="Delimiter">()</span> != b<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Identifier">return</span> a<span class="Delimiter">.</span>size<span class="Delimiter">()</span> < b<span class="Delimiter">.</span>size<span class="Delimiter">();</span> -<span id="L67" class="LineNr"> 67 </span> <span class="Normal">for</span> <span class="Delimiter">(</span>set<tag_condition_info>::const_iterator pa = a<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> pb = b<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> pa != a<span class="Delimiter">.</span><a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> ++pa<span class="Delimiter">,</span> ++pb<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L68" class="LineNr"> 68 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>pa<span class="Delimiter">-></span>offset != pb<span class="Delimiter">-></span>offset<span class="Delimiter">)</span> <span class="Identifier">return</span> pa<span class="Delimiter">-></span>offset < pb<span class="Delimiter">-></span>offset<span class="Delimiter">;</span> -<span id="L69" class="LineNr"> 69 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>pa<span class="Delimiter">-></span>tag != pb<span class="Delimiter">-></span>tag<span class="Delimiter">)</span> <span class="Identifier">return</span> pa<span class="Delimiter">-></span>tag < pb<span class="Delimiter">-></span>tag<span class="Delimiter">;</span> -<span id="L70" class="LineNr"> 70 </span> <span class="Delimiter">}</span> -<span id="L71" class="LineNr"> 71 </span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// equal</span> -<span id="L72" class="LineNr"> 72 </span><span class="Delimiter">}</span> -<span id="L73" class="LineNr"> 73 </span><span class="Normal">bool</span> <span class="Normal">operator</span><<span class="Delimiter">(</span><span class="Normal">const</span> tag_condition_info& a<span class="Delimiter">,</span> <span class="Normal">const</span> tag_condition_info& b<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L74" class="LineNr"> 74 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">.</span>offset != b<span class="Delimiter">.</span>offset<span class="Delimiter">)</span> <span class="Identifier">return</span> a<span class="Delimiter">.</span>offset < b<span class="Delimiter">.</span>offset<span class="Delimiter">;</span> -<span id="L75" class="LineNr"> 75 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">.</span>tag != b<span class="Delimiter">.</span>tag<span class="Delimiter">)</span> <span class="Identifier">return</span> a<span class="Delimiter">.</span>tag < b<span class="Delimiter">.</span>tag<span class="Delimiter">;</span> -<span id="L76" class="LineNr"> 76 </span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// equal</span> -<span id="L77" class="LineNr"> 77 </span><span class="Delimiter">}</span> -<span id="L78" class="LineNr"> 78 </span><span class="Normal">bool</span> <span class="Normal">operator</span><<span class="Delimiter">(</span><span class="Normal">const</span> set<address_element_info>& a<span class="Delimiter">,</span> <span class="Normal">const</span> set<address_element_info>& b<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L79" class="LineNr"> 79 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">.</span>size<span class="Delimiter">()</span> != b<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Identifier">return</span> a<span class="Delimiter">.</span>size<span class="Delimiter">()</span> < b<span class="Delimiter">.</span>size<span class="Delimiter">();</span> -<span id="L80" class="LineNr"> 80 </span> <span class="Normal">for</span> <span class="Delimiter">(</span>set<address_element_info>::const_iterator pa = a<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> pb = b<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> pa != a<span class="Delimiter">.</span><a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> ++pa<span class="Delimiter">,</span> ++pb<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L81" class="LineNr"> 81 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>pa<span class="Delimiter">-></span>offset != pb<span class="Delimiter">-></span>offset<span class="Delimiter">)</span> <span class="Identifier">return</span> pa<span class="Delimiter">-></span>offset < pb<span class="Delimiter">-></span>offset<span class="Delimiter">;</span> -<span id="L82" class="LineNr"> 82 </span> <span class="Delimiter">}</span> -<span id="L83" class="LineNr"> 83 </span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// equal</span> -<span id="L84" class="LineNr"> 84 </span><span class="Delimiter">}</span> -<span id="L85" class="LineNr"> 85 </span><span class="Normal">bool</span> <span class="Normal">operator</span><<span class="Delimiter">(</span><span class="Normal">const</span> address_element_info& a<span class="Delimiter">,</span> <span class="Normal">const</span> address_element_info& b<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L86" class="LineNr"> 86 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">.</span>offset != b<span class="Delimiter">.</span>offset<span class="Delimiter">)</span> <span class="Identifier">return</span> a<span class="Delimiter">.</span>offset < b<span class="Delimiter">.</span>offset<span class="Delimiter">;</span> -<span id="L87" class="LineNr"> 87 </span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// equal</span> -<span id="L88" class="LineNr"> 88 </span><span class="Delimiter">}</span> -<span id="L89" class="LineNr"> 89 </span> -<span id="L90" class="LineNr"> 90 </span><span class="Comment">//: populate metadata.address in a separate transform, because it requires</span> -<span id="L91" class="LineNr"> 91 </span><span class="Comment">//: already knowing the sizes of all types</span> -<span id="L92" class="LineNr"> 92 </span> -<span id="L93" class="LineNr"> 93 </span><span class="Delimiter">:(after "Transform.push_back(compute_container_sizes)")</span> -<span id="L94" class="LineNr"> 94 </span>Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>compute_container_address_offsets<span class="Delimiter">);</span> <span class="Comment">// idempotent</span> -<span id="L95" class="LineNr"> 95 </span><span class="Delimiter">:(code)</span> -<span id="L96" class="LineNr"> 96 </span><span class="Normal">void</span> compute_container_address_offsets<span class="Delimiter">(</span><span class="Normal">const</span> <a href='010vm.cc.html#L14'>recipe_ordinal</a> r<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L97" class="LineNr"> 97 </span> recipe& caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> -<span id="L98" class="LineNr"> 98 </span> <a href='003trace.cc.html#L167'>trace</a><span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"--- compute <a href='043space.cc.html#L80'>address</a> offsets for "</span> << caller<span class="Delimiter">.</span>name << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L99" class="LineNr"> 99 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>caller<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L100" class="LineNr">100 </span> instruction& inst = caller<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> -<span id="L101" class="LineNr">101 </span> <a href='003trace.cc.html#L167'>trace</a><span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"- compute <a href='043space.cc.html#L80'>address</a> offsets for "</span> << <a href='028call_return.cc.html#L163'>to_string</a><span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L102" class="LineNr">102 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> -<span id="L103" class="LineNr">103 </span> compute_container_address_offsets<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Constant">" in '"</span>+inst<span class="Delimiter">.</span>original_string+<span class="Constant">"'"</span><span class="Delimiter">);</span> -<span id="L104" class="LineNr">104 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> -<span id="L105" class="LineNr">105 </span> compute_container_address_offsets<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Constant">" in '"</span>+inst<span class="Delimiter">.</span>original_string+<span class="Constant">"'"</span><span class="Delimiter">);</span> -<span id="L106" class="LineNr">106 </span> <span class="Delimiter">}</span> -<span id="L107" class="LineNr">107 </span><span class="Delimiter">}</span> -<span id="L108" class="LineNr">108 </span> -<span id="L109" class="LineNr">109 </span><span class="Normal">void</span> compute_container_address_offsets<span class="Delimiter">(</span>reagent& r<span class="Delimiter">,</span> <span class="Normal">const</span> string& location_for_error_messages<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L110" class="LineNr">110 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>r<span class="Delimiter">)</span> || is_dummy<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> -<span id="L111" class="LineNr">111 </span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">,</span> location_for_error_messages<span class="Delimiter">);</span> -<span id="L112" class="LineNr">112 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">))</span> -<span id="L113" class="LineNr">113 </span> r<span class="Delimiter">.</span>metadata = get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">);</span> -<span id="L114" class="LineNr">114 </span><span class="Delimiter">}</span> -<span id="L115" class="LineNr">115 </span> -<span id="L116" class="LineNr">116 </span><span class="Comment">// the recursive structure of this function needs to exactly match</span> -<span id="L117" class="LineNr">117 </span><span class="Comment">// compute_container_sizes</span> -<span id="L118" class="LineNr">118 </span><span class="Normal">void</span> compute_container_address_offsets<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">,</span> <span class="Normal">const</span> string& location_for_error_messages<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L119" class="LineNr">119 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> -<span id="L120" class="LineNr">120 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">-></span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L121" class="LineNr">121 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">-></span>left<span class="Delimiter">-></span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L122" class="LineNr">122 </span> <a href='003trace.cc.html#L174'>raise</a> << <span class="Constant">"invalid type "</span> << <a href='028call_return.cc.html#L163'>to_string</a><span class="Delimiter">(</span>type<span class="Delimiter">)</span> << location_for_error_messages << <span class="cSpecial">'\n'</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L123" class="LineNr">123 </span> <span class="Identifier">return</span><span class="Delimiter">;</span> -<span id="L124" class="LineNr">124 </span> <span class="Delimiter">}</span> -<span id="L125" class="LineNr">125 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-></span>left<span class="Delimiter">-></span>name == <span class="Constant">"address"</span><span class="Delimiter">)</span> -<span id="L126" class="LineNr">126 </span> compute_container_address_offsets<span class="Delimiter">(</span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">(</span>type<span class="Delimiter">),</span> location_for_error_messages<span class="Delimiter">);</span> -<span id="L127" class="LineNr">127 </span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-></span>left<span class="Delimiter">-></span>name == <span class="Constant">"array"</span><span class="Delimiter">)</span> -<span id="L128" class="LineNr">128 </span> compute_container_address_offsets<span class="Delimiter">(</span><a href='032array.cc.html#L379'>array_element</a><span class="Delimiter">(</span>type<span class="Delimiter">),</span> location_for_error_messages<span class="Delimiter">);</span> -<span id="L129" class="LineNr">129 </span> <span class="Comment">// End compute_container_address_offsets Non-atom Special-cases</span> -<span id="L130" class="LineNr">130 </span> <span class="Delimiter">}</span> -<span id="L131" class="LineNr">131 </span> <span class="Normal">const</span> type_tree* base_type = type<span class="Delimiter">;</span> -<span id="L132" class="LineNr">132 </span> <span class="Comment">// Update base_type in compute_container_address_offsets</span> -<span id="L133" class="LineNr">133 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">-></span>value<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// error raised elsewhere</span> -<span id="L134" class="LineNr">134 </span> type_info& info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> -<span id="L135" class="LineNr">135 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == <a href='010vm.cc.html#L174'>CONTAINER</a><span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L136" class="LineNr">136 </span> compute_container_address_offsets<span class="Delimiter">(</span>info<span class="Delimiter">,</span> type<span class="Delimiter">,</span> location_for_error_messages<span class="Delimiter">);</span> -<span id="L137" class="LineNr">137 </span> <span class="Delimiter">}</span> -<span id="L138" class="LineNr">138 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == <a href='010vm.cc.html#L175'>EXCLUSIVE_CONTAINER</a><span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L139" class="LineNr">139 </span> <a href='036refcount.cc.html#L150'>compute_exclusive_container_address_offsets</a><span class="Delimiter">(</span>info<span class="Delimiter">,</span> type<span class="Delimiter">,</span> location_for_error_messages<span class="Delimiter">);</span> -<span id="L140" class="LineNr">140 </span> <span class="Delimiter">}</span> -<span id="L141" class="LineNr">141 </span><span class="Delimiter">}</span> -<span id="L142" class="LineNr">142 </span> -<span id="L143" class="LineNr">143 </span><span class="Normal">void</span> compute_container_address_offsets<span class="Delimiter">(</span><span class="Normal">const</span> type_info& container_info<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* full_type<span class="Delimiter">,</span> <span class="Normal">const</span> string& location_for_error_messages<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L144" class="LineNr">144 </span> container_metadata& metadata = get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> full_type<span class="Delimiter">);</span> -<span id="L145" class="LineNr">145 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> -<span id="L146" class="LineNr">146 </span> <a href='003trace.cc.html#L167'>trace</a><span class="Delimiter">(</span><span class="Constant">9994</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"compute <a href='043space.cc.html#L80'>address</a> offsets for container "</span> << container_info<span class="Delimiter">.</span>name << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L147" class="LineNr">147 </span> <a href='036refcount.cc.html#L160'>append_addresses</a><span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> full_type<span class="Delimiter">,</span> metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">(),</span> location_for_error_messages<span class="Delimiter">);</span> -<span id="L148" class="LineNr">148 </span><span class="Delimiter">}</span> -<span id="L149" class="LineNr">149 </span> -<span id="L150" class="LineNr">150 </span><span class="Normal">void</span> <a href='036refcount.cc.html#L150'>compute_exclusive_container_address_offsets</a><span class="Delimiter">(</span><span class="Normal">const</span> type_info& exclusive_container_info<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* full_type<span class="Delimiter">,</span> <span class="Normal">const</span> string& location_for_error_messages<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L151" class="LineNr">151 </span> container_metadata& metadata = get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> full_type<span class="Delimiter">);</span> -<span id="L152" class="LineNr">152 </span> <a href='003trace.cc.html#L167'>trace</a><span class="Delimiter">(</span><span class="Constant">9994</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"compute <a href='043space.cc.html#L80'>address</a> offsets for exclusive container "</span> << exclusive_container_info<span class="Delimiter">.</span>name << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L153" class="LineNr">153 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> tag = <span class="Constant">0</span><span class="Delimiter">;</span> tag < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>exclusive_container_info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++tag<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L154" class="LineNr">154 </span> set<tag_condition_info> key<span class="Delimiter">;</span> -<span id="L155" class="LineNr">155 </span> key<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>tag_condition_info<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">tag is at offset</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">,</span> tag<span class="Delimiter">));</span> -<span id="L156" class="LineNr">156 </span> <a href='036refcount.cc.html#L160'>append_addresses</a><span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">skip tag offset</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> variant_type<span class="Delimiter">(</span>full_type<span class="Delimiter">,</span> tag<span class="Delimiter">).</span>type<span class="Delimiter">,</span> metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> key<span class="Delimiter">,</span> location_for_error_messages<span class="Delimiter">);</span> -<span id="L157" class="LineNr">157 </span> <span class="Delimiter">}</span> -<span id="L158" class="LineNr">158 </span><span class="Delimiter">}</span> -<span id="L159" class="LineNr">159 </span> -<span id="L160" class="LineNr">160 </span><span class="Normal">void</span> <a href='036refcount.cc.html#L160'>append_addresses</a><span class="Delimiter">(</span><span class="Normal">int</span> base_offset<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* type<span class="Delimiter">,</span> map<set<tag_condition_info><span class="Delimiter">,</span> set<address_element_info> >& out<span class="Delimiter">,</span> <span class="Normal">const</span> set<tag_condition_info>& key<span class="Delimiter">,</span> <span class="Normal">const</span> string& location_for_error_messages<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L161" class="LineNr">161 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>type<span class="Delimiter">))</span> <span class="Delimiter">{</span> -<span id="L162" class="LineNr">162 </span> <a href='001help.cc.html#L229'>get_or_insert</a><span class="Delimiter">(</span>out<span class="Delimiter">,</span> key<span class="Delimiter">).</span>insert<span class="Delimiter">(</span>address_element_info<span class="Delimiter">(</span>base_offset<span class="Delimiter">,</span> <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*payload_type<span class="Delimiter">(</span>type<span class="Delimiter">))));</span> -<span id="L163" class="LineNr">163 </span> <span class="Identifier">return</span><span class="Delimiter">;</span> -<span id="L164" class="LineNr">164 </span> <span class="Delimiter">}</span> -<span id="L165" class="LineNr">165 </span> <span class="Normal">const</span> type_tree* base_type = type<span class="Delimiter">;</span> -<span id="L166" class="LineNr">166 </span> <span class="Comment">// Update base_type in append_container_address_offsets</span> -<span id="L167" class="LineNr">167 </span> <span class="Normal">const</span> type_info& info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> -<span id="L168" class="LineNr">168 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == <a href='010vm.cc.html#L174'>CONTAINER</a><span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L169" class="LineNr">169 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> curr_index = <span class="Constant">0</span><span class="Delimiter">,</span> curr_offset = base_offset<span class="Delimiter">;</span> curr_index < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++curr_index<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L170" class="LineNr">170 </span> <a href='003trace.cc.html#L167'>trace</a><span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"checking container "</span> << base_type<span class="Delimiter">-></span>name << <span class="Constant">", element "</span> << curr_index << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L171" class="LineNr">171 </span> reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> element = <a href='030container.cc.html#L429'>element_type</a><span class="Delimiter">(</span>type<span class="Delimiter">,</span> curr_index<span class="Delimiter">);</span> <span class="Comment">// not base_type</span> -<span id="L172" class="LineNr">172 </span> <span class="Comment">// Compute Container Address Offset(element)</span> -<span id="L173" class="LineNr">173 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> -<span id="L174" class="LineNr">174 </span> <a href='003trace.cc.html#L167'>trace</a><span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"address at offset "</span> << curr_offset << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L175" class="LineNr">175 </span> <a href='001help.cc.html#L229'>get_or_insert</a><span class="Delimiter">(</span>out<span class="Delimiter">,</span> key<span class="Delimiter">).</span>insert<span class="Delimiter">(</span>address_element_info<span class="Delimiter">(</span>curr_offset<span class="Delimiter">,</span> <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*payload_type<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">))));</span> -<span id="L176" class="LineNr">176 </span> ++curr_offset<span class="Delimiter">;</span> -<span id="L177" class="LineNr">177 </span> <span class="Delimiter">}</span> -<span id="L178" class="LineNr">178 </span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_array<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> -<span id="L179" class="LineNr">179 </span> curr_offset += <span class="Comment">/*</span><span class="Comment">array length</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> -<span id="L180" class="LineNr">180 </span> <span class="Normal">const</span> type_tree* array_element_type = <a href='032array.cc.html#L379'>array_element</a><span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">);</span> -<span id="L181" class="LineNr">181 </span> <span class="Normal">int</span> array_element_size = size_of<span class="Delimiter">(</span>array_element_type<span class="Delimiter">);</span> -<span id="L182" class="LineNr">182 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='032array.cc.html#L117'>static_array_length</a><span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L183" class="LineNr">183 </span> <a href='036refcount.cc.html#L160'>append_addresses</a><span class="Delimiter">(</span>curr_offset<span class="Delimiter">,</span> array_element_type<span class="Delimiter">,</span> out<span class="Delimiter">,</span> key<span class="Delimiter">,</span> location_for_error_messages<span class="Delimiter">);</span> -<span id="L184" class="LineNr">184 </span> curr_offset += array_element_size<span class="Delimiter">;</span> -<span id="L185" class="LineNr">185 </span> <span class="Delimiter">}</span> -<span id="L186" class="LineNr">186 </span> <span class="Delimiter">}</span> -<span id="L187" class="LineNr">187 </span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_container<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> -<span id="L188" class="LineNr">188 </span> <a href='036refcount.cc.html#L160'>append_addresses</a><span class="Delimiter">(</span>curr_offset<span class="Delimiter">,</span> element<span class="Delimiter">.</span>type<span class="Delimiter">,</span> out<span class="Delimiter">,</span> key<span class="Delimiter">,</span> location_for_error_messages<span class="Delimiter">);</span> -<span id="L189" class="LineNr">189 </span> curr_offset += size_of<span class="Delimiter">(</span>element<span class="Delimiter">);</span> -<span id="L190" class="LineNr">190 </span> <span class="Delimiter">}</span> -<span id="L191" class="LineNr">191 </span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_exclusive_container<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> -<span id="L192" class="LineNr">192 </span> <span class="Normal">const</span> type_tree* element_base_type = element<span class="Delimiter">.</span>type<span class="Delimiter">;</span> -<span id="L193" class="LineNr">193 </span> <span class="Comment">// Update element_base_type For Exclusive Container in append_addresses</span> -<span id="L194" class="LineNr">194 </span> <span class="Normal">const</span> type_info& element_info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> element_base_type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> -<span id="L195" class="LineNr">195 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> tag = <span class="Constant">0</span><span class="Delimiter">;</span> tag < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>element_info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++tag<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L196" class="LineNr">196 </span> set<tag_condition_info> new_key = key<span class="Delimiter">;</span> -<span id="L197" class="LineNr">197 </span> new_key<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>tag_condition_info<span class="Delimiter">(</span>curr_offset<span class="Delimiter">,</span> tag<span class="Delimiter">));</span> -<span id="L198" class="LineNr">198 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>out<span class="Delimiter">,</span> new_key<span class="Delimiter">))</span> -<span id="L199" class="LineNr">199 </span> <a href='036refcount.cc.html#L160'>append_addresses</a><span class="Delimiter">(</span>curr_offset+<span class="Comment">/*</span><span class="Comment">skip tag</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> variant_type<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">,</span> tag<span class="Delimiter">).</span>type<span class="Delimiter">,</span> out<span class="Delimiter">,</span> new_key<span class="Delimiter">,</span> location_for_error_messages<span class="Delimiter">);</span> -<span id="L200" class="LineNr">200 </span> <span class="Delimiter">}</span> -<span id="L201" class="LineNr">201 </span> curr_offset += size_of<span class="Delimiter">(</span>element<span class="Delimiter">);</span> -<span id="L202" class="LineNr">202 </span> <span class="Delimiter">}</span> -<span id="L203" class="LineNr">203 </span> <span class="Normal">else</span> <span class="Delimiter">{</span> -<span id="L204" class="LineNr">204 </span> <span class="Comment">// non-address primitive</span> -<span id="L205" class="LineNr">205 </span> ++curr_offset<span class="Delimiter">;</span> -<span id="L206" class="LineNr">206 </span> <span class="Delimiter">}</span> -<span id="L207" class="LineNr">207 </span> <span class="Delimiter">}</span> -<span id="L208" class="LineNr">208 </span> <span class="Delimiter">}</span> -<span id="L209" class="LineNr">209 </span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == <a href='010vm.cc.html#L175'>EXCLUSIVE_CONTAINER</a><span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L210" class="LineNr">210 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> tag = <span class="Constant">0</span><span class="Delimiter">;</span> tag < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++tag<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L211" class="LineNr">211 </span> set<tag_condition_info> new_key = key<span class="Delimiter">;</span> -<span id="L212" class="LineNr">212 </span> new_key<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>tag_condition_info<span class="Delimiter">(</span>base_offset<span class="Delimiter">,</span> tag<span class="Delimiter">));</span> -<span id="L213" class="LineNr">213 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>out<span class="Delimiter">,</span> new_key<span class="Delimiter">))</span> -<span id="L214" class="LineNr">214 </span> <a href='036refcount.cc.html#L160'>append_addresses</a><span class="Delimiter">(</span>base_offset+<span class="Comment">/*</span><span class="Comment">skip tag</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> variant_type<span class="Delimiter">(</span>type<span class="Delimiter">,</span> tag<span class="Delimiter">).</span>type<span class="Delimiter">,</span> out<span class="Delimiter">,</span> new_key<span class="Delimiter">,</span> location_for_error_messages<span class="Delimiter">);</span> -<span id="L215" class="LineNr">215 </span> <span class="Delimiter">}</span> -<span id="L216" class="LineNr">216 </span> <span class="Delimiter">}</span> -<span id="L217" class="LineNr">217 </span><span class="Delimiter">}</span> -<span id="L218" class="LineNr">218 </span> -<span id="L219" class="LineNr">219 </span><span class="Comment">//: for the following unit tests we'll do the work of the transform by hand</span> -<span id="L220" class="LineNr">220 </span> -<span id="L221" class="LineNr">221 </span><span class="Delimiter">:(before "End Unit Tests")</span> -<span id="L222" class="LineNr">222 </span><span class="Normal">void</span> <a href='036refcount.cc.html#L222'>test_container_address_offsets_empty</a><span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span id="L223" class="LineNr">223 </span> <span class="Normal">int</span> old_size = <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> -<span id="L224" class="LineNr">224 </span> <span class="Comment">// define a container with no addresses</span> -<span id="L225" class="LineNr">225 </span> reagent r<span class="Delimiter">(</span><span class="Constant">"x:point"</span><span class="Delimiter">);</span> -<span id="L226" class="LineNr">226 </span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> -<span id="L227" class="LineNr">227 </span> <span class="Comment">// scan</span> -<span id="L228" class="LineNr">228 </span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> -<span id="L229" class="LineNr">229 </span> <span class="Comment">// global metadata contains just the entry for foo</span> -<span id="L230" class="LineNr">230 </span> <span class="Comment">// no entries for non-container types or other junk</span> -<span id="L231" class="LineNr">231 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L232" class="LineNr">232 </span> <span class="Comment">// the reagent we scanned knows it has no addresses</span> -<span id="L233" class="LineNr">233 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">.</span>empty<span class="Delimiter">());</span> -<span id="L234" class="LineNr">234 </span> <span class="Comment">// the global table contains an identical entry</span> -<span id="L235" class="LineNr">235 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">));</span> -<span id="L236" class="LineNr">236 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">).</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">.</span>empty<span class="Delimiter">());</span> -<span id="L237" class="LineNr">237 </span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> -<span id="L238" class="LineNr">238 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L239" class="LineNr">239 </span><span class="Delimiter">}</span> -<span id="L240" class="LineNr">240 </span> -<span id="L241" class="LineNr">241 </span><span class="Normal">void</span> <a href='036refcount.cc.html#L241'>test_container_address_offsets</a><span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span id="L242" class="LineNr">242 </span> <span class="Normal">int</span> old_size = <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> -<span id="L243" class="LineNr">243 </span> <span class="Comment">// define a container with an address at offset 0 that we have the size for</span> -<span id="L244" class="LineNr">244 </span> run<span class="Delimiter">(</span><span class="Constant">"container foo [</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L245" class="LineNr">245 </span> <span class="Constant">" x:<a href='043space.cc.html#L80'>address</a>:num</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L246" class="LineNr">246 </span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> -<span id="L247" class="LineNr">247 </span> reagent r<span class="Delimiter">(</span><span class="Constant">"x:foo"</span><span class="Delimiter">);</span> -<span id="L248" class="LineNr">248 </span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> -<span id="L249" class="LineNr">249 </span> <span class="Comment">// scan</span> -<span id="L250" class="LineNr">250 </span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> -<span id="L251" class="LineNr">251 </span> <span class="Comment">// global metadata contains just the entry for foo</span> -<span id="L252" class="LineNr">252 </span> <span class="Comment">// no entries for non-container types or other junk</span> -<span id="L253" class="LineNr">253 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L254" class="LineNr">254 </span> <span class="Comment">// the reagent we scanned knows it has an address at offset 0</span> -<span id="L255" class="LineNr">255 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L256" class="LineNr">256 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">()));</span> -<span id="L257" class="LineNr">257 </span> <span class="Normal">const</span> set<address_element_info>& address_offsets = get<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">());</span> <span class="Comment">// unconditional for containers</span> -<span id="L258" class="LineNr">258 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>address_offsets<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L259" class="LineNr">259 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> -<span id="L260" class="LineNr">260 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>atom<span class="Delimiter">);</span> -<span id="L261" class="LineNr">261 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> -<span id="L262" class="LineNr">262 </span> <span class="Comment">// the global table contains an identical entry</span> -<span id="L263" class="LineNr">263 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">));</span> -<span id="L264" class="LineNr">264 </span> <span class="Normal">const</span> set<address_element_info>& address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">).</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">());</span> -<span id="L265" class="LineNr">265 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L266" class="LineNr">266 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> -<span id="L267" class="LineNr">267 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>atom<span class="Delimiter">);</span> -<span id="L268" class="LineNr">268 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> -<span id="L269" class="LineNr">269 </span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> -<span id="L270" class="LineNr">270 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L271" class="LineNr">271 </span><span class="Delimiter">}</span> -<span id="L272" class="LineNr">272 </span> -<span id="L273" class="LineNr">273 </span><span class="Normal">void</span> <a href='036refcount.cc.html#L273'>test_container_address_offsets_2</a><span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span id="L274" class="LineNr">274 </span> <span class="Normal">int</span> old_size = <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> -<span id="L275" class="LineNr">275 </span> <span class="Comment">// define a container with an address at offset 1 that we have the size for</span> -<span id="L276" class="LineNr">276 </span> run<span class="Delimiter">(</span><span class="Constant">"container foo [</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L277" class="LineNr">277 </span> <span class="Constant">" x:num</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L278" class="LineNr">278 </span> <span class="Constant">" y:<a href='043space.cc.html#L80'>address</a>:num</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L279" class="LineNr">279 </span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> -<span id="L280" class="LineNr">280 </span> reagent r<span class="Delimiter">(</span><span class="Constant">"x:foo"</span><span class="Delimiter">);</span> -<span id="L281" class="LineNr">281 </span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> -<span id="L282" class="LineNr">282 </span> <span class="Comment">// global metadata contains just the entry for foo</span> -<span id="L283" class="LineNr">283 </span> <span class="Comment">// no entries for non-container types or other junk</span> -<span id="L284" class="LineNr">284 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L285" class="LineNr">285 </span> <span class="Comment">// scan</span> -<span id="L286" class="LineNr">286 </span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> -<span id="L287" class="LineNr">287 </span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> -<span id="L288" class="LineNr">288 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L289" class="LineNr">289 </span> <span class="Comment">// the reagent we scanned knows it has an address at offset 1</span> -<span id="L290" class="LineNr">290 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L291" class="LineNr">291 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">()));</span> -<span id="L292" class="LineNr">292 </span> <span class="Normal">const</span> set<address_element_info>& address_offsets = get<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">());</span> -<span id="L293" class="LineNr">293 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>address_offsets<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L294" class="LineNr">294 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span>offset<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">//</span> -<span id="L295" class="LineNr">295 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>atom<span class="Delimiter">);</span> -<span id="L296" class="LineNr">296 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> -<span id="L297" class="LineNr">297 </span> <span class="Comment">// the global table contains an identical entry</span> -<span id="L298" class="LineNr">298 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">));</span> -<span id="L299" class="LineNr">299 </span> <span class="Normal">const</span> set<address_element_info>& address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">).</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">());</span> -<span id="L300" class="LineNr">300 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L301" class="LineNr">301 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span>offset<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">//</span> -<span id="L302" class="LineNr">302 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>atom<span class="Delimiter">);</span> -<span id="L303" class="LineNr">303 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> -<span id="L304" class="LineNr">304 </span><span class="Delimiter">}</span> -<span id="L305" class="LineNr">305 </span> -<span id="L306" class="LineNr">306 </span><span class="Normal">void</span> <a href='036refcount.cc.html#L306'>test_container_address_offsets_nested</a><span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span id="L307" class="LineNr">307 </span> <span class="Normal">int</span> old_size = <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> -<span id="L308" class="LineNr">308 </span> <span class="Comment">// define a container with a nested container containing an address</span> -<span id="L309" class="LineNr">309 </span> run<span class="Delimiter">(</span><span class="Constant">"container foo [</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L310" class="LineNr">310 </span> <span class="Constant">" x:<a href='043space.cc.html#L80'>address</a>:num</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L311" class="LineNr">311 </span> <span class="Constant">" y:num</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L312" class="LineNr">312 </span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L313" class="LineNr">313 </span> <span class="Constant">"container bar [</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L314" class="LineNr">314 </span> <span class="Constant">" p:point</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L315" class="LineNr">315 </span> <span class="Constant">" f:foo</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Comment">// nested container containing address</span> -<span id="L316" class="LineNr">316 </span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> -<span id="L317" class="LineNr">317 </span> reagent r<span class="Delimiter">(</span><span class="Constant">"x:bar"</span><span class="Delimiter">);</span> -<span id="L318" class="LineNr">318 </span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> -<span id="L319" class="LineNr">319 </span> <span class="Comment">// global metadata contains entries for bar and included types: point and foo</span> -<span id="L320" class="LineNr">320 </span> <span class="Comment">// no entries for non-container types or other junk</span> -<span id="L321" class="LineNr">321 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">3</span><span class="Delimiter">);</span> -<span id="L322" class="LineNr">322 </span> <span class="Comment">// scan</span> -<span id="L323" class="LineNr">323 </span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> -<span id="L324" class="LineNr">324 </span> <span class="Comment">// the reagent we scanned knows it has an address at offset 2</span> -<span id="L325" class="LineNr">325 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L326" class="LineNr">326 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">()));</span> -<span id="L327" class="LineNr">327 </span> <span class="Normal">const</span> set<address_element_info>& address_offsets = get<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">());</span> -<span id="L328" class="LineNr">328 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>address_offsets<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L329" class="LineNr">329 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span>offset<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">);</span> <span class="Comment">//</span> -<span id="L330" class="LineNr">330 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>atom<span class="Delimiter">);</span> -<span id="L331" class="LineNr">331 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> -<span id="L332" class="LineNr">332 </span> <span class="Comment">// the global table also knows its address offset</span> -<span id="L333" class="LineNr">333 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">));</span> -<span id="L334" class="LineNr">334 </span> <span class="Normal">const</span> set<address_element_info>& address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">).</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">());</span> -<span id="L335" class="LineNr">335 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L336" class="LineNr">336 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span>offset<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">);</span> <span class="Comment">//</span> -<span id="L337" class="LineNr">337 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>atom<span class="Delimiter">);</span> -<span id="L338" class="LineNr">338 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> -<span id="L339" class="LineNr">339 </span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> -<span id="L340" class="LineNr">340 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">3</span><span class="Delimiter">);</span> -<span id="L341" class="LineNr">341 </span><span class="Delimiter">}</span> -<span id="L342" class="LineNr">342 </span> -<span id="L343" class="LineNr">343 </span><span class="Normal">void</span> <a href='036refcount.cc.html#L343'>test_container_address_offsets_from_address</a><span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span id="L344" class="LineNr">344 </span> <span class="Normal">int</span> old_size = <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> -<span id="L345" class="LineNr">345 </span> <span class="Comment">// define a container with an address at offset 0</span> -<span id="L346" class="LineNr">346 </span> run<span class="Delimiter">(</span><span class="Constant">"container foo [</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L347" class="LineNr">347 </span> <span class="Constant">" x:<a href='043space.cc.html#L80'>address</a>:num</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L348" class="LineNr">348 </span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> -<span id="L349" class="LineNr">349 </span> reagent r<span class="Delimiter">(</span><span class="Constant">"x:<a href='043space.cc.html#L80'>address</a>:foo"</span><span class="Delimiter">);</span> -<span id="L350" class="LineNr">350 </span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> -<span id="L351" class="LineNr">351 </span> <span class="Comment">// global metadata contains just the entry for foo</span> -<span id="L352" class="LineNr">352 </span> <span class="Comment">// no entries for non-container types or other junk</span> -<span id="L353" class="LineNr">353 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L354" class="LineNr">354 </span> <span class="Comment">// scan an address to the container</span> -<span id="L355" class="LineNr">355 </span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> -<span id="L356" class="LineNr">356 </span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> -<span id="L357" class="LineNr">357 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L358" class="LineNr">358 </span> <span class="Comment">// scanning precomputed metadata for the container</span> -<span id="L359" class="LineNr">359 </span> reagent container<span class="Delimiter">(</span><span class="Constant">"x:foo"</span><span class="Delimiter">);</span> -<span id="L360" class="LineNr">360 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span> -<span id="L361" class="LineNr">361 </span> <span class="Normal">const</span> set<address_element_info>& address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">).</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">());</span> -<span id="L362" class="LineNr">362 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L363" class="LineNr">363 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> -<span id="L364" class="LineNr">364 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>atom<span class="Delimiter">);</span> -<span id="L365" class="LineNr">365 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> -<span id="L366" class="LineNr">366 </span><span class="Delimiter">}</span> -<span id="L367" class="LineNr">367 </span> -<span id="L368" class="LineNr">368 </span><span class="Normal">void</span> <a href='036refcount.cc.html#L368'>test_container_address_offsets_from_array</a><span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span id="L369" class="LineNr">369 </span> <span class="Normal">int</span> old_size = <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> -<span id="L370" class="LineNr">370 </span> <span class="Comment">// define a container with an address at offset 0</span> -<span id="L371" class="LineNr">371 </span> run<span class="Delimiter">(</span><span class="Constant">"container foo [</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L372" class="LineNr">372 </span> <span class="Constant">" x:<a href='043space.cc.html#L80'>address</a>:num</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L373" class="LineNr">373 </span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> -<span id="L374" class="LineNr">374 </span> reagent r<span class="Delimiter">(</span><span class="Constant">"x:array:foo"</span><span class="Delimiter">);</span> -<span id="L375" class="LineNr">375 </span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> -<span id="L376" class="LineNr">376 </span> <span class="Comment">// global metadata contains just the entry for foo</span> -<span id="L377" class="LineNr">377 </span> <span class="Comment">// no entries for non-container types or other junk</span> -<span id="L378" class="LineNr">378 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L379" class="LineNr">379 </span> <span class="Comment">// scan an array of the container</span> -<span id="L380" class="LineNr">380 </span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> -<span id="L381" class="LineNr">381 </span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> -<span id="L382" class="LineNr">382 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L383" class="LineNr">383 </span> <span class="Comment">// scanning precomputed metadata for the container</span> -<span id="L384" class="LineNr">384 </span> reagent container<span class="Delimiter">(</span><span class="Constant">"x:foo"</span><span class="Delimiter">);</span> -<span id="L385" class="LineNr">385 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span> -<span id="L386" class="LineNr">386 </span> <span class="Normal">const</span> set<address_element_info>& address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">).</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">());</span> -<span id="L387" class="LineNr">387 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L388" class="LineNr">388 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> -<span id="L389" class="LineNr">389 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>atom<span class="Delimiter">);</span> -<span id="L390" class="LineNr">390 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> -<span id="L391" class="LineNr">391 </span><span class="Delimiter">}</span> -<span id="L392" class="LineNr">392 </span> -<span id="L393" class="LineNr">393 </span><span class="Normal">void</span> <a href='036refcount.cc.html#L393'>test_container_address_offsets_from_address_to_array</a><span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span id="L394" class="LineNr">394 </span> <span class="Normal">int</span> old_size = <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> -<span id="L395" class="LineNr">395 </span> <span class="Comment">// define a container with an address at offset 0</span> -<span id="L396" class="LineNr">396 </span> run<span class="Delimiter">(</span><span class="Constant">"container foo [</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L397" class="LineNr">397 </span> <span class="Constant">" x:<a href='043space.cc.html#L80'>address</a>:num</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L398" class="LineNr">398 </span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> -<span id="L399" class="LineNr">399 </span> reagent r<span class="Delimiter">(</span><span class="Constant">"x:<a href='043space.cc.html#L80'>address</a>:array:foo"</span><span class="Delimiter">);</span> -<span id="L400" class="LineNr">400 </span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> -<span id="L401" class="LineNr">401 </span> <span class="Comment">// global metadata contains just the entry for foo</span> -<span id="L402" class="LineNr">402 </span> <span class="Comment">// no entries for non-container types or other junk</span> -<span id="L403" class="LineNr">403 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L404" class="LineNr">404 </span> <span class="Comment">// scan an address to an array of the container</span> -<span id="L405" class="LineNr">405 </span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> -<span id="L406" class="LineNr">406 </span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> -<span id="L407" class="LineNr">407 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L408" class="LineNr">408 </span> <span class="Comment">// scanning precomputed metadata for the container</span> -<span id="L409" class="LineNr">409 </span> reagent container<span class="Delimiter">(</span><span class="Constant">"x:foo"</span><span class="Delimiter">);</span> -<span id="L410" class="LineNr">410 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span> -<span id="L411" class="LineNr">411 </span> <span class="Normal">const</span> set<address_element_info>& address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">).</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">());</span> -<span id="L412" class="LineNr">412 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L413" class="LineNr">413 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> -<span id="L414" class="LineNr">414 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>atom<span class="Delimiter">);</span> -<span id="L415" class="LineNr">415 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> -<span id="L416" class="LineNr">416 </span><span class="Delimiter">}</span> -<span id="L417" class="LineNr">417 </span> -<span id="L418" class="LineNr">418 </span><span class="Normal">void</span> <a href='036refcount.cc.html#L418'>test_container_address_offsets_from_static_array</a><span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span id="L419" class="LineNr">419 </span> <span class="Normal">int</span> old_size = <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> -<span id="L420" class="LineNr">420 </span> <span class="Comment">// define a container with an address at offset 0</span> -<span id="L421" class="LineNr">421 </span> run<span class="Delimiter">(</span><span class="Constant">"container foo [</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L422" class="LineNr">422 </span> <span class="Constant">" x:<a href='043space.cc.html#L80'>address</a>:num</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L423" class="LineNr">423 </span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> -<span id="L424" class="LineNr">424 </span> reagent r<span class="Delimiter">(</span><span class="Constant">"x:array:foo:10"</span><span class="Delimiter">);</span> -<span id="L425" class="LineNr">425 </span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> -<span id="L426" class="LineNr">426 </span> <span class="Comment">// global metadata contains just the entry for foo</span> -<span id="L427" class="LineNr">427 </span> <span class="Comment">// no entries for non-container types or other junk</span> -<span id="L428" class="LineNr">428 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L429" class="LineNr">429 </span> <span class="Comment">// scan a static array of the container</span> -<span id="L430" class="LineNr">430 </span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> -<span id="L431" class="LineNr">431 </span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> -<span id="L432" class="LineNr">432 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L433" class="LineNr">433 </span> <span class="Comment">// scanning precomputed metadata for the container</span> -<span id="L434" class="LineNr">434 </span> reagent container<span class="Delimiter">(</span><span class="Constant">"x:foo"</span><span class="Delimiter">);</span> -<span id="L435" class="LineNr">435 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span> -<span id="L436" class="LineNr">436 </span> <span class="Normal">const</span> set<address_element_info>& address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">).</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">());</span> -<span id="L437" class="LineNr">437 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L438" class="LineNr">438 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> -<span id="L439" class="LineNr">439 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>atom<span class="Delimiter">);</span> -<span id="L440" class="LineNr">440 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> -<span id="L441" class="LineNr">441 </span><span class="Delimiter">}</span> -<span id="L442" class="LineNr">442 </span> -<span id="L443" class="LineNr">443 </span><span class="Normal">void</span> <a href='036refcount.cc.html#L443'>test_container_address_offsets_from_address_to_static_array</a><span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span id="L444" class="LineNr">444 </span> <span class="Normal">int</span> old_size = <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> -<span id="L445" class="LineNr">445 </span> <span class="Comment">// define a container with an address at offset 0</span> -<span id="L446" class="LineNr">446 </span> run<span class="Delimiter">(</span><span class="Constant">"container foo [</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L447" class="LineNr">447 </span> <span class="Constant">" x:<a href='043space.cc.html#L80'>address</a>:num</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L448" class="LineNr">448 </span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> -<span id="L449" class="LineNr">449 </span> reagent r<span class="Delimiter">(</span><span class="Constant">"x:<a href='043space.cc.html#L80'>address</a>:array:foo:10"</span><span class="Delimiter">);</span> -<span id="L450" class="LineNr">450 </span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> -<span id="L451" class="LineNr">451 </span> <span class="Comment">// global metadata contains just the entry for foo</span> -<span id="L452" class="LineNr">452 </span> <span class="Comment">// no entries for non-container types or other junk</span> -<span id="L453" class="LineNr">453 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L454" class="LineNr">454 </span> <span class="Comment">// scan an address to a static array of the container</span> -<span id="L455" class="LineNr">455 </span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> -<span id="L456" class="LineNr">456 </span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> -<span id="L457" class="LineNr">457 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L458" class="LineNr">458 </span> <span class="Comment">// scanning precomputed metadata for the container</span> -<span id="L459" class="LineNr">459 </span> reagent container<span class="Delimiter">(</span><span class="Constant">"x:foo"</span><span class="Delimiter">);</span> -<span id="L460" class="LineNr">460 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span> -<span id="L461" class="LineNr">461 </span> <span class="Normal">const</span> set<address_element_info>& address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">).</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">());</span> -<span id="L462" class="LineNr">462 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L463" class="LineNr">463 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> -<span id="L464" class="LineNr">464 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>atom<span class="Delimiter">);</span> -<span id="L465" class="LineNr">465 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> -<span id="L466" class="LineNr">466 </span><span class="Delimiter">}</span> -<span id="L467" class="LineNr">467 </span> -<span id="L468" class="LineNr">468 </span><span class="Normal">void</span> <a href='036refcount.cc.html#L468'>test_container_address_offsets_from_repeated_address_and_array_types</a><span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span id="L469" class="LineNr">469 </span> <span class="Normal">int</span> old_size = <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> -<span id="L470" class="LineNr">470 </span> <span class="Comment">// define a container with an address at offset 0</span> -<span id="L471" class="LineNr">471 </span> run<span class="Delimiter">(</span><span class="Constant">"container foo [</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L472" class="LineNr">472 </span> <span class="Constant">" x:<a href='043space.cc.html#L80'>address</a>:num</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L473" class="LineNr">473 </span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> -<span id="L474" class="LineNr">474 </span> <span class="Comment">// scan a deep nest of 'address' and 'array' types modifying a container</span> -<span id="L475" class="LineNr">475 </span> reagent r<span class="Delimiter">(</span><span class="Constant">"x:<a href='043space.cc.html#L80'>address</a>:array:<a href='043space.cc.html#L80'>address</a>:<a href='043space.cc.html#L80'>address</a>:array:foo:10"</span><span class="Delimiter">);</span> -<span id="L476" class="LineNr">476 </span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> -<span id="L477" class="LineNr">477 </span> <span class="Comment">// global metadata contains just the entry for foo</span> -<span id="L478" class="LineNr">478 </span> <span class="Comment">// no entries for non-container types or other junk</span> -<span id="L479" class="LineNr">479 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L480" class="LineNr">480 </span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> -<span id="L481" class="LineNr">481 </span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> -<span id="L482" class="LineNr">482 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L483" class="LineNr">483 </span> <span class="Comment">// scanning precomputed metadata for the container</span> -<span id="L484" class="LineNr">484 </span> reagent container<span class="Delimiter">(</span><span class="Constant">"x:foo"</span><span class="Delimiter">);</span> -<span id="L485" class="LineNr">485 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span> -<span id="L486" class="LineNr">486 </span> <span class="Normal">const</span> set<address_element_info>& address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">).</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">());</span> -<span id="L487" class="LineNr">487 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L488" class="LineNr">488 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> -<span id="L489" class="LineNr">489 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>atom<span class="Delimiter">);</span> -<span id="L490" class="LineNr">490 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> -<span id="L491" class="LineNr">491 </span><span class="Delimiter">}</span> -<span id="L492" class="LineNr">492 </span> -<span id="L493" class="LineNr">493 </span><span class="Delimiter">:(code)</span> -<span id="L494" class="LineNr">494 </span><span class="Normal">bool</span> <a href='036refcount.cc.html#L494'>all_match</a><span class="Delimiter">(</span><span class="Normal">const</span> vector<<span class="Normal">double</span>>& data<span class="Delimiter">,</span> <span class="Normal">const</span> set<tag_condition_info>& conditions<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L495" class="LineNr">495 </span> <span class="Normal">for</span> <span class="Delimiter">(</span>set<tag_condition_info>::const_iterator p = conditions<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != conditions<span class="Delimiter">.</span><a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L496" class="LineNr">496 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>data<span class="Delimiter">.</span>at<span class="Delimiter">(</span>p<span class="Delimiter">-></span>offset<span class="Delimiter">)</span> != p<span class="Delimiter">-></span>tag<span class="Delimiter">)</span> -<span id="L497" class="LineNr">497 </span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> -<span id="L498" class="LineNr">498 </span> <span class="Delimiter">}</span> -<span id="L499" class="LineNr">499 </span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> -<span id="L500" class="LineNr">500 </span><span class="Delimiter">}</span> -<span id="L501" class="LineNr">501 </span> -<span id="L502" class="LineNr">502 </span><span class="Normal">bool</span> is_mu_container<span class="Delimiter">(</span><span class="Normal">const</span> reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L503" class="LineNr">503 </span> <span class="Identifier">return</span> is_mu_container<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">);</span> -<span id="L504" class="LineNr">504 </span><span class="Delimiter">}</span> -<span id="L505" class="LineNr">505 </span><span class="Normal">bool</span> is_mu_container<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L506" class="LineNr">506 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> -<span id="L507" class="LineNr">507 </span> <span class="Comment">// End is_mu_container(type) Special-cases</span> -<span id="L508" class="LineNr">508 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-></span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> -<span id="L509" class="LineNr">509 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-></span>value<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// error raised elsewhere</span> -<span id="L510" class="LineNr">510 </span> type_info& info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> -<span id="L511" class="LineNr">511 </span> <span class="Identifier">return</span> info<span class="Delimiter">.</span>kind == <a href='010vm.cc.html#L174'>CONTAINER</a><span class="Delimiter">;</span> -<span id="L512" class="LineNr">512 </span><span class="Delimiter">}</span> -<span id="L513" class="LineNr">513 </span> -<span id="L514" class="LineNr">514 </span><span class="Normal">bool</span> is_mu_exclusive_container<span class="Delimiter">(</span><span class="Normal">const</span> reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L515" class="LineNr">515 </span> <span class="Identifier">return</span> is_mu_exclusive_container<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">);</span> -<span id="L516" class="LineNr">516 </span><span class="Delimiter">}</span> -<span id="L517" class="LineNr">517 </span><span class="Normal">bool</span> is_mu_exclusive_container<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L518" class="LineNr">518 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> -<span id="L519" class="LineNr">519 </span> <span class="Comment">// End is_mu_exclusive_container(type) Special-cases</span> -<span id="L520" class="LineNr">520 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-></span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> -<span id="L521" class="LineNr">521 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-></span>value<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// error raised elsewhere</span> -<span id="L522" class="LineNr">522 </span> type_info& info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> -<span id="L523" class="LineNr">523 </span> <span class="Identifier">return</span> info<span class="Delimiter">.</span>kind == <a href='010vm.cc.html#L175'>EXCLUSIVE_CONTAINER</a><span class="Delimiter">;</span> -<span id="L524" class="LineNr">524 </span><span class="Delimiter">}</span> +<span id="L1" class="LineNr"> 1 </span><span class="Normal">int</span> <a href='036refcount.cc.html#L1'>payload_size</a><span class="Delimiter">(</span>reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> x<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L2" class="LineNr"> 2 </span> x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> string_tree*><span class="Delimiter">(</span><span class="Constant">"lookup"</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> +<span id="L3" class="LineNr"> 3 </span> lookup_memory_core<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">check_for_null</span><span class="Comment">*/</span><span class="Constant">false</span><span class="Delimiter">);</span> +<span id="L4" class="LineNr"> 4 </span> <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>x<span class="Delimiter">);</span> +<span id="L5" class="LineNr"> 5 </span><span class="Delimiter">}</span> +<span id="L6" class="LineNr"> 6 </span> +<span id="L7" class="LineNr"> 7 </span><span class="Normal">bool</span> is_mu_container<span class="Delimiter">(</span><span class="Normal">const</span> reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L8" class="LineNr"> 8 </span> <span class="Identifier">return</span> is_mu_container<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">);</span> +<span id="L9" class="LineNr"> 9 </span><span class="Delimiter">}</span> +<span id="L10" class="LineNr">10 </span><span class="Normal">bool</span> is_mu_container<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L11" class="LineNr">11 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span id="L12" class="LineNr">12 </span> <span class="Comment">// End is_mu_container(type) Special-cases</span> +<span id="L13" class="LineNr">13 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-></span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span id="L14" class="LineNr">14 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-></span>value<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// error raised elsewhere</span> +<span id="L15" class="LineNr">15 </span> type_info& info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> +<span id="L16" class="LineNr">16 </span> <span class="Identifier">return</span> info<span class="Delimiter">.</span>kind == <a href='010vm.cc.html#L174'>CONTAINER</a><span class="Delimiter">;</span> +<span id="L17" class="LineNr">17 </span><span class="Delimiter">}</span> +<span id="L18" class="LineNr">18 </span> +<span id="L19" class="LineNr">19 </span><span class="Normal">bool</span> is_mu_exclusive_container<span class="Delimiter">(</span><span class="Normal">const</span> reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L20" class="LineNr">20 </span> <span class="Identifier">return</span> is_mu_exclusive_container<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">);</span> +<span id="L21" class="LineNr">21 </span><span class="Delimiter">}</span> +<span id="L22" class="LineNr">22 </span><span class="Normal">bool</span> is_mu_exclusive_container<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L23" class="LineNr">23 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span id="L24" class="LineNr">24 </span> <span class="Comment">// End is_mu_exclusive_container(type) Special-cases</span> +<span id="L25" class="LineNr">25 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-></span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span id="L26" class="LineNr">26 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-></span>value<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// error raised elsewhere</span> +<span id="L27" class="LineNr">27 </span> type_info& info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> +<span id="L28" class="LineNr">28 </span> <span class="Identifier">return</span> info<span class="Delimiter">.</span>kind == <a href='010vm.cc.html#L175'>EXCLUSIVE_CONTAINER</a><span class="Delimiter">;</span> +<span id="L29" class="LineNr">29 </span><span class="Delimiter">}</span> </pre> </body> </html> diff --git a/html/055shape_shifting_container.cc.html b/html/055shape_shifting_container.cc.html index fcff28ed..419864c4 100644 --- a/html/055shape_shifting_container.cc.html +++ b/html/055shape_shifting_container.cc.html @@ -87,12 +87,12 @@ if ('onhashchange' in window) { <span id="L22" class="LineNr"> 22 </span>base_type = get_base_type<span class="Delimiter">(</span>base_type<span class="Delimiter">);</span> <span id="L23" class="LineNr"> 23 </span><span class="Delimiter">:(after "Update base_type in element_type")</span> <span id="L24" class="LineNr"> 24 </span>base_type = get_base_type<span class="Delimiter">(</span>base_type<span class="Delimiter">);</span> -<span id="L25" class="LineNr"> 25 </span><span class="Delimiter">:(after "Update base_type in compute_container_address_offsets")</span> -<span id="L26" class="LineNr"> 26 </span>base_type = get_base_type<span class="Delimiter">(</span>base_type<span class="Delimiter">);</span> -<span id="L27" class="LineNr"> 27 </span><span class="Delimiter">:(after "Update base_type in append_container_address_offsets")</span> -<span id="L28" class="LineNr"> 28 </span>base_type = get_base_type<span class="Delimiter">(</span>base_type<span class="Delimiter">);</span> -<span id="L29" class="LineNr"> 29 </span><span class="Delimiter">:(after "Update element_base_type For Exclusive Container in append_addresses")</span> -<span id="L30" class="LineNr"> 30 </span>element_base_type = get_base_type<span class="Delimiter">(</span>element_base_type<span class="Delimiter">);</span> +<span id="L25" class="LineNr"> 25 </span><span class="CommentedCode">//? :(after "Update base_type in compute_container_address_offsets")</span> +<span id="L26" class="LineNr"> 26 </span><span class="CommentedCode">//? base_type = get_base_type(base_type);</span> +<span id="L27" class="LineNr"> 27 </span><span class="CommentedCode">//? :(after "Update base_type in append_container_address_offsets")</span> +<span id="L28" class="LineNr"> 28 </span><span class="CommentedCode">//? base_type = get_base_type(base_type);</span> +<span id="L29" class="LineNr"> 29 </span><span class="CommentedCode">//? :(after "Update element_base_type For Exclusive Container in append_addresses")</span> +<span id="L30" class="LineNr"> 30 </span><span class="CommentedCode">//? element_base_type = get_base_type(element_base_type);</span> <span id="L31" class="LineNr"> 31 </span><span class="Delimiter">:(after "Update base_type in skip_addresses")</span> <span id="L32" class="LineNr"> 32 </span>base_type = get_base_type<span class="Delimiter">(</span>base_type<span class="Delimiter">);</span> <span id="L33" class="LineNr"> 33 </span><span class="Delimiter">:(replace{} "const type_tree* get_base_type(const type_tree* t)")</span> @@ -385,9 +385,9 @@ if ('onhashchange' in window) { <span id="L320" class="LineNr">320 </span>replace_type_ingredients<span class="Delimiter">(</span>element<span class="Delimiter">,</span> full_type<span class="Delimiter">,</span> container_info<span class="Delimiter">,</span> location_for_error_messages<span class="Delimiter">);</span> <span id="L321" class="LineNr">321 </span><span class="Delimiter">:(before "Compute Exclusive Container Size(element, full_type)")</span> <span id="L322" class="LineNr">322 </span>replace_type_ingredients<span class="Delimiter">(</span>element<span class="Delimiter">,</span> full_type<span class="Delimiter">,</span> exclusive_container_info<span class="Delimiter">,</span> location_for_error_messages<span class="Delimiter">);</span> -<span id="L323" class="LineNr">323 </span><span class="Delimiter">:(before "Compute Container Address Offset(element)")</span> -<span id="L324" class="LineNr">324 </span>replace_type_ingredients<span class="Delimiter">(</span>element<span class="Delimiter">,</span> type<span class="Delimiter">,</span> info<span class="Delimiter">,</span> location_for_error_messages<span class="Delimiter">);</span> -<span id="L325" class="LineNr">325 </span><span class="Normal">if</span> <span class="Delimiter">(</span>contains_type_ingredient<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// error raised elsewhere</span> +<span id="L323" class="LineNr">323 </span><span class="CommentedCode">//? :(before "Compute Container Address Offset(element)")</span> +<span id="L324" class="LineNr">324 </span><span class="CommentedCode">//? replace_type_ingredients(element, type, info, location_for_error_messages);</span> +<span id="L325" class="LineNr">325 </span><span class="CommentedCode">//? if (contains_type_ingredient(element)) return; // error raised elsewhere</span> <span id="L326" class="LineNr">326 </span> <span id="L327" class="LineNr">327 </span><span class="Delimiter">:(after "Compute size_of Container")</span> <span id="L328" class="LineNr">328 </span>assert<span class="Delimiter">(</span>!contains_type_ingredient<span class="Delimiter">(</span>type<span class="Delimiter">));</span> @@ -680,160 +680,104 @@ if ('onhashchange' in window) { <span id="L615" class="LineNr">615 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>r2<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>size<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">);</span> <span id="L616" class="LineNr">616 </span><span class="Delimiter">}</span> <span id="L617" class="LineNr">617 </span> -<span id="L618" class="LineNr">618 </span><span class="Delimiter">:(before "End compute_container_address_offsets Non-atom Special-cases")</span> -<span id="L619" class="LineNr">619 </span><span class="Normal">const</span> type_tree* root = get_base_type<span class="Delimiter">(</span>type<span class="Delimiter">);</span> -<span id="L620" class="LineNr">620 </span><span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> root<span class="Delimiter">-></span>value<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// error raised elsewhere</span> -<span id="L621" class="LineNr">621 </span>type_info& info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> root<span class="Delimiter">-></span>value<span class="Delimiter">);</span> -<span id="L622" class="LineNr">622 </span><span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == <a href='010vm.cc.html#L174'>CONTAINER</a><span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L623" class="LineNr">623 </span> compute_container_address_offsets<span class="Delimiter">(</span>info<span class="Delimiter">,</span> type<span class="Delimiter">,</span> location_for_error_messages<span class="Delimiter">);</span> -<span id="L624" class="LineNr">624 </span> <span class="Identifier">return</span><span class="Delimiter">;</span> -<span id="L625" class="LineNr">625 </span><span class="Delimiter">}</span> -<span id="L626" class="LineNr">626 </span><span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == <a href='010vm.cc.html#L175'>EXCLUSIVE_CONTAINER</a><span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L627" class="LineNr">627 </span> <a href='036refcount.cc.html#L150'>compute_exclusive_container_address_offsets</a><span class="Delimiter">(</span>info<span class="Delimiter">,</span> type<span class="Delimiter">,</span> location_for_error_messages<span class="Delimiter">);</span> -<span id="L628" class="LineNr">628 </span> <span class="Identifier">return</span><span class="Delimiter">;</span> -<span id="L629" class="LineNr">629 </span><span class="Delimiter">}</span> -<span id="L630" class="LineNr">630 </span> -<span id="L631" class="LineNr">631 </span><span class="Delimiter">:(before "End Unit Tests")</span> -<span id="L632" class="LineNr">632 </span><span class="Normal">void</span> test_container_address_offsets_in_shape_shifting_container<span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span id="L633" class="LineNr">633 </span> run<span class="Delimiter">(</span><span class="Constant">"container foo:_t [</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L634" class="LineNr">634 </span> <span class="Constant">" x:num</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L635" class="LineNr">635 </span> <span class="Constant">" y:_t</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L636" class="LineNr">636 </span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> -<span id="L637" class="LineNr">637 </span> reagent r<span class="Delimiter">(</span><span class="Constant">"x:foo:&:num"</span><span class="Delimiter">);</span> -<span id="L638" class="LineNr">638 </span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> -<span id="L639" class="LineNr">639 </span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> -<span id="L640" class="LineNr">640 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L641" class="LineNr">641 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">()));</span> -<span id="L642" class="LineNr">642 </span> set<address_element_info>& offset_info = get<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">());</span> -<span id="L643" class="LineNr">643 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>offset_info<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L644" class="LineNr">644 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>offset_info<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span>offset<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">//</span> -<span id="L645" class="LineNr">645 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>offset_info<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>atom<span class="Delimiter">);</span> -<span id="L646" class="LineNr">646 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>offset_info<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> -<span id="L647" class="LineNr">647 </span><span class="Delimiter">}</span> -<span id="L648" class="LineNr">648 </span> -<span id="L649" class="LineNr">649 </span><span class="Normal">void</span> test_container_address_offsets_in_nested_shape_shifting_container<span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span id="L650" class="LineNr">650 </span> run<span class="Delimiter">(</span><span class="Constant">"container foo:_t [</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L651" class="LineNr">651 </span> <span class="Constant">" x:num</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L652" class="LineNr">652 </span> <span class="Constant">" y:_t</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L653" class="LineNr">653 </span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L654" class="LineNr">654 </span> <span class="Constant">"container bar:_t [</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L655" class="LineNr">655 </span> <span class="Constant">" x:_t</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L656" class="LineNr">656 </span> <span class="Constant">" y:foo:_t</span><span class="cSpecial">\n</span><span class="Constant">"</span> -<span id="L657" class="LineNr">657 </span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> -<span id="L658" class="LineNr">658 </span> reagent r<span class="Delimiter">(</span><span class="Constant">"x:bar:&:num"</span><span class="Delimiter">);</span> -<span id="L659" class="LineNr">659 </span> <a href='003trace.cc.html#L164'>CLEAR_TRACE</a><span class="Delimiter">;</span> -<span id="L660" class="LineNr">660 </span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> -<span id="L661" class="LineNr">661 </span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> -<span id="L662" class="LineNr">662 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L663" class="LineNr">663 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">()));</span> -<span id="L664" class="LineNr">664 </span> set<address_element_info>& offset_info = get<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span><a href='043space.cc.html#L80'>address</a><span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">());</span> -<span id="L665" class="LineNr">665 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>offset_info<span class="Delimiter">),</span> <span class="Constant">2</span><span class="Delimiter">);</span> -<span id="L666" class="LineNr">666 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>offset_info<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">//</span> -<span id="L667" class="LineNr">667 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">(</span>offset_info<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>atom<span class="Delimiter">);</span> -<span id="L668" class="LineNr">668 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">(</span>offset_info<span class="Delimiter">.</span>begin<span class="Delimiter">()-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> -<span id="L669" class="LineNr">669 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">((</span>++offset_info<span class="Delimiter">.</span>begin<span class="Delimiter">())-></span>offset<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">);</span> <span class="Comment">//</span> -<span id="L670" class="LineNr">670 </span> <a href='002test.cc.html#L24'>CHECK</a><span class="Delimiter">((</span>++offset_info<span class="Delimiter">.</span>begin<span class="Delimiter">())-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>atom<span class="Delimiter">);</span> -<span id="L671" class="LineNr">671 </span> <a href='002test.cc.html#L31'>CHECK_EQ</a><span class="Delimiter">((</span>++offset_info<span class="Delimiter">.</span>begin<span class="Delimiter">())-></span><a href='030container.cc.html#L238'>payload_type</a><span class="Delimiter">-></span>name<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> -<span id="L672" class="LineNr">672 </span><span class="Delimiter">}</span> -<span id="L673" class="LineNr">673 </span> -<span id="L674" class="LineNr">674 </span><span class="Delimiter">:(scenario typos_in_container_definitions)</span> -<span id="L675" class="LineNr">675 </span><span class="Special">% Hide_errors = true;</span> -<span id="L676" class="LineNr">676 </span><span class="muData">container</span> foo:_t [ -<span id="L677" class="LineNr">677 </span> <span class="Normal">x</span>:adress:_t <span class="Comment"># typo</span> -<span id="L678" class="LineNr">678 </span>] -<span id="L679" class="LineNr">679 </span><span class="muRecipe">def</span> <a href='000organization.cc.html#L113'>main</a> [ -<span id="L680" class="LineNr">680 </span> local-scope -<span id="L681" class="LineNr">681 </span> <span class="Normal">x</span>:<a href='043space.cc.html#L80'>address</a>:foo:num<span class="Special"> <- </span><span class="Normal">new</span> <span class="Delimiter">{(</span>foo num<span class="Delimiter">)</span>: type<span class="Delimiter">}</span> +<span id="L618" class="LineNr">618 </span><span class="Delimiter">:(scenario typos_in_container_definitions)</span> +<span id="L619" class="LineNr">619 </span><span class="Special">% Hide_errors = true;</span> +<span id="L620" class="LineNr">620 </span><span class="muData">container</span> foo:_t [ +<span id="L621" class="LineNr">621 </span> <span class="Normal">x</span>:adress:_t <span class="Comment"># typo</span> +<span id="L622" class="LineNr">622 </span>] +<span id="L623" class="LineNr">623 </span><span class="muRecipe">def</span> <a href='000organization.cc.html#L113'>main</a> [ +<span id="L624" class="LineNr">624 </span> local-scope +<span id="L625" class="LineNr">625 </span> <span class="Normal">x</span>:<a href='043space.cc.html#L80'>address</a>:foo:num<span class="Special"> <- </span><span class="Normal">new</span> <span class="Delimiter">{(</span>foo num<span class="Delimiter">)</span>: type<span class="Delimiter">}</span> +<span id="L626" class="LineNr">626 </span>] +<span id="L627" class="LineNr">627 </span><span class="Comment"># no crash</span> +<span id="L628" class="LineNr">628 </span> +<span id="L629" class="LineNr">629 </span><span class="Delimiter">:(scenario typos_in_recipes)</span> +<span id="L630" class="LineNr">630 </span><span class="Special">% Hide_errors = true;</span> +<span id="L631" class="LineNr">631 </span><span class="muRecipe">def</span> foo [ +<span id="L632" class="LineNr">632 </span> local-scope +<span id="L633" class="LineNr">633 </span> <span class="Normal">x</span>:adress:array:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># typo</span> +<span id="L634" class="LineNr">634 </span>] +<span id="L635" class="LineNr">635 </span><span class="Comment"># shouldn't crash</span> +<span id="L636" class="LineNr">636 </span> +<span id="L637" class="LineNr">637 </span><span class="SalientComment">//:: 'merge' on shape-shifting containers</span> +<span id="L638" class="LineNr">638 </span> +<span id="L639" class="LineNr">639 </span><span class="Delimiter">:(scenario merge_check_shape_shifting_container_containing_exclusive_container)</span> +<span id="L640" class="LineNr">640 </span><span class="muData">container</span> foo:_elem [ +<span id="L641" class="LineNr">641 </span> <span class="Normal">x</span>:num +<span id="L642" class="LineNr">642 </span> <span class="Normal">y</span>:_elem +<span id="L643" class="LineNr">643 </span>] +<span id="L644" class="LineNr">644 </span><span class="muData">exclusive-container</span> bar [ +<span id="L645" class="LineNr">645 </span> <span class="Normal">x</span>:num +<span id="L646" class="LineNr">646 </span> <span class="Normal">y</span>:num +<span id="L647" class="LineNr">647 </span>] +<span id="L648" class="LineNr">648 </span><span class="muRecipe">def</span> <a href='000organization.cc.html#L113'>main</a> [ +<span id="L649" class="LineNr">649 </span> <span class="Constant">1</span>:foo:bar<span class="Special"> <- </span>merge <span class="Constant">23</span><span class="Delimiter">,</span> <span class="Constant">1</span>/y<span class="Delimiter">,</span> <span class="Constant">34</span> +<span id="L650" class="LineNr">650 </span>] +<span id="L651" class="LineNr">651 </span><span class="traceContains">+mem: storing 23 in location 1</span> +<span id="L652" class="LineNr">652 </span><span class="traceContains">+mem: storing 1 in location 2</span> +<span id="L653" class="LineNr">653 </span><span class="traceContains">+mem: storing 34 in location 3</span> +<span id="L654" class="LineNr">654 </span>$error: <span class="Constant">0</span> +<span id="L655" class="LineNr">655 </span> +<span id="L656" class="LineNr">656 </span><span class="Delimiter">:(scenario merge_check_shape_shifting_container_containing_exclusive_container_2)</span> +<span id="L657" class="LineNr">657 </span><span class="Special">% Hide_errors = true;</span> +<span id="L658" class="LineNr">658 </span><span class="muData">container</span> foo:_elem [ +<span id="L659" class="LineNr">659 </span> <span class="Normal">x</span>:num +<span id="L660" class="LineNr">660 </span> <span class="Normal">y</span>:_elem +<span id="L661" class="LineNr">661 </span>] +<span id="L662" class="LineNr">662 </span><span class="muData">exclusive-container</span> bar [ +<span id="L663" class="LineNr">663 </span> <span class="Normal">x</span>:num +<span id="L664" class="LineNr">664 </span> <span class="Normal">y</span>:num +<span id="L665" class="LineNr">665 </span>] +<span id="L666" class="LineNr">666 </span><span class="muRecipe">def</span> <a href='000organization.cc.html#L113'>main</a> [ +<span id="L667" class="LineNr">667 </span> <span class="Constant">1</span>:foo:bar<span class="Special"> <- </span>merge <span class="Constant">23</span><span class="Delimiter">,</span> <span class="Constant">1</span>/y<span class="Delimiter">,</span> <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">35</span> +<span id="L668" class="LineNr">668 </span>] +<span id="L669" class="LineNr">669 </span><span class="traceContains">+error: <a href='000organization.cc.html#L113'>main</a>: too many ingredients in '1:foo:bar <- merge 23, 1/y, 34, 35'</span> +<span id="L670" class="LineNr">670 </span> +<span id="L671" class="LineNr">671 </span><span class="Delimiter">:(scenario merge_check_shape_shifting_exclusive_container_containing_container)</span> +<span id="L672" class="LineNr">672 </span><span class="muData">exclusive-container</span> foo:_elem [ +<span id="L673" class="LineNr">673 </span> <span class="Normal">x</span>:num +<span id="L674" class="LineNr">674 </span> <span class="Normal">y</span>:_elem +<span id="L675" class="LineNr">675 </span>] +<span id="L676" class="LineNr">676 </span><span class="muData">container</span> bar [ +<span id="L677" class="LineNr">677 </span> <span class="Normal">x</span>:num +<span id="L678" class="LineNr">678 </span> <span class="Normal">y</span>:num +<span id="L679" class="LineNr">679 </span>] +<span id="L680" class="LineNr">680 </span><span class="muRecipe">def</span> <a href='000organization.cc.html#L113'>main</a> [ +<span id="L681" class="LineNr">681 </span> <span class="Constant">1</span>:foo:bar<span class="Special"> <- </span>merge <span class="Constant">1</span>/y<span class="Delimiter">,</span> <span class="Constant">23</span><span class="Delimiter">,</span> <span class="Constant">34</span> <span id="L682" class="LineNr">682 </span>] -<span id="L683" class="LineNr">683 </span><span class="Comment"># no crash</span> -<span id="L684" class="LineNr">684 </span> -<span id="L685" class="LineNr">685 </span><span class="Delimiter">:(scenario typos_in_recipes)</span> -<span id="L686" class="LineNr">686 </span><span class="Special">% Hide_errors = true;</span> -<span id="L687" class="LineNr">687 </span><span class="muRecipe">def</span> foo [ -<span id="L688" class="LineNr">688 </span> local-scope -<span id="L689" class="LineNr">689 </span> <span class="Normal">x</span>:adress:array:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># typo</span> -<span id="L690" class="LineNr">690 </span>] -<span id="L691" class="LineNr">691 </span><span class="Comment"># shouldn't crash</span> -<span id="L692" class="LineNr">692 </span> -<span id="L693" class="LineNr">693 </span><span class="SalientComment">//:: 'merge' on shape-shifting containers</span> -<span id="L694" class="LineNr">694 </span> -<span id="L695" class="LineNr">695 </span><span class="Delimiter">:(scenario merge_check_shape_shifting_container_containing_exclusive_container)</span> -<span id="L696" class="LineNr">696 </span><span class="muData">container</span> foo:_elem [ -<span id="L697" class="LineNr">697 </span> <span class="Normal">x</span>:num -<span id="L698" class="LineNr">698 </span> <span class="Normal">y</span>:_elem +<span id="L683" class="LineNr">683 </span><span class="traceContains">+mem: storing 1 in location 1</span> +<span id="L684" class="LineNr">684 </span><span class="traceContains">+mem: storing 23 in location 2</span> +<span id="L685" class="LineNr">685 </span><span class="traceContains">+mem: storing 34 in location 3</span> +<span id="L686" class="LineNr">686 </span>$error: <span class="Constant">0</span> +<span id="L687" class="LineNr">687 </span> +<span id="L688" class="LineNr">688 </span><span class="Delimiter">:(scenario merge_check_shape_shifting_exclusive_container_containing_container_2)</span> +<span id="L689" class="LineNr">689 </span><span class="muData">exclusive-container</span> foo:_elem [ +<span id="L690" class="LineNr">690 </span> <span class="Normal">x</span>:num +<span id="L691" class="LineNr">691 </span> <span class="Normal">y</span>:_elem +<span id="L692" class="LineNr">692 </span>] +<span id="L693" class="LineNr">693 </span><span class="muData">container</span> bar [ +<span id="L694" class="LineNr">694 </span> <span class="Normal">x</span>:num +<span id="L695" class="LineNr">695 </span> <span class="Normal">y</span>:num +<span id="L696" class="LineNr">696 </span>] +<span id="L697" class="LineNr">697 </span><span class="muRecipe">def</span> <a href='000organization.cc.html#L113'>main</a> [ +<span id="L698" class="LineNr">698 </span> <span class="Constant">1</span>:foo:bar<span class="Special"> <- </span>merge <span class="Constant">0</span>/x<span class="Delimiter">,</span> <span class="Constant">23</span> <span id="L699" class="LineNr">699 </span>] -<span id="L700" class="LineNr">700 </span><span class="muData">exclusive-container</span> bar [ -<span id="L701" class="LineNr">701 </span> <span class="Normal">x</span>:num -<span id="L702" class="LineNr">702 </span> <span class="Normal">y</span>:num -<span id="L703" class="LineNr">703 </span>] -<span id="L704" class="LineNr">704 </span><span class="muRecipe">def</span> <a href='000organization.cc.html#L113'>main</a> [ -<span id="L705" class="LineNr">705 </span> <span class="Constant">1</span>:foo:bar<span class="Special"> <- </span>merge <span class="Constant">23</span><span class="Delimiter">,</span> <span class="Constant">1</span>/y<span class="Delimiter">,</span> <span class="Constant">34</span> -<span id="L706" class="LineNr">706 </span>] -<span id="L707" class="LineNr">707 </span><span class="traceContains">+mem: storing 23 in location 1</span> -<span id="L708" class="LineNr">708 </span><span class="traceContains">+mem: storing 1 in location 2</span> -<span id="L709" class="LineNr">709 </span><span class="traceContains">+mem: storing 34 in location 3</span> -<span id="L710" class="LineNr">710 </span>$error: <span class="Constant">0</span> -<span id="L711" class="LineNr">711 </span> -<span id="L712" class="LineNr">712 </span><span class="Delimiter">:(scenario merge_check_shape_shifting_container_containing_exclusive_container_2)</span> -<span id="L713" class="LineNr">713 </span><span class="Special">% Hide_errors = true;</span> -<span id="L714" class="LineNr">714 </span><span class="muData">container</span> foo:_elem [ -<span id="L715" class="LineNr">715 </span> <span class="Normal">x</span>:num -<span id="L716" class="LineNr">716 </span> <span class="Normal">y</span>:_elem -<span id="L717" class="LineNr">717 </span>] -<span id="L718" class="LineNr">718 </span><span class="muData">exclusive-container</span> bar [ -<span id="L719" class="LineNr">719 </span> <span class="Normal">x</span>:num -<span id="L720" class="LineNr">720 </span> <span class="Normal">y</span>:num -<span id="L721" class="LineNr">721 </span>] -<span id="L722" class="LineNr">722 </span><span class="muRecipe">def</span> <a href='000organization.cc.html#L113'>main</a> [ -<span id="L723" class="LineNr">723 </span> <span class="Constant">1</span>:foo:bar<span class="Special"> <- </span>merge <span class="Constant">23</span><span class="Delimiter">,</span> <span class="Constant">1</span>/y<span class="Delimiter">,</span> <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">35</span> -<span id="L724" class="LineNr">724 </span>] -<span id="L725" class="LineNr">725 </span><span class="traceContains">+error: <a href='000organization.cc.html#L113'>main</a>: too many ingredients in '1:foo:bar <- merge 23, 1/y, 34, 35'</span> -<span id="L726" class="LineNr">726 </span> -<span id="L727" class="LineNr">727 </span><span class="Delimiter">:(scenario merge_check_shape_shifting_exclusive_container_containing_container)</span> -<span id="L728" class="LineNr">728 </span><span class="muData">exclusive-container</span> foo:_elem [ -<span id="L729" class="LineNr">729 </span> <span class="Normal">x</span>:num -<span id="L730" class="LineNr">730 </span> <span class="Normal">y</span>:_elem -<span id="L731" class="LineNr">731 </span>] -<span id="L732" class="LineNr">732 </span><span class="muData">container</span> bar [ -<span id="L733" class="LineNr">733 </span> <span class="Normal">x</span>:num -<span id="L734" class="LineNr">734 </span> <span class="Normal">y</span>:num -<span id="L735" class="LineNr">735 </span>] -<span id="L736" class="LineNr">736 </span><span class="muRecipe">def</span> <a href='000organization.cc.html#L113'>main</a> [ -<span id="L737" class="LineNr">737 </span> <span class="Constant">1</span>:foo:bar<span class="Special"> <- </span>merge <span class="Constant">1</span>/y<span class="Delimiter">,</span> <span class="Constant">23</span><span class="Delimiter">,</span> <span class="Constant">34</span> -<span id="L738" class="LineNr">738 </span>] -<span id="L739" class="LineNr">739 </span><span class="traceContains">+mem: storing 1 in location 1</span> -<span id="L740" class="LineNr">740 </span><span class="traceContains">+mem: storing 23 in location 2</span> -<span id="L741" class="LineNr">741 </span><span class="traceContains">+mem: storing 34 in location 3</span> -<span id="L742" class="LineNr">742 </span>$error: <span class="Constant">0</span> -<span id="L743" class="LineNr">743 </span> -<span id="L744" class="LineNr">744 </span><span class="Delimiter">:(scenario merge_check_shape_shifting_exclusive_container_containing_container_2)</span> -<span id="L745" class="LineNr">745 </span><span class="muData">exclusive-container</span> foo:_elem [ -<span id="L746" class="LineNr">746 </span> <span class="Normal">x</span>:num -<span id="L747" class="LineNr">747 </span> <span class="Normal">y</span>:_elem -<span id="L748" class="LineNr">748 </span>] -<span id="L749" class="LineNr">749 </span><span class="muData">container</span> bar [ -<span id="L750" class="LineNr">750 </span> <span class="Normal">x</span>:num -<span id="L751" class="LineNr">751 </span> <span class="Normal">y</span>:num -<span id="L752" class="LineNr">752 </span>] -<span id="L753" class="LineNr">753 </span><span class="muRecipe">def</span> <a href='000organization.cc.html#L113'>main</a> [ -<span id="L754" class="LineNr">754 </span> <span class="Constant">1</span>:foo:bar<span class="Special"> <- </span>merge <span class="Constant">0</span>/x<span class="Delimiter">,</span> <span class="Constant">23</span> -<span id="L755" class="LineNr">755 </span>] -<span id="L756" class="LineNr">756 </span>$error: <span class="Constant">0</span> -<span id="L757" class="LineNr">757 </span> -<span id="L758" class="LineNr">758 </span><span class="Delimiter">:(scenario merge_check_shape_shifting_exclusive_container_containing_container_3)</span> -<span id="L759" class="LineNr">759 </span><span class="Special">% Hide_errors = true;</span> -<span id="L760" class="LineNr">760 </span><span class="muData">exclusive-container</span> foo:_elem [ -<span id="L761" class="LineNr">761 </span> <span class="Normal">x</span>:num -<span id="L762" class="LineNr">762 </span> <span class="Normal">y</span>:_elem -<span id="L763" class="LineNr">763 </span>] -<span id="L764" class="LineNr">764 </span><span class="muData">container</span> bar [ -<span id="L765" class="LineNr">765 </span> <span class="Normal">x</span>:num -<span id="L766" class="LineNr">766 </span> <span class="Normal">y</span>:num -<span id="L767" class="LineNr">767 </span>] -<span id="L768" class="LineNr">768 </span><span class="muRecipe">def</span> <a href='000organization.cc.html#L113'>main</a> [ -<span id="L769" class="LineNr">769 </span> <span class="Constant">1</span>:foo:bar<span class="Special"> <- </span>merge <span class="Constant">1</span>/y<span class="Delimiter">,</span> <span class="Constant">23</span> -<span id="L770" class="LineNr">770 </span>] -<span id="L771" class="LineNr">771 </span><span class="traceContains">+error: <a href='000organization.cc.html#L113'>main</a>: too few ingredients in '1:foo:bar <- merge 1/y, 23'</span> +<span id="L700" class="LineNr">700 </span>$error: <span class="Constant">0</span> +<span id="L701" class="LineNr">701 </span> +<span id="L702" class="LineNr">702 </span><span class="Delimiter">:(scenario merge_check_shape_shifting_exclusive_container_containing_container_3)</span> +<span id="L703" class="LineNr">703 </span><span class="Special">% Hide_errors = true;</span> +<span id="L704" class="LineNr">704 </span><span class="muData">exclusive-container</span> foo:_elem [ +<span id="L705" class="LineNr">705 </span> <span class="Normal">x</span>:num +<span id="L706" class="LineNr">706 </span> <span class="Normal">y</span>:_elem +<span id="L707" class="LineNr">707 </span>] +<span id="L708" class="LineNr">708 </span><span class="muData">container</span> bar [ +<span id="L709" class="LineNr">709 </span> <span class="Normal">x</span>:num +<span id="L710" class="LineNr">710 </span> <span class="Normal">y</span>:num +<span id="L711" class="LineNr">711 </span>] +<span id="L712" class="LineNr">712 </span><span class="muRecipe">def</span> <a href='000organization.cc.html#L113'>main</a> [ +<span id="L713" class="LineNr">713 </span> <span class="Constant">1</span>:foo:bar<span class="Special"> <- </span>merge <span class="Constant">1</span>/y<span class="Delimiter">,</span> <span class="Constant">23</span> +<span id="L714" class="LineNr">714 </span>] +<span id="L715" class="LineNr">715 </span><span class="traceContains">+error: <a href='000organization.cc.html#L113'>main</a>: too few ingredients in '1:foo:bar <- merge 1/y, 23'</span> </pre> </body> </html> diff --git a/html/061text.mu.html b/html/061text.mu.html index 1cf8aa34..d069e621 100644 --- a/html/061text.mu.html +++ b/html/061text.mu.html @@ -183,17 +183,17 @@ if ('onhashchange' in window) { <span id="L122" class="LineNr"> 122 </span> data:&:@:_elem <span id="L123" class="LineNr"> 123 </span>] <span id="L124" class="LineNr"> 124 </span> -<span id="L125" class="LineNr"> 125 </span><span class="muRecipe">def</span> <a href='061text.mu.html#L125'>new-buffer</a> <a href='075channel.mu.html#L399'>capacity</a>:num<span class="muRecipe"> -> </span>result:&:<a href='061text.mu.html#L120'>buffer</a>:_elem [ +<span id="L125" class="LineNr"> 125 </span><span class="muRecipe">def</span> <a href='061text.mu.html#L125'>new-buffer</a> <a href='075channel.mu.html#L391'>capacity</a>:num<span class="muRecipe"> -> </span>result:&:<a href='061text.mu.html#L120'>buffer</a>:_elem [ <span id="L126" class="LineNr"> 126 </span> <span class="Constant">local-scope</span> <span id="L127" class="LineNr"> 127 </span> <span class="Constant">load-inputs</span> <span id="L128" class="LineNr"> 128 </span> result <span class="Special"><-</span> new <span class="Delimiter">{</span>(buffer _elem): type<span class="Delimiter">}</span> <span id="L129" class="LineNr"> 129 </span> *result <span class="Special"><-</span> put *result, <span class="Constant">length:offset</span>,<span class="Constant"> 0</span> <span id="L130" class="LineNr"> 130 </span> <span class="Delimiter">{</span> -<span id="L131" class="LineNr"> 131 </span> <span class="muControl">break-if</span> <a href='075channel.mu.html#L399'>capacity</a> +<span id="L131" class="LineNr"> 131 </span> <span class="muControl">break-if</span> <a href='075channel.mu.html#L391'>capacity</a> <span id="L132" class="LineNr"> 132 </span> <span class="Comment"># capacity not provided</span> -<span id="L133" class="LineNr"> 133 </span> <a href='075channel.mu.html#L399'>capacity</a> <span class="Special"><-</span> copy<span class="Constant"> 10</span> +<span id="L133" class="LineNr"> 133 </span> <a href='075channel.mu.html#L391'>capacity</a> <span class="Special"><-</span> copy<span class="Constant"> 10</span> <span id="L134" class="LineNr"> 134 </span> <span class="Delimiter">}</span> -<span id="L135" class="LineNr"> 135 </span> data:&:@:_elem <span class="Special"><-</span> new <span class="Constant">_elem:type</span>, <a href='075channel.mu.html#L399'>capacity</a> +<span id="L135" class="LineNr"> 135 </span> data:&:@:_elem <span class="Special"><-</span> new <span class="Constant">_elem:type</span>, <a href='075channel.mu.html#L391'>capacity</a> <span id="L136" class="LineNr"> 136 </span> *result <span class="Special"><-</span> put *result, <span class="Constant">data:offset</span>, data <span id="L137" class="LineNr"> 137 </span> <span class="muControl"> return</span> result <span id="L138" class="LineNr"> 138 </span>] @@ -224,8 +224,8 @@ if ('onhashchange' in window) { <span id="L163" class="LineNr"> 163 </span> <span class="Constant">load-inputs</span> <span id="L164" class="LineNr"> 164 </span> len:num <span class="Special"><-</span> get *in, <span class="Constant">length:offset</span> <span id="L165" class="LineNr"> 165 </span> s:&:@:_elem <span class="Special"><-</span> get *in, <span class="Constant">data:offset</span> -<span id="L166" class="LineNr"> 166 </span> <a href='075channel.mu.html#L399'>capacity</a>:num <span class="Special"><-</span> length *s -<span id="L167" class="LineNr"> 167 </span> result <span class="Special"><-</span> greater-or-equal len, <a href='075channel.mu.html#L399'>capacity</a> +<span id="L166" class="LineNr"> 166 </span> <a href='075channel.mu.html#L391'>capacity</a>:num <span class="Special"><-</span> length *s +<span id="L167" class="LineNr"> 167 </span> result <span class="Special"><-</span> greater-or-equal len, <a href='075channel.mu.html#L391'>capacity</a> <span id="L168" class="LineNr"> 168 </span>] <span id="L169" class="LineNr"> 169 </span> <span id="L170" class="LineNr"> 170 </span><span class="Comment"># most broadly applicable definition of append to a buffer</span> diff --git a/html/063array.mu.html b/html/063array.mu.html index 80244daf..e194f20a 100644 --- a/html/063array.mu.html +++ b/html/063array.mu.html @@ -75,20 +75,20 @@ if ('onhashchange' in window) { <span id="L15" class="LineNr"> 15 </span><span class="Comment"># create an array out of a list of args</span> <span id="L16" class="LineNr"> 16 </span><span class="muRecipe">def</span> <a href='063array.mu.html#L16'>new-array</a><span class="muRecipe"> -> </span>result:&:@:_elem [ <span id="L17" class="LineNr"> 17 </span> <span class="Constant">local-scope</span> -<span id="L18" class="LineNr"> 18 </span> <a href='075channel.mu.html#L399'>capacity</a>:num <span class="Special"><-</span> copy<span class="Constant"> 0</span> +<span id="L18" class="LineNr"> 18 </span> <a href='075channel.mu.html#L391'>capacity</a>:num <span class="Special"><-</span> copy<span class="Constant"> 0</span> <span id="L19" class="LineNr"> 19 </span> <span class="Delimiter">{</span> <span id="L20" class="LineNr"> 20 </span> <span class="Comment"># while read curr-value</span> <span id="L21" class="LineNr"> 21 </span> curr-value:_elem, exists?:bool <span class="Special"><-</span> <span class="Constant">next-input</span> <span id="L22" class="LineNr"> 22 </span> <span class="muControl">break-unless</span> exists? -<span id="L23" class="LineNr"> 23 </span> <a href='075channel.mu.html#L399'>capacity</a> <span class="Special"><-</span> add <a href='075channel.mu.html#L399'>capacity</a>,<span class="Constant"> 1</span> +<span id="L23" class="LineNr"> 23 </span> <a href='075channel.mu.html#L391'>capacity</a> <span class="Special"><-</span> add <a href='075channel.mu.html#L391'>capacity</a>,<span class="Constant"> 1</span> <span id="L24" class="LineNr"> 24 </span> <span class="muControl"> loop</span> <span id="L25" class="LineNr"> 25 </span> <span class="Delimiter">}</span> -<span id="L26" class="LineNr"> 26 </span> result <span class="Special"><-</span> new <span class="Constant">_elem:type</span>, <a href='075channel.mu.html#L399'>capacity</a> +<span id="L26" class="LineNr"> 26 </span> result <span class="Special"><-</span> new <span class="Constant">_elem:type</span>, <a href='075channel.mu.html#L391'>capacity</a> <span id="L27" class="LineNr"> 27 </span> <span class="Constant">rewind-inputs</span> <span id="L28" class="LineNr"> 28 </span> i:num <span class="Special"><-</span> copy<span class="Constant"> 0</span> <span id="L29" class="LineNr"> 29 </span> <span class="Delimiter">{</span> <span id="L30" class="LineNr"> 30 </span> <span class="Comment"># while read curr-value</span> -<span id="L31" class="LineNr"> 31 </span> done?:bool <span class="Special"><-</span> greater-or-equal i, <a href='075channel.mu.html#L399'>capacity</a> +<span id="L31" class="LineNr"> 31 </span> done?:bool <span class="Special"><-</span> greater-or-equal i, <a href='075channel.mu.html#L391'>capacity</a> <span id="L32" class="LineNr"> 32 </span> <span class="muControl">break-if</span> done? <span id="L33" class="LineNr"> 33 </span> curr-value:_elem, exists?:bool <span class="Special"><-</span> <span class="Constant">next-input</span> <span id="L34" class="LineNr"> 34 </span> assert exists?, <span class="Constant">[error in rewinding inputs to new-array]</span> diff --git a/html/068random.mu.html b/html/068random.mu.html index 1c2d47fc..accb90a3 100644 --- a/html/068random.mu.html +++ b/html/068random.mu.html @@ -97,11 +97,11 @@ if ('onhashchange' in window) { <span id="L37" class="LineNr">37 </span> <span id="L38" class="LineNr">38 </span><span class="muScenario">scenario</span> random-numbers-in-scenario [ <span id="L39" class="LineNr">39 </span> <span class="Constant">local-scope</span> -<span id="L40" class="LineNr">40 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='066stream.mu.html#L2'>stream</a>:num <span class="Special"><-</span> <a href='068random.mu.html#L14'>assume-random-numbers</a><span class="Constant"> 34</span>,<span class="Constant"> 35</span>,<span class="Constant"> 37</span> -<span id="L41" class="LineNr">41 </span> 1:num/<span class="Special">raw</span>, 2:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='068random.mu.html#L1'>random</a> <a href='075channel.mu.html#L43'>source</a> -<span id="L42" class="LineNr">42 </span> 3:num/<span class="Special">raw</span>, 4:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='068random.mu.html#L1'>random</a> <a href='075channel.mu.html#L43'>source</a> -<span id="L43" class="LineNr">43 </span> 5:num/<span class="Special">raw</span>, 6:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='068random.mu.html#L1'>random</a> <a href='075channel.mu.html#L43'>source</a> -<span id="L44" class="LineNr">44 </span> 7:num/<span class="Special">raw</span>, 8:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='068random.mu.html#L1'>random</a> <a href='075channel.mu.html#L43'>source</a> +<span id="L40" class="LineNr">40 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='066stream.mu.html#L2'>stream</a>:num <span class="Special"><-</span> <a href='068random.mu.html#L14'>assume-random-numbers</a><span class="Constant"> 34</span>,<span class="Constant"> 35</span>,<span class="Constant"> 37</span> +<span id="L41" class="LineNr">41 </span> 1:num/<span class="Special">raw</span>, 2:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='068random.mu.html#L1'>random</a> <a href='075channel.mu.html#L36'>source</a> +<span id="L42" class="LineNr">42 </span> 3:num/<span class="Special">raw</span>, 4:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='068random.mu.html#L1'>random</a> <a href='075channel.mu.html#L36'>source</a> +<span id="L43" class="LineNr">43 </span> 5:num/<span class="Special">raw</span>, 6:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='068random.mu.html#L1'>random</a> <a href='075channel.mu.html#L36'>source</a> +<span id="L44" class="LineNr">44 </span> 7:num/<span class="Special">raw</span>, 8:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='068random.mu.html#L1'>random</a> <a href='075channel.mu.html#L36'>source</a> <span id="L45" class="LineNr">45 </span> memory-should-contain [ <span id="L46" class="LineNr">46 </span> <span class="Constant"> 1</span> <span class="Special"><-</span><span class="Constant"> 34</span> <span id="L47" class="LineNr">47 </span> <span class="Constant"> 2</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># everything went well</span> @@ -127,8 +127,8 @@ if ('onhashchange' in window) { <span id="L67" class="LineNr">67 </span> <span id="L68" class="LineNr">68 </span><span class="muScenario">scenario</span> <a href='068random.mu.html#L58'>random-in-range</a> [ <span id="L69" class="LineNr">69 </span> <span class="Constant">local-scope</span> -<span id="L70" class="LineNr">70 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='066stream.mu.html#L2'>stream</a>:num <span class="Special"><-</span> <a href='068random.mu.html#L14'>assume-random-numbers</a><span class="Constant"> 91</span> -<span id="L71" class="LineNr">71 </span> 1:num/<span class="Special">raw</span> <span class="Special"><-</span> <a href='068random.mu.html#L58'>random-in-range</a> <a href='075channel.mu.html#L43'>source</a>,<span class="Constant"> 40</span>,<span class="Constant"> 50</span> +<span id="L70" class="LineNr">70 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='066stream.mu.html#L2'>stream</a>:num <span class="Special"><-</span> <a href='068random.mu.html#L14'>assume-random-numbers</a><span class="Constant"> 91</span> +<span id="L71" class="LineNr">71 </span> 1:num/<span class="Special">raw</span> <span class="Special"><-</span> <a href='068random.mu.html#L58'>random-in-range</a> <a href='075channel.mu.html#L36'>source</a>,<span class="Constant"> 40</span>,<span class="Constant"> 50</span> <span id="L72" class="LineNr">72 </span> memory-should-contain [ <span id="L73" class="LineNr">73 </span> <span class="Constant"> 1</span> <span class="Special"><-</span><span class="Constant"> 41</span> <span id="L74" class="LineNr">74 </span> ] diff --git a/html/070table.mu.html b/html/070table.mu.html index 6e1c73f7..f8e12f73 100644 --- a/html/070table.mu.html +++ b/html/070table.mu.html @@ -104,7 +104,7 @@ if ('onhashchange' in window) { <span id="L43" class="LineNr"> 43 </span> <span id="L44" class="LineNr"> 44 </span><span class="muData">container</span> <a href='070table.mu.html#L44'>table</a>:_key:_value [ <span id="L45" class="LineNr"> 45 </span> length:num -<span id="L46" class="LineNr"> 46 </span> <a href='075channel.mu.html#L399'>capacity</a>:num +<span id="L46" class="LineNr"> 46 </span> <a href='075channel.mu.html#L391'>capacity</a>:num <span id="L47" class="LineNr"> 47 </span> data:&:@:<a href='070table.mu.html#L50'>table-row</a>:_key:_value <span id="L48" class="LineNr"> 48 </span>] <span id="L49" class="LineNr"> 49 </span> @@ -114,12 +114,12 @@ if ('onhashchange' in window) { <span id="L53" class="LineNr"> 53 </span> value:_value <span id="L54" class="LineNr"> 54 </span>] <span id="L55" class="LineNr"> 55 </span> -<span id="L56" class="LineNr"> 56 </span><span class="muRecipe">def</span> <a href='070table.mu.html#L56'>new-table</a> <a href='075channel.mu.html#L399'>capacity</a>:num<span class="muRecipe"> -> </span>result:&:<a href='070table.mu.html#L44'>table</a>:_key:_value [ +<span id="L56" class="LineNr"> 56 </span><span class="muRecipe">def</span> <a href='070table.mu.html#L56'>new-table</a> <a href='075channel.mu.html#L391'>capacity</a>:num<span class="muRecipe"> -> </span>result:&:<a href='070table.mu.html#L44'>table</a>:_key:_value [ <span id="L57" class="LineNr"> 57 </span> <span class="Constant">local-scope</span> <span id="L58" class="LineNr"> 58 </span> <span class="Constant">load-inputs</span> <span id="L59" class="LineNr"> 59 </span> result <span class="Special"><-</span> new <span class="Delimiter">{</span>(table _key _value): type<span class="Delimiter">}</span> -<span id="L60" class="LineNr"> 60 </span> data:&:@:<a href='070table.mu.html#L50'>table-row</a>:_key:_value <span class="Special"><-</span> new <span class="Delimiter">{</span>(table-row _key _value): type<span class="Delimiter">}</span>, <a href='075channel.mu.html#L399'>capacity</a> -<span id="L61" class="LineNr"> 61 </span> *result <span class="Special"><-</span> merge <span class="Constant">0/length</span>, <a href='075channel.mu.html#L399'>capacity</a>, data +<span id="L60" class="LineNr"> 60 </span> data:&:@:<a href='070table.mu.html#L50'>table-row</a>:_key:_value <span class="Special"><-</span> new <span class="Delimiter">{</span>(table-row _key _value): type<span class="Delimiter">}</span>, <a href='075channel.mu.html#L391'>capacity</a> +<span id="L61" class="LineNr"> 61 </span> *result <span class="Special"><-</span> merge <span class="Constant">0/length</span>, <a href='075channel.mu.html#L391'>capacity</a>, data <span id="L62" class="LineNr"> 62 </span>] <span id="L63" class="LineNr"> 63 </span> <span id="L64" class="LineNr"> 64 </span><span class="Comment"># todo: tag results as /required so that call-sites are forbidden from ignoring them</span> @@ -129,8 +129,8 @@ if ('onhashchange' in window) { <span id="L68" class="LineNr"> 68 </span> <span class="Constant">load-inputs</span> <span id="L69" class="LineNr"> 69 </span> hash:num <span class="Special"><-</span> hash key <span id="L70" class="LineNr"> 70 </span> hash <span class="Special"><-</span> <a href='070table.mu.html#L103'>abs</a> hash -<span id="L71" class="LineNr"> 71 </span> <a href='075channel.mu.html#L399'>capacity</a>:num <span class="Special"><-</span> get *table, <span class="Constant"><a href='075channel.mu.html#L399'>capacity</a>:offset</span> -<span id="L72" class="LineNr"> 72 </span> _, hash-key:num <span class="Special"><-</span> divide-with-remainder hash, <a href='075channel.mu.html#L399'>capacity</a> +<span id="L71" class="LineNr"> 71 </span> <a href='075channel.mu.html#L391'>capacity</a>:num <span class="Special"><-</span> get *table, <span class="Constant"><a href='075channel.mu.html#L391'>capacity</a>:offset</span> +<span id="L72" class="LineNr"> 72 </span> _, hash-key:num <span class="Special"><-</span> divide-with-remainder hash, <a href='075channel.mu.html#L391'>capacity</a> <span id="L73" class="LineNr"> 73 </span> hash-key <span class="Special"><-</span> <a href='070table.mu.html#L103'>abs</a> hash-key <span class="Comment"># in case hash overflows from a double into a negative integer inside 'divide-with-remainder' above</span> <span id="L74" class="LineNr"> 74 </span> table-data:&:@:<a href='070table.mu.html#L50'>table-row</a>:_key:_value <span class="Special"><-</span> get *table, <span class="Constant">data:offset</span> <span id="L75" class="LineNr"> 75 </span> x:<a href='070table.mu.html#L50'>table-row</a>:_key:_value <span class="Special"><-</span> index *table-data, hash-key @@ -146,8 +146,8 @@ if ('onhashchange' in window) { <span id="L85" class="LineNr"> 85 </span> <span class="Constant">load-inputs</span> <span id="L86" class="LineNr"> 86 </span> hash:num <span class="Special"><-</span> hash key <span id="L87" class="LineNr"> 87 </span> hash <span class="Special"><-</span> <a href='070table.mu.html#L103'>abs</a> hash -<span id="L88" class="LineNr"> 88 </span> <a href='075channel.mu.html#L399'>capacity</a>:num <span class="Special"><-</span> get *table, <span class="Constant"><a href='075channel.mu.html#L399'>capacity</a>:offset</span> -<span id="L89" class="LineNr"> 89 </span> _, hash-key:num <span class="Special"><-</span> divide-with-remainder hash, <a href='075channel.mu.html#L399'>capacity</a> +<span id="L88" class="LineNr"> 88 </span> <a href='075channel.mu.html#L391'>capacity</a>:num <span class="Special"><-</span> get *table, <span class="Constant"><a href='075channel.mu.html#L391'>capacity</a>:offset</span> +<span id="L89" class="LineNr"> 89 </span> _, hash-key:num <span class="Special"><-</span> divide-with-remainder hash, <a href='075channel.mu.html#L391'>capacity</a> <span id="L90" class="LineNr"> 90 </span> hash-key <span class="Special"><-</span> <a href='070table.mu.html#L103'>abs</a> hash-key <span class="Comment"># in case hash overflows from a double into a negative integer inside 'divide-with-remainder' above</span> <span id="L91" class="LineNr"> 91 </span> table-data:&:@:<a href='070table.mu.html#L50'>table-row</a>:_key:_value <span class="Special"><-</span> get *table, <span class="Constant">data:offset</span> <span id="L92" class="LineNr"> 92 </span> x:<a href='070table.mu.html#L50'>table-row</a>:_key:_value <span class="Special"><-</span> index *table-data, hash-key diff --git a/html/073scheduler.cc.html b/html/073scheduler.cc.html index 9d95b952..b3e6e792 100644 --- a/html/073scheduler.cc.html +++ b/html/073scheduler.cc.html @@ -242,449 +242,448 @@ if ('onhashchange' in window) { <span id="L178" class="LineNr">178 </span> new_routine<span class="Delimiter">-></span>parent_index = Current_routine_index<span class="Delimiter">;</span> <span id="L179" class="LineNr">179 </span> <span class="Comment">// populate ingredients</span> <span id="L180" class="LineNr">180 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Comment">/*</span><span class="Comment">skip callee</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span><a href='026call.cc.html#L89'>current_instruction</a><span class="Delimiter">().</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L181" class="LineNr">181 </span> reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> ingredient = <a href='026call.cc.html#L89'>current_instruction</a><span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> -<span id="L182" class="LineNr">182 </span> new_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ingredient<span class="Delimiter">);</span> -<span id="L183" class="LineNr">183 </span> vector<<span class="Normal">double</span>> new_ingredient_atoms = deep_copy<span class="Delimiter">(</span>ingredient<span class="Delimiter">);</span> -<span id="L184" class="LineNr">184 </span> new_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_ingredient_atoms<span class="Delimiter">);</span> -<span id="L185" class="LineNr">185 </span> <span class="Comment">// End Populate start-running Ingredient</span> -<span id="L186" class="LineNr">186 </span> <span class="Delimiter">}</span> -<span id="L187" class="LineNr">187 </span> Routines<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_routine<span class="Delimiter">);</span> -<span id="L188" class="LineNr">188 </span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L189" class="LineNr">189 </span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>new_routine<span class="Delimiter">-></span>id<span class="Delimiter">);</span> -<span id="L190" class="LineNr">190 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L191" class="LineNr">191 </span><span class="Delimiter">}</span> -<span id="L192" class="LineNr">192 </span> -<span id="L193" class="LineNr">193 </span><span class="Delimiter">:(scenario scheduler_runs_single_routine)</span> -<span id="L194" class="LineNr">194 </span><span class="Special">% Scheduling_interval = 1;</span> -<span id="L195" class="LineNr">195 </span><span class="muRecipe">def</span> f1 [ -<span id="L196" class="LineNr">196 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> -<span id="L197" class="LineNr">197 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> -<span id="L198" class="LineNr">198 </span>] -<span id="L199" class="LineNr">199 </span><span class="traceContains">+schedule: f1</span> -<span id="L200" class="LineNr">200 </span><span class="traceContains">+run: {1: "number"} <- copy {0: "literal"}</span> -<span id="L201" class="LineNr">201 </span><span class="traceContains">+schedule: f1</span> -<span id="L202" class="LineNr">202 </span><span class="traceContains">+run: {2: "number"} <- copy {0: "literal"}</span> -<span id="L203" class="LineNr">203 </span> -<span id="L204" class="LineNr">204 </span><span class="Delimiter">:(scenario scheduler_interleaves_routines)</span> -<span id="L205" class="LineNr">205 </span><span class="Special">% Scheduling_interval = 1;</span> -<span id="L206" class="LineNr">206 </span><span class="muRecipe">def</span> f1 [ -<span id="L207" class="LineNr">207 </span> start-running f2 -<span id="L208" class="LineNr">208 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> -<span id="L209" class="LineNr">209 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> -<span id="L210" class="LineNr">210 </span>] -<span id="L211" class="LineNr">211 </span><span class="muRecipe">def</span> f2 [ -<span id="L212" class="LineNr">212 </span> <span class="Constant">3</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> -<span id="L213" class="LineNr">213 </span> <span class="Constant">4</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> -<span id="L214" class="LineNr">214 </span>] -<span id="L215" class="LineNr">215 </span><span class="traceContains">+schedule: f1</span> -<span id="L216" class="LineNr">216 </span><span class="traceContains">+run: start-running {f2: "recipe-literal"}</span> -<span id="L217" class="LineNr">217 </span><span class="traceContains">+schedule: f2</span> -<span id="L218" class="LineNr">218 </span><span class="traceContains">+run: {3: "number"} <- copy {0: "literal"}</span> -<span id="L219" class="LineNr">219 </span><span class="traceContains">+schedule: f1</span> -<span id="L220" class="LineNr">220 </span><span class="traceContains">+run: {1: "number"} <- copy {0: "literal"}</span> -<span id="L221" class="LineNr">221 </span><span class="traceContains">+schedule: f2</span> -<span id="L222" class="LineNr">222 </span><span class="traceContains">+run: {4: "number"} <- copy {0: "literal"}</span> -<span id="L223" class="LineNr">223 </span><span class="traceContains">+schedule: f1</span> -<span id="L224" class="LineNr">224 </span><span class="traceContains">+run: {2: "number"} <- copy {0: "literal"}</span> -<span id="L225" class="LineNr">225 </span> -<span id="L226" class="LineNr">226 </span><span class="Delimiter">:(scenario start_running_takes_ingredients)</span> -<span id="L227" class="LineNr">227 </span><span class="muRecipe">def</span> f1 [ -<span id="L228" class="LineNr">228 </span> start-running f2<span class="Delimiter">,</span> <span class="Constant">3</span> -<span id="L229" class="LineNr">229 </span> <span class="Comment"># wait for f2 to run</span> -<span id="L230" class="LineNr">230 </span> <span class="Delimiter">{</span> -<span id="L231" class="LineNr">231 </span> jump-unless <span class="Constant">1</span>:num<span class="Delimiter">,</span> -<span class="Constant">1</span> -<span id="L232" class="LineNr">232 </span> <span class="Delimiter">}</span> -<span id="L233" class="LineNr">233 </span>] -<span id="L234" class="LineNr">234 </span><span class="muRecipe">def</span> f2 [ -<span id="L235" class="LineNr">235 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>next-ingredient -<span id="L236" class="LineNr">236 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>add <span class="Constant">1</span>:num<span class="Delimiter">,</span> <span class="Constant">1</span> -<span id="L237" class="LineNr">237 </span>] -<span id="L238" class="LineNr">238 </span><span class="traceContains">+mem: storing 4 in location 2</span> -<span id="L239" class="LineNr">239 </span> -<span id="L240" class="LineNr">240 </span><span class="Comment">//: type-checking for 'start-running'</span> -<span id="L241" class="LineNr">241 </span> -<span id="L242" class="LineNr">242 </span><span class="Delimiter">:(scenario start_running_checks_types)</span> -<span id="L243" class="LineNr">243 </span><span class="Special">% Hide_errors = true;</span> -<span id="L244" class="LineNr">244 </span><span class="muRecipe">def</span> f1 [ -<span id="L245" class="LineNr">245 </span> start-running f2<span class="Delimiter">,</span> <span class="Constant">3</span> -<span id="L246" class="LineNr">246 </span>] -<span id="L247" class="LineNr">247 </span><span class="muRecipe">def</span> f2 n:&:num [ -<span id="L248" class="LineNr">248 </span>] -<span id="L249" class="LineNr">249 </span><span class="traceContains">+error: f1: ingredient 0 has the wrong type at 'start-running f2, 3'</span> -<span id="L250" class="LineNr">250 </span> -<span id="L251" class="LineNr">251 </span><span class="Comment">// 'start-running' only uses the ingredients of the callee, not its products</span> -<span id="L252" class="LineNr">252 </span><span class="Delimiter">:(before "End <a href='072recipe.cc.html#L257'>is_indirect_call_with_ingredients</a> Special-cases")</span> -<span id="L253" class="LineNr">253 </span><span class="Normal">if</span> <span class="Delimiter">(</span>r == START_RUNNING<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> -<span id="L254" class="LineNr">254 </span> -<span id="L255" class="LineNr">255 </span><span class="Comment">//: back to testing 'start-running'</span> -<span id="L256" class="LineNr">256 </span> -<span id="L257" class="LineNr">257 </span><span class="Delimiter">:(scenario start_running_returns_routine_id)</span> -<span id="L258" class="LineNr">258 </span><span class="muRecipe">def</span> f1 [ -<span id="L259" class="LineNr">259 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>start-running f2 -<span id="L260" class="LineNr">260 </span>] -<span id="L261" class="LineNr">261 </span><span class="muRecipe">def</span> f2 [ -<span id="L262" class="LineNr">262 </span> <span class="Constant">12</span>:num<span class="Special"> <- </span>copy <span class="Constant">44</span> -<span id="L263" class="LineNr">263 </span>] -<span id="L264" class="LineNr">264 </span><span class="traceContains">+mem: storing 2 in location 1</span> -<span id="L265" class="LineNr">265 </span> -<span id="L266" class="LineNr">266 </span><span class="Comment">//: this scenario will require some careful setup in escaped C++</span> -<span id="L267" class="LineNr">267 </span><span class="Comment">//: (straining our tangle capabilities to near-breaking point)</span> -<span id="L268" class="LineNr">268 </span><span class="Delimiter">:(scenario scheduler_skips_completed_routines)</span> -<span id="L269" class="LineNr">269 </span><span class="Special">% <a href='010vm.cc.html#L14'>recipe_ordinal</a> f1 = load("recipe f1 [\n1:num <- copy 0\n]\n").front();</span> -<span id="L270" class="LineNr">270 </span><span class="Special">% <a href='010vm.cc.html#L14'>recipe_ordinal</a> f2 = load("recipe f2 [\n2:num <- copy 0\n]\n").front();</span> -<span id="L271" class="LineNr">271 </span><span class="Special">% Routines.push_back(new routine(f1)); // f1 meant to run</span> -<span id="L272" class="LineNr">272 </span><span class="Special">% Routines.push_back(new routine(f2));</span> -<span id="L273" class="LineNr">273 </span><span class="Special">% Routines.back()->state = COMPLETED; // f2 not meant to run</span> -<span id="L274" class="LineNr">274 </span><span class="Comment"># must have at least one routine without escaping</span> -<span id="L275" class="LineNr">275 </span><span class="muRecipe">def</span> f3 [ -<span id="L276" class="LineNr">276 </span> <span class="Constant">3</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> -<span id="L277" class="LineNr">277 </span>] -<span id="L278" class="LineNr">278 </span><span class="Comment"># by interleaving '+' lines with '-' lines, we allow f1 and f3 to run in any order</span> -<span id="L279" class="LineNr">279 </span><span class="traceContains">+schedule: f1</span> -<span id="L280" class="LineNr">280 </span><span class="traceContains">+mem: storing 0 in location 1</span> -<span id="L281" class="LineNr">281 </span><span class="traceAbsent">-schedule: f2</span> -<span id="L282" class="LineNr">282 </span><span class="traceAbsent">-mem: storing 0 in location 2</span> -<span id="L283" class="LineNr">283 </span><span class="traceContains">+schedule: f3</span> -<span id="L284" class="LineNr">284 </span><span class="traceContains">+mem: storing 0 in location 3</span> -<span id="L285" class="LineNr">285 </span> -<span id="L286" class="LineNr">286 </span><span class="Delimiter">:(scenario scheduler_starts_at_middle_of_routines)</span> -<span id="L287" class="LineNr">287 </span><span class="Special">% Routines.push_back(new routine(COPY));</span> -<span id="L288" class="LineNr">288 </span><span class="Special">% Routines.back()->state = COMPLETED;</span> -<span id="L289" class="LineNr">289 </span><span class="muRecipe">def</span> f1 [ -<span id="L290" class="LineNr">290 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> -<span id="L291" class="LineNr">291 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> -<span id="L292" class="LineNr">292 </span>] -<span id="L293" class="LineNr">293 </span><span class="traceContains">+schedule: f1</span> -<span id="L294" class="LineNr">294 </span><span class="traceAbsent">-run: idle</span> -<span id="L295" class="LineNr">295 </span> -<span id="L296" class="LineNr">296 </span><span class="SalientComment">//:: Errors in a routine cause it to terminate.</span> -<span id="L297" class="LineNr">297 </span> -<span id="L298" class="LineNr">298 </span><span class="Delimiter">:(scenario scheduler_terminates_routines_after_errors)</span> -<span id="L299" class="LineNr">299 </span><span class="Special">% Hide_errors = true;</span> -<span id="L300" class="LineNr">300 </span><span class="Special">% Scheduling_interval = 2;</span> -<span id="L301" class="LineNr">301 </span><span class="muRecipe">def</span> f1 [ -<span id="L302" class="LineNr">302 </span> start-running f2 -<span id="L303" class="LineNr">303 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> -<span id="L304" class="LineNr">304 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> -<span id="L305" class="LineNr">305 </span>] -<span id="L306" class="LineNr">306 </span><span class="muRecipe">def</span> f2 [ -<span id="L307" class="LineNr">307 </span> <span class="Comment"># divide by 0 twice</span> -<span id="L308" class="LineNr">308 </span> <span class="Constant">3</span>:num<span class="Special"> <- </span>divide-with-remainder <span class="Constant">4</span><span class="Delimiter">,</span> <span class="Constant">0</span> -<span id="L309" class="LineNr">309 </span> <span class="Constant">4</span>:num<span class="Special"> <- </span>divide-with-remainder <span class="Constant">4</span><span class="Delimiter">,</span> <span class="Constant">0</span> -<span id="L310" class="LineNr">310 </span>] -<span id="L311" class="LineNr">311 </span><span class="Comment"># f2 should stop after first divide by 0</span> -<span id="L312" class="LineNr">312 </span><span class="traceContains">+error: f2: divide by zero in '3:num <- divide-with-remainder 4, 0'</span> -<span id="L313" class="LineNr">313 </span><span class="traceAbsent">-error: f2: divide by zero in '4:num <- divide-with-remainder 4, 0'</span> -<span id="L314" class="LineNr">314 </span> -<span id="L315" class="LineNr">315 </span><span class="Delimiter">:(after "operator<<(ostream& os, <a href='001help.cc.html#L259'>vestigial</a> end)")</span> -<span id="L316" class="LineNr">316 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Trace_stream && Trace_stream<span class="Delimiter">-></span>curr_label == <span class="Constant">"error"</span> && Current_routine<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L317" class="LineNr">317 </span> Current_routine<span class="Delimiter">-></span>state = <a href='073scheduler.cc.html#L42'>COMPLETED</a><span class="Delimiter">;</span> -<span id="L318" class="LineNr">318 </span> <span class="Delimiter">}</span> -<span id="L319" class="LineNr">319 </span> -<span id="L320" class="LineNr">320 </span><span class="SalientComment">//:: Routines are marked completed when their parent completes.</span> -<span id="L321" class="LineNr">321 </span> -<span id="L322" class="LineNr">322 </span><span class="Delimiter">:(scenario scheduler_kills_orphans)</span> -<span id="L323" class="LineNr">323 </span><span class="muRecipe">def</span> <a href='000organization.cc.html#L113'>main</a> [ -<span id="L324" class="LineNr">324 </span> start-running f1 -<span id="L325" class="LineNr">325 </span> <span class="Comment"># f1 never actually runs because its parent completes without waiting for it</span> -<span id="L326" class="LineNr">326 </span>] -<span id="L327" class="LineNr">327 </span><span class="muRecipe">def</span> f1 [ -<span id="L328" class="LineNr">328 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> -<span id="L329" class="LineNr">329 </span>] -<span id="L330" class="LineNr">330 </span><span class="traceAbsent">-schedule: f1</span> -<span id="L331" class="LineNr">331 </span> -<span id="L332" class="LineNr">332 </span><span class="Delimiter">:(before "End Scheduler Cleanup")</span> -<span id="L333" class="LineNr">333 </span><span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L334" class="LineNr">334 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state == <a href='073scheduler.cc.html#L42'>COMPLETED</a><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> -<span id="L335" class="LineNr">335 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>parent_index < <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// root thread</span> -<span id="L336" class="LineNr">336 </span> <span class="Comment">// structured concurrency: <a href="http://250bpm.com/blog:71">http://250bpm.com/blog:71</a></span> -<span id="L337" class="LineNr">337 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>has_completed_parent<span class="Delimiter">(</span>i<span class="Delimiter">))</span> <span class="Delimiter">{</span> -<span id="L338" class="LineNr">338 </span> Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state = <a href='073scheduler.cc.html#L42'>COMPLETED</a><span class="Delimiter">;</span> -<span id="L339" class="LineNr">339 </span> <span class="Delimiter">}</span> -<span id="L340" class="LineNr">340 </span><span class="Delimiter">}</span> -<span id="L341" class="LineNr">341 </span> -<span id="L342" class="LineNr">342 </span><span class="Delimiter">:(code)</span> -<span id="L343" class="LineNr">343 </span><span class="Normal">bool</span> has_completed_parent<span class="Delimiter">(</span><span class="Normal">int</span> routine_index<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L344" class="LineNr">344 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> j = routine_index<span class="Delimiter">;</span> j >= <span class="Constant">0</span><span class="Delimiter">;</span> j = Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)-></span>parent_index<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L345" class="LineNr">345 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)-></span>state == <a href='073scheduler.cc.html#L42'>COMPLETED</a><span class="Delimiter">)</span> -<span id="L346" class="LineNr">346 </span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> -<span id="L347" class="LineNr">347 </span> <span class="Delimiter">}</span> -<span id="L348" class="LineNr">348 </span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> -<span id="L349" class="LineNr">349 </span><span class="Delimiter">}</span> -<span id="L350" class="LineNr">350 </span> -<span id="L351" class="LineNr">351 </span><span class="SalientComment">//:: 'routine-state' can tell if a given routine id is running</span> -<span id="L352" class="LineNr">352 </span> -<span id="L353" class="LineNr">353 </span><span class="Delimiter">:(scenario routine_state_test)</span> -<span id="L354" class="LineNr">354 </span><span class="Special">% Scheduling_interval = 2;</span> -<span id="L355" class="LineNr">355 </span><span class="muRecipe">def</span> f1 [ -<span id="L356" class="LineNr">356 </span> <span class="Constant">1</span>:num/child-id<span class="Special"> <- </span>start-running f2 -<span id="L357" class="LineNr">357 </span> <span class="Constant">12</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># race condition since we don't care about location 12</span> -<span id="L358" class="LineNr">358 </span> <span class="Comment"># thanks to Scheduling_interval, f2's one instruction runs in between here and completes</span> -<span id="L359" class="LineNr">359 </span> <span class="Constant">2</span>:num/state<span class="Special"> <- </span>routine-state <span class="Constant">1</span>:num/child-id -<span id="L360" class="LineNr">360 </span>] -<span id="L361" class="LineNr">361 </span><span class="muRecipe">def</span> f2 [ -<span id="L362" class="LineNr">362 </span> <span class="Constant">12</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> -<span id="L363" class="LineNr">363 </span> <span class="Comment"># trying to run a second instruction marks routine as completed</span> -<span id="L364" class="LineNr">364 </span>] -<span id="L365" class="LineNr">365 </span><span class="Comment"># recipe f2 should be in state COMPLETED</span> -<span id="L366" class="LineNr">366 </span><span class="traceContains">+mem: storing 1 in location 2</span> -<span id="L367" class="LineNr">367 </span> -<span id="L368" class="LineNr">368 </span><span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> -<span id="L369" class="LineNr">369 </span>ROUTINE_STATE<span class="Delimiter">,</span> -<span id="L370" class="LineNr">370 </span><span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -<span id="L371" class="LineNr">371 </span><a href='001help.cc.html#L221'>put</a><span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"routine-state"</span><span class="Delimiter">,</span> ROUTINE_STATE<span class="Delimiter">);</span> -<span id="L372" class="LineNr">372 </span><span class="Delimiter">:(before "End Primitive Recipe Checks")</span> -<span id="L373" class="LineNr">373 </span><span class="Normal">case</span> ROUTINE_STATE: <span class="Delimiter">{</span> -<span id="L374" class="LineNr">374 </span> <span class="Normal">if</span> <span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L375" class="LineNr">375 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'routine-state' requires exactly one ingredient, but got '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L376" class="LineNr">376 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L377" class="LineNr">377 </span> <span class="Delimiter">}</span> -<span id="L378" class="LineNr">378 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> -<span id="L379" class="LineNr">379 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'routine-state' should be a routine id generated by 'start-running', but got '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L380" class="LineNr">380 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L381" class="LineNr">381 </span> <span class="Delimiter">}</span> -<span id="L382" class="LineNr">382 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L383" class="LineNr">383 </span><span class="Delimiter">}</span> -<span id="L384" class="LineNr">384 </span><span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span id="L385" class="LineNr">385 </span><span class="Normal">case</span> ROUTINE_STATE: <span class="Delimiter">{</span> -<span id="L386" class="LineNr">386 </span> <span class="Normal">int</span> id = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> -<span id="L387" class="LineNr">387 </span> <span class="Normal">int</span> result = -<span class="Constant">1</span><span class="Delimiter">;</span> -<span id="L388" class="LineNr">388 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L389" class="LineNr">389 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>id == id<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L390" class="LineNr">390 </span> result = Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state<span class="Delimiter">;</span> -<span id="L391" class="LineNr">391 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L392" class="LineNr">392 </span> <span class="Delimiter">}</span> -<span id="L393" class="LineNr">393 </span> <span class="Delimiter">}</span> -<span id="L394" class="LineNr">394 </span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L395" class="LineNr">395 </span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> -<span id="L396" class="LineNr">396 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L397" class="LineNr">397 </span><span class="Delimiter">}</span> -<span id="L398" class="LineNr">398 </span> -<span id="L399" class="LineNr">399 </span><span class="SalientComment">//:: miscellaneous helpers</span> -<span id="L400" class="LineNr">400 </span> -<span id="L401" class="LineNr">401 </span><span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> -<span id="L402" class="LineNr">402 </span>STOP<span class="Delimiter">,</span> -<span id="L403" class="LineNr">403 </span><span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -<span id="L404" class="LineNr">404 </span><a href='001help.cc.html#L221'>put</a><span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"stop"</span><span class="Delimiter">,</span> STOP<span class="Delimiter">);</span> -<span id="L405" class="LineNr">405 </span><span class="Delimiter">:(before "End Primitive Recipe Checks")</span> -<span id="L406" class="LineNr">406 </span><span class="Normal">case</span> STOP: <span class="Delimiter">{</span> -<span id="L407" class="LineNr">407 </span> <span class="Normal">if</span> <span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L408" class="LineNr">408 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'stop' requires exactly one ingredient, but got '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L409" class="LineNr">409 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L410" class="LineNr">410 </span> <span class="Delimiter">}</span> -<span id="L411" class="LineNr">411 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> -<span id="L412" class="LineNr">412 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'stop' should be a routine id generated by 'start-running', but got '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L413" class="LineNr">413 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L414" class="LineNr">414 </span> <span class="Delimiter">}</span> -<span id="L415" class="LineNr">415 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L416" class="LineNr">416 </span><span class="Delimiter">}</span> -<span id="L417" class="LineNr">417 </span><span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span id="L418" class="LineNr">418 </span><span class="Normal">case</span> STOP: <span class="Delimiter">{</span> -<span id="L419" class="LineNr">419 </span> <span class="Normal">int</span> id = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> -<span id="L420" class="LineNr">420 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L421" class="LineNr">421 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>id == id<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L422" class="LineNr">422 </span> Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state = <a href='073scheduler.cc.html#L42'>COMPLETED</a><span class="Delimiter">;</span> -<span id="L423" class="LineNr">423 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L424" class="LineNr">424 </span> <span class="Delimiter">}</span> -<span id="L425" class="LineNr">425 </span> <span class="Delimiter">}</span> -<span id="L426" class="LineNr">426 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L427" class="LineNr">427 </span><span class="Delimiter">}</span> -<span id="L428" class="LineNr">428 </span> -<span id="L429" class="LineNr">429 </span><span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> -<span id="L430" class="LineNr">430 </span>_DUMP_ROUTINES<span class="Delimiter">,</span> -<span id="L431" class="LineNr">431 </span><span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -<span id="L432" class="LineNr">432 </span><a href='001help.cc.html#L221'>put</a><span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"$dump-routines"</span><span class="Delimiter">,</span> _DUMP_ROUTINES<span class="Delimiter">);</span> -<span id="L433" class="LineNr">433 </span><span class="Delimiter">:(before "End Primitive Recipe Checks")</span> -<span id="L434" class="LineNr">434 </span><span class="Normal">case</span> _DUMP_ROUTINES: <span class="Delimiter">{</span> -<span id="L435" class="LineNr">435 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L436" class="LineNr">436 </span><span class="Delimiter">}</span> -<span id="L437" class="LineNr">437 </span><span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span id="L438" class="LineNr">438 </span><span class="Normal">case</span> _DUMP_ROUTINES: <span class="Delimiter">{</span> -<span id="L439" class="LineNr">439 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L440" class="LineNr">440 </span> cerr << i << <span class="Constant">": "</span> << Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>id << <span class="Constant">' '</span> << Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state << <span class="Constant">' '</span> << Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>parent_index << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> -<span id="L441" class="LineNr">441 </span> <span class="Delimiter">}</span> -<span id="L442" class="LineNr">442 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L443" class="LineNr">443 </span><span class="Delimiter">}</span> -<span id="L444" class="LineNr">444 </span> -<span id="L445" class="LineNr">445 </span><span class="Comment">//: support for stopping routines after some number of cycles</span> -<span id="L446" class="LineNr">446 </span> -<span id="L447" class="LineNr">447 </span><span class="Delimiter">:(scenario routine_discontinues_past_limit)</span> -<span id="L448" class="LineNr">448 </span><span class="Special">% Scheduling_interval = 2;</span> -<span id="L449" class="LineNr">449 </span><span class="muRecipe">def</span> f1 [ -<span id="L450" class="LineNr">450 </span> <span class="Constant">1</span>:num/child-id<span class="Special"> <- </span>start-running f2 -<span id="L451" class="LineNr">451 </span> limit-time <span class="Constant">1</span>:num/child-id<span class="Delimiter">,</span> <span class="Constant">10</span> -<span id="L452" class="LineNr">452 </span> <span class="Comment"># padding loop just to make sure f2 has time to completed</span> -<span id="L453" class="LineNr">453 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">20</span> -<span id="L454" class="LineNr">454 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>subtract <span class="Constant">2</span>:num<span class="Delimiter">,</span> <span class="Constant">1</span> -<span id="L455" class="LineNr">455 </span> jump-<span class="Normal">if</span> <span class="Constant">2</span>:num<span class="Delimiter">,</span> <span class="Constant">-2:offset</span> -<span id="L456" class="LineNr">456 </span>] -<span id="L457" class="LineNr">457 </span><span class="muRecipe">def</span> f2 [ -<span id="L458" class="LineNr">458 </span> jump <span class="Constant">-1:offset</span> <span class="Comment"># run forever</span> -<span id="L459" class="LineNr">459 </span> $print [should never get here]<span class="Delimiter">,</span> <span class="Constant">10</span>/newline -<span id="L460" class="LineNr">460 </span>] -<span id="L461" class="LineNr">461 </span><span class="Comment"># f2 terminates</span> -<span id="L462" class="LineNr">462 </span><span class="traceContains">+schedule: discontinuing routine 2</span> -<span id="L463" class="LineNr">463 </span> -<span id="L464" class="LineNr">464 </span><span class="Delimiter">:(before "End routine States")</span> -<span id="L465" class="LineNr">465 </span>DISCONTINUED<span class="Delimiter">,</span> -<span id="L466" class="LineNr">466 </span><span class="Delimiter">:(before "End Scheduler State Transitions")</span> -<span id="L467" class="LineNr">467 </span><span class="Normal">if</span> <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>limit >= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L468" class="LineNr">468 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>limit <= Scheduling_interval<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L469" class="LineNr">469 </span> <a href='003trace.cc.html#L167'>trace</a><span class="Delimiter">(</span><span class="Constant">"schedule"</span><span class="Delimiter">)</span> << <span class="Constant">"discontinuing routine "</span> << Current_routine<span class="Delimiter">-></span>id << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L470" class="LineNr">470 </span> Current_routine<span class="Delimiter">-></span>state = DISCONTINUED<span class="Delimiter">;</span> -<span id="L471" class="LineNr">471 </span> Current_routine<span class="Delimiter">-></span>limit = <span class="Constant">0</span><span class="Delimiter">;</span> -<span id="L472" class="LineNr">472 </span> <span class="Delimiter">}</span> -<span id="L473" class="LineNr">473 </span> <span class="Normal">else</span> <span class="Delimiter">{</span> -<span id="L474" class="LineNr">474 </span> Current_routine<span class="Delimiter">-></span>limit -= Scheduling_interval<span class="Delimiter">;</span> -<span id="L475" class="LineNr">475 </span> <span class="Delimiter">}</span> -<span id="L476" class="LineNr">476 </span><span class="Delimiter">}</span> -<span id="L477" class="LineNr">477 </span> -<span id="L478" class="LineNr">478 </span><span class="Delimiter">:(before "End Test Teardown")</span> -<span id="L479" class="LineNr">479 </span><span class="Normal">if</span> <span class="Delimiter">(</span>Passed && any_routines_with_error<span class="Delimiter">())</span> -<span id="L480" class="LineNr">480 </span> <a href='003trace.cc.html#L174'>raise</a> << <span class="Constant">"some routines died with errors</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L481" class="LineNr">481 </span><span class="Delimiter">:(before "End Mu Test Teardown")</span> -<span id="L482" class="LineNr">482 </span><span class="Normal">if</span> <span class="Delimiter">(</span>Passed && any_routines_with_error<span class="Delimiter">())</span> -<span id="L483" class="LineNr">483 </span> <a href='003trace.cc.html#L174'>raise</a> << Current_scenario<span class="Delimiter">-></span>name << <span class="Constant">": some routines died with errors</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L484" class="LineNr">484 </span> -<span id="L485" class="LineNr">485 </span><span class="Delimiter">:(code)</span> -<span id="L486" class="LineNr">486 </span><span class="Normal">bool</span> any_routines_with_error<span class="Delimiter">()</span> <span class="Delimiter">{</span> -<span id="L487" class="LineNr">487 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L488" class="LineNr">488 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state == DISCONTINUED<span class="Delimiter">)</span> -<span id="L489" class="LineNr">489 </span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> -<span id="L490" class="LineNr">490 </span> <span class="Delimiter">}</span> -<span id="L491" class="LineNr">491 </span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> -<span id="L492" class="LineNr">492 </span><span class="Delimiter">}</span> -<span id="L493" class="LineNr">493 </span> -<span id="L494" class="LineNr">494 </span><span class="Delimiter">:(before "End routine Fields")</span> -<span id="L495" class="LineNr">495 </span><span class="Normal">int</span> limit<span class="Delimiter">;</span> -<span id="L496" class="LineNr">496 </span><span class="Delimiter">:(before "End routine Constructor")</span> -<span id="L497" class="LineNr">497 </span>limit = -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Comment">/*</span><span class="Comment"> no limit </span><span class="Comment">*/</span> -<span id="L498" class="LineNr">498 </span> -<span id="L499" class="LineNr">499 </span><span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> -<span id="L500" class="LineNr">500 </span>LIMIT_TIME<span class="Delimiter">,</span> -<span id="L501" class="LineNr">501 </span><span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -<span id="L502" class="LineNr">502 </span><a href='001help.cc.html#L221'>put</a><span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"limit-time"</span><span class="Delimiter">,</span> LIMIT_TIME<span class="Delimiter">);</span> -<span id="L503" class="LineNr">503 </span><span class="Delimiter">:(before "End Primitive Recipe Checks")</span> -<span id="L504" class="LineNr">504 </span><span class="Normal">case</span> LIMIT_TIME: <span class="Delimiter">{</span> -<span id="L505" class="LineNr">505 </span> <span class="Normal">if</span> <span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L506" class="LineNr">506 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'limit-time' requires exactly two ingredient, but got '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L507" class="LineNr">507 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L508" class="LineNr">508 </span> <span class="Delimiter">}</span> -<span id="L509" class="LineNr">509 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> -<span id="L510" class="LineNr">510 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'limit-time' should be a routine id generated by 'start-running', but got '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L511" class="LineNr">511 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L512" class="LineNr">512 </span> <span class="Delimiter">}</span> -<span id="L513" class="LineNr">513 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> -<span id="L514" class="LineNr">514 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"second ingredient of 'limit-time' should be a number (of instructions to run for), but got '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L515" class="LineNr">515 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L516" class="LineNr">516 </span> <span class="Delimiter">}</span> -<span id="L517" class="LineNr">517 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L518" class="LineNr">518 </span><span class="Delimiter">}</span> -<span id="L519" class="LineNr">519 </span><span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span id="L520" class="LineNr">520 </span><span class="Normal">case</span> LIMIT_TIME: <span class="Delimiter">{</span> -<span id="L521" class="LineNr">521 </span> <span class="Normal">int</span> id = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> -<span id="L522" class="LineNr">522 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L523" class="LineNr">523 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>id == id<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L524" class="LineNr">524 </span> Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>limit = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> -<span id="L525" class="LineNr">525 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L526" class="LineNr">526 </span> <span class="Delimiter">}</span> -<span id="L527" class="LineNr">527 </span> <span class="Delimiter">}</span> -<span id="L528" class="LineNr">528 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L529" class="LineNr">529 </span><span class="Delimiter">}</span> -<span id="L530" class="LineNr">530 </span> -<span id="L531" class="LineNr">531 </span><span class="Delimiter">:(before "End routine Fields")</span> -<span id="L532" class="LineNr">532 </span><span class="Normal">int</span> instructions_run<span class="Delimiter">;</span> -<span id="L533" class="LineNr">533 </span><span class="Delimiter">:(before "End routine Constructor")</span> -<span id="L534" class="LineNr">534 </span>instructions_run = <span class="Constant">0</span><span class="Delimiter">;</span> -<span id="L535" class="LineNr">535 </span><span class="Delimiter">:(before "Reset instructions_run_this_scheduling_slice")</span> -<span id="L536" class="LineNr">536 </span>Current_routine<span class="Delimiter">-></span>instructions_run += Current_routine<span class="Delimiter">-></span>instructions_run_this_scheduling_slice<span class="Delimiter">;</span> -<span id="L537" class="LineNr">537 </span><span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> -<span id="L538" class="LineNr">538 </span>NUMBER_OF_INSTRUCTIONS<span class="Delimiter">,</span> -<span id="L539" class="LineNr">539 </span><span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -<span id="L540" class="LineNr">540 </span><a href='001help.cc.html#L221'>put</a><span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"number-of-instructions"</span><span class="Delimiter">,</span> NUMBER_OF_INSTRUCTIONS<span class="Delimiter">);</span> -<span id="L541" class="LineNr">541 </span><span class="Delimiter">:(before "End Primitive Recipe Checks")</span> -<span id="L542" class="LineNr">542 </span><span class="Normal">case</span> NUMBER_OF_INSTRUCTIONS: <span class="Delimiter">{</span> -<span id="L543" class="LineNr">543 </span> <span class="Normal">if</span> <span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L544" class="LineNr">544 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'number-of-instructions' requires exactly one ingredient, but got '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L545" class="LineNr">545 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L546" class="LineNr">546 </span> <span class="Delimiter">}</span> -<span id="L547" class="LineNr">547 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> -<span id="L548" class="LineNr">548 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'number-of-instructions' should be a routine id generated by 'start-running', but got '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> -<span id="L549" class="LineNr">549 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L550" class="LineNr">550 </span> <span class="Delimiter">}</span> -<span id="L551" class="LineNr">551 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L552" class="LineNr">552 </span><span class="Delimiter">}</span> -<span id="L553" class="LineNr">553 </span><span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span id="L554" class="LineNr">554 </span><span class="Normal">case</span> NUMBER_OF_INSTRUCTIONS: <span class="Delimiter">{</span> -<span id="L555" class="LineNr">555 </span> <span class="Normal">int</span> id = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> -<span id="L556" class="LineNr">556 </span> <span class="Normal">int</span> result = -<span class="Constant">1</span><span class="Delimiter">;</span> -<span id="L557" class="LineNr">557 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L558" class="LineNr">558 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>id == id<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span id="L559" class="LineNr">559 </span> result = Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>instructions_run<span class="Delimiter">;</span> -<span id="L560" class="LineNr">560 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L561" class="LineNr">561 </span> <span class="Delimiter">}</span> -<span id="L562" class="LineNr">562 </span> <span class="Delimiter">}</span> -<span id="L563" class="LineNr">563 </span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> -<span id="L564" class="LineNr">564 </span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> -<span id="L565" class="LineNr">565 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> -<span id="L566" class="LineNr">566 </span><span class="Delimiter">}</span> -<span id="L567" class="LineNr">567 </span> -<span id="L568" class="LineNr">568 </span><span class="Delimiter">:(scenario number_of_instructions)</span> -<span id="L569" class="LineNr">569 </span><span class="muRecipe">def</span> f1 [ -<span id="L570" class="LineNr">570 </span> <span class="Constant">10</span>:num/child-id<span class="Special"> <- </span>start-running f2 -<span id="L571" class="LineNr">571 </span> <span class="Delimiter">{</span> -<span id="L572" class="LineNr">572 </span> loop-unless <span class="Constant">20</span>:num -<span id="L573" class="LineNr">573 </span> <span class="Delimiter">}</span> -<span id="L574" class="LineNr">574 </span> <span class="Constant">11</span>:num<span class="Special"> <- </span>number-of-instructions <span class="Constant">10</span>:num -<span id="L575" class="LineNr">575 </span>] -<span id="L576" class="LineNr">576 </span><span class="muRecipe">def</span> f2 [ -<span id="L577" class="LineNr">577 </span> <span class="Comment"># 2 instructions worth of work</span> -<span id="L578" class="LineNr">578 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">34</span> -<span id="L579" class="LineNr">579 </span> <span class="Constant">20</span>:num<span class="Special"> <- </span>copy <span class="Constant">1</span> -<span id="L580" class="LineNr">580 </span>] -<span id="L581" class="LineNr">581 </span><span class="Comment"># f2 runs an extra instruction for the implicit return added by the</span> -<span id="L582" class="LineNr">582 </span><span class="Comment"># fill_in_return_ingredients transform</span> -<span id="L583" class="LineNr">583 </span><span class="traceContains">+mem: storing 3 in location 11</span> -<span id="L584" class="LineNr">584 </span> -<span id="L585" class="LineNr">585 </span><span class="Delimiter">:(scenario number_of_instructions_across_multiple_scheduling_intervals)</span> -<span id="L586" class="LineNr">586 </span><span class="Special">% Scheduling_interval = 1;</span> -<span id="L587" class="LineNr">587 </span><span class="muRecipe">def</span> f1 [ -<span id="L588" class="LineNr">588 </span> <span class="Constant">10</span>:num/child-id<span class="Special"> <- </span>start-running f2 -<span id="L589" class="LineNr">589 </span> <span class="Delimiter">{</span> -<span id="L590" class="LineNr">590 </span> loop-unless <span class="Constant">20</span>:num -<span id="L591" class="LineNr">591 </span> <span class="Delimiter">}</span> -<span id="L592" class="LineNr">592 </span> <span class="Constant">11</span>:num<span class="Special"> <- </span>number-of-instructions <span class="Constant">10</span>:num -<span id="L593" class="LineNr">593 </span>] -<span id="L594" class="LineNr">594 </span><span class="muRecipe">def</span> f2 [ -<span id="L595" class="LineNr">595 </span> <span class="Comment"># 4 instructions worth of work</span> -<span id="L596" class="LineNr">596 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">34</span> -<span id="L597" class="LineNr">597 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">1</span> -<span id="L598" class="LineNr">598 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">3</span> -<span id="L599" class="LineNr">599 </span> <span class="Constant">20</span>:num<span class="Special"> <- </span>copy <span class="Constant">1</span> -<span id="L600" class="LineNr">600 </span>] -<span id="L601" class="LineNr">601 </span><span class="Comment"># f2 runs an extra instruction for the implicit return added by the</span> -<span id="L602" class="LineNr">602 </span><span class="Comment"># fill_in_return_ingredients transform</span> -<span id="L603" class="LineNr">603 </span><span class="traceContains">+mem: storing 5 in location 11</span> -<span id="L604" class="LineNr">604 </span> -<span id="L605" class="LineNr">605 </span><span class="SalientComment">//:: make sure that each routine gets a different alloc to start</span> -<span id="L606" class="LineNr">606 </span> -<span id="L607" class="LineNr">607 </span><span class="Delimiter">:(scenario new_concurrent)</span> -<span id="L608" class="LineNr">608 </span><span class="muRecipe">def</span> f1 [ -<span id="L609" class="LineNr">609 </span> start-running f2 -<span id="L610" class="LineNr">610 </span> <span class="Constant">1</span>:&:num/<span class="Special">raw <- </span><span class="Normal">new</span> <span class="Constant">number:type</span> -<span id="L611" class="LineNr">611 </span> <span class="Comment"># wait for f2 to complete</span> -<span id="L612" class="LineNr">612 </span> <span class="Delimiter">{</span> -<span id="L613" class="LineNr">613 </span> loop-unless <span class="Constant">4</span>:num/<span class="Special">raw</span> -<span id="L614" class="LineNr">614 </span> <span class="Delimiter">}</span> -<span id="L615" class="LineNr">615 </span>] -<span id="L616" class="LineNr">616 </span><span class="muRecipe">def</span> f2 [ -<span id="L617" class="LineNr">617 </span> <span class="Constant">2</span>:&:num/<span class="Special">raw <- </span><span class="Normal">new</span> <span class="Constant">number:type</span> -<span id="L618" class="LineNr">618 </span> <span class="Comment"># hack: assumes scheduler implementation</span> -<span id="L619" class="LineNr">619 </span> <span class="Constant">3</span>:<span class="Normal">bool</span>/<span class="Special">raw <- </span>equal <span class="Constant">1</span>:&:num/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2</span>:&:num/<span class="Special">raw</span> -<span id="L620" class="LineNr">620 </span> <span class="Comment"># signal f2 complete</span> -<span id="L621" class="LineNr">621 </span> <span class="Constant">4</span>:num/<span class="Special">raw <- </span>copy <span class="Constant">1</span> -<span id="L622" class="LineNr">622 </span>] -<span id="L623" class="LineNr">623 </span><span class="traceContains">+mem: storing 0 in location 3</span> +<span id="L181" class="LineNr">181 </span> new_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> +<span id="L182" class="LineNr">182 </span> reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> ingredient = <a href='026call.cc.html#L89'>current_instruction</a><span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> +<span id="L183" class="LineNr">183 </span> new_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ingredient<span class="Delimiter">);</span> +<span id="L184" class="LineNr">184 </span> <span class="Comment">// End Populate start-running Ingredient</span> +<span id="L185" class="LineNr">185 </span> <span class="Delimiter">}</span> +<span id="L186" class="LineNr">186 </span> Routines<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_routine<span class="Delimiter">);</span> +<span id="L187" class="LineNr">187 </span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> +<span id="L188" class="LineNr">188 </span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>new_routine<span class="Delimiter">-></span>id<span class="Delimiter">);</span> +<span id="L189" class="LineNr">189 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L190" class="LineNr">190 </span><span class="Delimiter">}</span> +<span id="L191" class="LineNr">191 </span> +<span id="L192" class="LineNr">192 </span><span class="Delimiter">:(scenario scheduler_runs_single_routine)</span> +<span id="L193" class="LineNr">193 </span><span class="Special">% Scheduling_interval = 1;</span> +<span id="L194" class="LineNr">194 </span><span class="muRecipe">def</span> f1 [ +<span id="L195" class="LineNr">195 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> +<span id="L196" class="LineNr">196 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> +<span id="L197" class="LineNr">197 </span>] +<span id="L198" class="LineNr">198 </span><span class="traceContains">+schedule: f1</span> +<span id="L199" class="LineNr">199 </span><span class="traceContains">+run: {1: "number"} <- copy {0: "literal"}</span> +<span id="L200" class="LineNr">200 </span><span class="traceContains">+schedule: f1</span> +<span id="L201" class="LineNr">201 </span><span class="traceContains">+run: {2: "number"} <- copy {0: "literal"}</span> +<span id="L202" class="LineNr">202 </span> +<span id="L203" class="LineNr">203 </span><span class="Delimiter">:(scenario scheduler_interleaves_routines)</span> +<span id="L204" class="LineNr">204 </span><span class="Special">% Scheduling_interval = 1;</span> +<span id="L205" class="LineNr">205 </span><span class="muRecipe">def</span> f1 [ +<span id="L206" class="LineNr">206 </span> start-running f2 +<span id="L207" class="LineNr">207 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> +<span id="L208" class="LineNr">208 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> +<span id="L209" class="LineNr">209 </span>] +<span id="L210" class="LineNr">210 </span><span class="muRecipe">def</span> f2 [ +<span id="L211" class="LineNr">211 </span> <span class="Constant">3</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> +<span id="L212" class="LineNr">212 </span> <span class="Constant">4</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> +<span id="L213" class="LineNr">213 </span>] +<span id="L214" class="LineNr">214 </span><span class="traceContains">+schedule: f1</span> +<span id="L215" class="LineNr">215 </span><span class="traceContains">+run: start-running {f2: "recipe-literal"}</span> +<span id="L216" class="LineNr">216 </span><span class="traceContains">+schedule: f2</span> +<span id="L217" class="LineNr">217 </span><span class="traceContains">+run: {3: "number"} <- copy {0: "literal"}</span> +<span id="L218" class="LineNr">218 </span><span class="traceContains">+schedule: f1</span> +<span id="L219" class="LineNr">219 </span><span class="traceContains">+run: {1: "number"} <- copy {0: "literal"}</span> +<span id="L220" class="LineNr">220 </span><span class="traceContains">+schedule: f2</span> +<span id="L221" class="LineNr">221 </span><span class="traceContains">+run: {4: "number"} <- copy {0: "literal"}</span> +<span id="L222" class="LineNr">222 </span><span class="traceContains">+schedule: f1</span> +<span id="L223" class="LineNr">223 </span><span class="traceContains">+run: {2: "number"} <- copy {0: "literal"}</span> +<span id="L224" class="LineNr">224 </span> +<span id="L225" class="LineNr">225 </span><span class="Delimiter">:(scenario start_running_takes_ingredients)</span> +<span id="L226" class="LineNr">226 </span><span class="muRecipe">def</span> f1 [ +<span id="L227" class="LineNr">227 </span> start-running f2<span class="Delimiter">,</span> <span class="Constant">3</span> +<span id="L228" class="LineNr">228 </span> <span class="Comment"># wait for f2 to run</span> +<span id="L229" class="LineNr">229 </span> <span class="Delimiter">{</span> +<span id="L230" class="LineNr">230 </span> jump-unless <span class="Constant">1</span>:num<span class="Delimiter">,</span> -<span class="Constant">1</span> +<span id="L231" class="LineNr">231 </span> <span class="Delimiter">}</span> +<span id="L232" class="LineNr">232 </span>] +<span id="L233" class="LineNr">233 </span><span class="muRecipe">def</span> f2 [ +<span id="L234" class="LineNr">234 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>next-ingredient +<span id="L235" class="LineNr">235 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>add <span class="Constant">1</span>:num<span class="Delimiter">,</span> <span class="Constant">1</span> +<span id="L236" class="LineNr">236 </span>] +<span id="L237" class="LineNr">237 </span><span class="traceContains">+mem: storing 4 in location 2</span> +<span id="L238" class="LineNr">238 </span> +<span id="L239" class="LineNr">239 </span><span class="Comment">//: type-checking for 'start-running'</span> +<span id="L240" class="LineNr">240 </span> +<span id="L241" class="LineNr">241 </span><span class="Delimiter">:(scenario start_running_checks_types)</span> +<span id="L242" class="LineNr">242 </span><span class="Special">% Hide_errors = true;</span> +<span id="L243" class="LineNr">243 </span><span class="muRecipe">def</span> f1 [ +<span id="L244" class="LineNr">244 </span> start-running f2<span class="Delimiter">,</span> <span class="Constant">3</span> +<span id="L245" class="LineNr">245 </span>] +<span id="L246" class="LineNr">246 </span><span class="muRecipe">def</span> f2 n:&:num [ +<span id="L247" class="LineNr">247 </span>] +<span id="L248" class="LineNr">248 </span><span class="traceContains">+error: f1: ingredient 0 has the wrong type at 'start-running f2, 3'</span> +<span id="L249" class="LineNr">249 </span> +<span id="L250" class="LineNr">250 </span><span class="Comment">// 'start-running' only uses the ingredients of the callee, not its products</span> +<span id="L251" class="LineNr">251 </span><span class="Delimiter">:(before "End <a href='072recipe.cc.html#L257'>is_indirect_call_with_ingredients</a> Special-cases")</span> +<span id="L252" class="LineNr">252 </span><span class="Normal">if</span> <span class="Delimiter">(</span>r == START_RUNNING<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> +<span id="L253" class="LineNr">253 </span> +<span id="L254" class="LineNr">254 </span><span class="Comment">//: back to testing 'start-running'</span> +<span id="L255" class="LineNr">255 </span> +<span id="L256" class="LineNr">256 </span><span class="Delimiter">:(scenario start_running_returns_routine_id)</span> +<span id="L257" class="LineNr">257 </span><span class="muRecipe">def</span> f1 [ +<span id="L258" class="LineNr">258 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>start-running f2 +<span id="L259" class="LineNr">259 </span>] +<span id="L260" class="LineNr">260 </span><span class="muRecipe">def</span> f2 [ +<span id="L261" class="LineNr">261 </span> <span class="Constant">12</span>:num<span class="Special"> <- </span>copy <span class="Constant">44</span> +<span id="L262" class="LineNr">262 </span>] +<span id="L263" class="LineNr">263 </span><span class="traceContains">+mem: storing 2 in location 1</span> +<span id="L264" class="LineNr">264 </span> +<span id="L265" class="LineNr">265 </span><span class="Comment">//: this scenario will require some careful setup in escaped C++</span> +<span id="L266" class="LineNr">266 </span><span class="Comment">//: (straining our tangle capabilities to near-breaking point)</span> +<span id="L267" class="LineNr">267 </span><span class="Delimiter">:(scenario scheduler_skips_completed_routines)</span> +<span id="L268" class="LineNr">268 </span><span class="Special">% <a href='010vm.cc.html#L14'>recipe_ordinal</a> f1 = load("recipe f1 [\n1:num <- copy 0\n]\n").front();</span> +<span id="L269" class="LineNr">269 </span><span class="Special">% <a href='010vm.cc.html#L14'>recipe_ordinal</a> f2 = load("recipe f2 [\n2:num <- copy 0\n]\n").front();</span> +<span id="L270" class="LineNr">270 </span><span class="Special">% Routines.push_back(new routine(f1)); // f1 meant to run</span> +<span id="L271" class="LineNr">271 </span><span class="Special">% Routines.push_back(new routine(f2));</span> +<span id="L272" class="LineNr">272 </span><span class="Special">% Routines.back()->state = COMPLETED; // f2 not meant to run</span> +<span id="L273" class="LineNr">273 </span><span class="Comment"># must have at least one routine without escaping</span> +<span id="L274" class="LineNr">274 </span><span class="muRecipe">def</span> f3 [ +<span id="L275" class="LineNr">275 </span> <span class="Constant">3</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> +<span id="L276" class="LineNr">276 </span>] +<span id="L277" class="LineNr">277 </span><span class="Comment"># by interleaving '+' lines with '-' lines, we allow f1 and f3 to run in any order</span> +<span id="L278" class="LineNr">278 </span><span class="traceContains">+schedule: f1</span> +<span id="L279" class="LineNr">279 </span><span class="traceContains">+mem: storing 0 in location 1</span> +<span id="L280" class="LineNr">280 </span><span class="traceAbsent">-schedule: f2</span> +<span id="L281" class="LineNr">281 </span><span class="traceAbsent">-mem: storing 0 in location 2</span> +<span id="L282" class="LineNr">282 </span><span class="traceContains">+schedule: f3</span> +<span id="L283" class="LineNr">283 </span><span class="traceContains">+mem: storing 0 in location 3</span> +<span id="L284" class="LineNr">284 </span> +<span id="L285" class="LineNr">285 </span><span class="Delimiter">:(scenario scheduler_starts_at_middle_of_routines)</span> +<span id="L286" class="LineNr">286 </span><span class="Special">% Routines.push_back(new routine(COPY));</span> +<span id="L287" class="LineNr">287 </span><span class="Special">% Routines.back()->state = COMPLETED;</span> +<span id="L288" class="LineNr">288 </span><span class="muRecipe">def</span> f1 [ +<span id="L289" class="LineNr">289 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> +<span id="L290" class="LineNr">290 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> +<span id="L291" class="LineNr">291 </span>] +<span id="L292" class="LineNr">292 </span><span class="traceContains">+schedule: f1</span> +<span id="L293" class="LineNr">293 </span><span class="traceAbsent">-run: idle</span> +<span id="L294" class="LineNr">294 </span> +<span id="L295" class="LineNr">295 </span><span class="SalientComment">//:: Errors in a routine cause it to terminate.</span> +<span id="L296" class="LineNr">296 </span> +<span id="L297" class="LineNr">297 </span><span class="Delimiter">:(scenario scheduler_terminates_routines_after_errors)</span> +<span id="L298" class="LineNr">298 </span><span class="Special">% Hide_errors = true;</span> +<span id="L299" class="LineNr">299 </span><span class="Special">% Scheduling_interval = 2;</span> +<span id="L300" class="LineNr">300 </span><span class="muRecipe">def</span> f1 [ +<span id="L301" class="LineNr">301 </span> start-running f2 +<span id="L302" class="LineNr">302 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> +<span id="L303" class="LineNr">303 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> +<span id="L304" class="LineNr">304 </span>] +<span id="L305" class="LineNr">305 </span><span class="muRecipe">def</span> f2 [ +<span id="L306" class="LineNr">306 </span> <span class="Comment"># divide by 0 twice</span> +<span id="L307" class="LineNr">307 </span> <span class="Constant">3</span>:num<span class="Special"> <- </span>divide-with-remainder <span class="Constant">4</span><span class="Delimiter">,</span> <span class="Constant">0</span> +<span id="L308" class="LineNr">308 </span> <span class="Constant">4</span>:num<span class="Special"> <- </span>divide-with-remainder <span class="Constant">4</span><span class="Delimiter">,</span> <span class="Constant">0</span> +<span id="L309" class="LineNr">309 </span>] +<span id="L310" class="LineNr">310 </span><span class="Comment"># f2 should stop after first divide by 0</span> +<span id="L311" class="LineNr">311 </span><span class="traceContains">+error: f2: divide by zero in '3:num <- divide-with-remainder 4, 0'</span> +<span id="L312" class="LineNr">312 </span><span class="traceAbsent">-error: f2: divide by zero in '4:num <- divide-with-remainder 4, 0'</span> +<span id="L313" class="LineNr">313 </span> +<span id="L314" class="LineNr">314 </span><span class="Delimiter">:(after "operator<<(ostream& os, <a href='001help.cc.html#L259'>vestigial</a> end)")</span> +<span id="L315" class="LineNr">315 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Trace_stream && Trace_stream<span class="Delimiter">-></span>curr_label == <span class="Constant">"error"</span> && Current_routine<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L316" class="LineNr">316 </span> Current_routine<span class="Delimiter">-></span>state = <a href='073scheduler.cc.html#L42'>COMPLETED</a><span class="Delimiter">;</span> +<span id="L317" class="LineNr">317 </span> <span class="Delimiter">}</span> +<span id="L318" class="LineNr">318 </span> +<span id="L319" class="LineNr">319 </span><span class="SalientComment">//:: Routines are marked completed when their parent completes.</span> +<span id="L320" class="LineNr">320 </span> +<span id="L321" class="LineNr">321 </span><span class="Delimiter">:(scenario scheduler_kills_orphans)</span> +<span id="L322" class="LineNr">322 </span><span class="muRecipe">def</span> <a href='000organization.cc.html#L113'>main</a> [ +<span id="L323" class="LineNr">323 </span> start-running f1 +<span id="L324" class="LineNr">324 </span> <span class="Comment"># f1 never actually runs because its parent completes without waiting for it</span> +<span id="L325" class="LineNr">325 </span>] +<span id="L326" class="LineNr">326 </span><span class="muRecipe">def</span> f1 [ +<span id="L327" class="LineNr">327 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> +<span id="L328" class="LineNr">328 </span>] +<span id="L329" class="LineNr">329 </span><span class="traceAbsent">-schedule: f1</span> +<span id="L330" class="LineNr">330 </span> +<span id="L331" class="LineNr">331 </span><span class="Delimiter">:(before "End Scheduler Cleanup")</span> +<span id="L332" class="LineNr">332 </span><span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L333" class="LineNr">333 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state == <a href='073scheduler.cc.html#L42'>COMPLETED</a><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> +<span id="L334" class="LineNr">334 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>parent_index < <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// root thread</span> +<span id="L335" class="LineNr">335 </span> <span class="Comment">// structured concurrency: <a href="http://250bpm.com/blog:71">http://250bpm.com/blog:71</a></span> +<span id="L336" class="LineNr">336 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>has_completed_parent<span class="Delimiter">(</span>i<span class="Delimiter">))</span> <span class="Delimiter">{</span> +<span id="L337" class="LineNr">337 </span> Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state = <a href='073scheduler.cc.html#L42'>COMPLETED</a><span class="Delimiter">;</span> +<span id="L338" class="LineNr">338 </span> <span class="Delimiter">}</span> +<span id="L339" class="LineNr">339 </span><span class="Delimiter">}</span> +<span id="L340" class="LineNr">340 </span> +<span id="L341" class="LineNr">341 </span><span class="Delimiter">:(code)</span> +<span id="L342" class="LineNr">342 </span><span class="Normal">bool</span> has_completed_parent<span class="Delimiter">(</span><span class="Normal">int</span> routine_index<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L343" class="LineNr">343 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> j = routine_index<span class="Delimiter">;</span> j >= <span class="Constant">0</span><span class="Delimiter">;</span> j = Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)-></span>parent_index<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L344" class="LineNr">344 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">)-></span>state == <a href='073scheduler.cc.html#L42'>COMPLETED</a><span class="Delimiter">)</span> +<span id="L345" class="LineNr">345 </span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> +<span id="L346" class="LineNr">346 </span> <span class="Delimiter">}</span> +<span id="L347" class="LineNr">347 </span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span id="L348" class="LineNr">348 </span><span class="Delimiter">}</span> +<span id="L349" class="LineNr">349 </span> +<span id="L350" class="LineNr">350 </span><span class="SalientComment">//:: 'routine-state' can tell if a given routine id is running</span> +<span id="L351" class="LineNr">351 </span> +<span id="L352" class="LineNr">352 </span><span class="Delimiter">:(scenario routine_state_test)</span> +<span id="L353" class="LineNr">353 </span><span class="Special">% Scheduling_interval = 2;</span> +<span id="L354" class="LineNr">354 </span><span class="muRecipe">def</span> f1 [ +<span id="L355" class="LineNr">355 </span> <span class="Constant">1</span>:num/child-id<span class="Special"> <- </span>start-running f2 +<span id="L356" class="LineNr">356 </span> <span class="Constant">12</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># race condition since we don't care about location 12</span> +<span id="L357" class="LineNr">357 </span> <span class="Comment"># thanks to Scheduling_interval, f2's one instruction runs in between here and completes</span> +<span id="L358" class="LineNr">358 </span> <span class="Constant">2</span>:num/state<span class="Special"> <- </span>routine-state <span class="Constant">1</span>:num/child-id +<span id="L359" class="LineNr">359 </span>] +<span id="L360" class="LineNr">360 </span><span class="muRecipe">def</span> f2 [ +<span id="L361" class="LineNr">361 </span> <span class="Constant">12</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> +<span id="L362" class="LineNr">362 </span> <span class="Comment"># trying to run a second instruction marks routine as completed</span> +<span id="L363" class="LineNr">363 </span>] +<span id="L364" class="LineNr">364 </span><span class="Comment"># recipe f2 should be in state COMPLETED</span> +<span id="L365" class="LineNr">365 </span><span class="traceContains">+mem: storing 1 in location 2</span> +<span id="L366" class="LineNr">366 </span> +<span id="L367" class="LineNr">367 </span><span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +<span id="L368" class="LineNr">368 </span>ROUTINE_STATE<span class="Delimiter">,</span> +<span id="L369" class="LineNr">369 </span><span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +<span id="L370" class="LineNr">370 </span><a href='001help.cc.html#L221'>put</a><span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"routine-state"</span><span class="Delimiter">,</span> ROUTINE_STATE<span class="Delimiter">);</span> +<span id="L371" class="LineNr">371 </span><span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span id="L372" class="LineNr">372 </span><span class="Normal">case</span> ROUTINE_STATE: <span class="Delimiter">{</span> +<span id="L373" class="LineNr">373 </span> <span class="Normal">if</span> <span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L374" class="LineNr">374 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'routine-state' requires exactly one ingredient, but got '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> +<span id="L375" class="LineNr">375 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L376" class="LineNr">376 </span> <span class="Delimiter">}</span> +<span id="L377" class="LineNr">377 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> +<span id="L378" class="LineNr">378 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'routine-state' should be a routine id generated by 'start-running', but got '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> +<span id="L379" class="LineNr">379 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L380" class="LineNr">380 </span> <span class="Delimiter">}</span> +<span id="L381" class="LineNr">381 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L382" class="LineNr">382 </span><span class="Delimiter">}</span> +<span id="L383" class="LineNr">383 </span><span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span id="L384" class="LineNr">384 </span><span class="Normal">case</span> ROUTINE_STATE: <span class="Delimiter">{</span> +<span id="L385" class="LineNr">385 </span> <span class="Normal">int</span> id = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> +<span id="L386" class="LineNr">386 </span> <span class="Normal">int</span> result = -<span class="Constant">1</span><span class="Delimiter">;</span> +<span id="L387" class="LineNr">387 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L388" class="LineNr">388 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>id == id<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L389" class="LineNr">389 </span> result = Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state<span class="Delimiter">;</span> +<span id="L390" class="LineNr">390 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L391" class="LineNr">391 </span> <span class="Delimiter">}</span> +<span id="L392" class="LineNr">392 </span> <span class="Delimiter">}</span> +<span id="L393" class="LineNr">393 </span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> +<span id="L394" class="LineNr">394 </span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> +<span id="L395" class="LineNr">395 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L396" class="LineNr">396 </span><span class="Delimiter">}</span> +<span id="L397" class="LineNr">397 </span> +<span id="L398" class="LineNr">398 </span><span class="SalientComment">//:: miscellaneous helpers</span> +<span id="L399" class="LineNr">399 </span> +<span id="L400" class="LineNr">400 </span><span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +<span id="L401" class="LineNr">401 </span>STOP<span class="Delimiter">,</span> +<span id="L402" class="LineNr">402 </span><span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +<span id="L403" class="LineNr">403 </span><a href='001help.cc.html#L221'>put</a><span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"stop"</span><span class="Delimiter">,</span> STOP<span class="Delimiter">);</span> +<span id="L404" class="LineNr">404 </span><span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span id="L405" class="LineNr">405 </span><span class="Normal">case</span> STOP: <span class="Delimiter">{</span> +<span id="L406" class="LineNr">406 </span> <span class="Normal">if</span> <span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L407" class="LineNr">407 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'stop' requires exactly one ingredient, but got '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> +<span id="L408" class="LineNr">408 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L409" class="LineNr">409 </span> <span class="Delimiter">}</span> +<span id="L410" class="LineNr">410 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> +<span id="L411" class="LineNr">411 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'stop' should be a routine id generated by 'start-running', but got '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> +<span id="L412" class="LineNr">412 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L413" class="LineNr">413 </span> <span class="Delimiter">}</span> +<span id="L414" class="LineNr">414 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L415" class="LineNr">415 </span><span class="Delimiter">}</span> +<span id="L416" class="LineNr">416 </span><span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span id="L417" class="LineNr">417 </span><span class="Normal">case</span> STOP: <span class="Delimiter">{</span> +<span id="L418" class="LineNr">418 </span> <span class="Normal">int</span> id = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> +<span id="L419" class="LineNr">419 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L420" class="LineNr">420 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>id == id<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L421" class="LineNr">421 </span> Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state = <a href='073scheduler.cc.html#L42'>COMPLETED</a><span class="Delimiter">;</span> +<span id="L422" class="LineNr">422 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L423" class="LineNr">423 </span> <span class="Delimiter">}</span> +<span id="L424" class="LineNr">424 </span> <span class="Delimiter">}</span> +<span id="L425" class="LineNr">425 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L426" class="LineNr">426 </span><span class="Delimiter">}</span> +<span id="L427" class="LineNr">427 </span> +<span id="L428" class="LineNr">428 </span><span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +<span id="L429" class="LineNr">429 </span>_DUMP_ROUTINES<span class="Delimiter">,</span> +<span id="L430" class="LineNr">430 </span><span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +<span id="L431" class="LineNr">431 </span><a href='001help.cc.html#L221'>put</a><span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"$dump-routines"</span><span class="Delimiter">,</span> _DUMP_ROUTINES<span class="Delimiter">);</span> +<span id="L432" class="LineNr">432 </span><span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span id="L433" class="LineNr">433 </span><span class="Normal">case</span> _DUMP_ROUTINES: <span class="Delimiter">{</span> +<span id="L434" class="LineNr">434 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L435" class="LineNr">435 </span><span class="Delimiter">}</span> +<span id="L436" class="LineNr">436 </span><span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span id="L437" class="LineNr">437 </span><span class="Normal">case</span> _DUMP_ROUTINES: <span class="Delimiter">{</span> +<span id="L438" class="LineNr">438 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L439" class="LineNr">439 </span> cerr << i << <span class="Constant">": "</span> << Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>id << <span class="Constant">' '</span> << Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state << <span class="Constant">' '</span> << Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>parent_index << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> +<span id="L440" class="LineNr">440 </span> <span class="Delimiter">}</span> +<span id="L441" class="LineNr">441 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L442" class="LineNr">442 </span><span class="Delimiter">}</span> +<span id="L443" class="LineNr">443 </span> +<span id="L444" class="LineNr">444 </span><span class="Comment">//: support for stopping routines after some number of cycles</span> +<span id="L445" class="LineNr">445 </span> +<span id="L446" class="LineNr">446 </span><span class="Delimiter">:(scenario routine_discontinues_past_limit)</span> +<span id="L447" class="LineNr">447 </span><span class="Special">% Scheduling_interval = 2;</span> +<span id="L448" class="LineNr">448 </span><span class="muRecipe">def</span> f1 [ +<span id="L449" class="LineNr">449 </span> <span class="Constant">1</span>:num/child-id<span class="Special"> <- </span>start-running f2 +<span id="L450" class="LineNr">450 </span> limit-time <span class="Constant">1</span>:num/child-id<span class="Delimiter">,</span> <span class="Constant">10</span> +<span id="L451" class="LineNr">451 </span> <span class="Comment"># padding loop just to make sure f2 has time to completed</span> +<span id="L452" class="LineNr">452 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">20</span> +<span id="L453" class="LineNr">453 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>subtract <span class="Constant">2</span>:num<span class="Delimiter">,</span> <span class="Constant">1</span> +<span id="L454" class="LineNr">454 </span> jump-<span class="Normal">if</span> <span class="Constant">2</span>:num<span class="Delimiter">,</span> <span class="Constant">-2:offset</span> +<span id="L455" class="LineNr">455 </span>] +<span id="L456" class="LineNr">456 </span><span class="muRecipe">def</span> f2 [ +<span id="L457" class="LineNr">457 </span> jump <span class="Constant">-1:offset</span> <span class="Comment"># run forever</span> +<span id="L458" class="LineNr">458 </span> $print [should never get here]<span class="Delimiter">,</span> <span class="Constant">10</span>/newline +<span id="L459" class="LineNr">459 </span>] +<span id="L460" class="LineNr">460 </span><span class="Comment"># f2 terminates</span> +<span id="L461" class="LineNr">461 </span><span class="traceContains">+schedule: discontinuing routine 2</span> +<span id="L462" class="LineNr">462 </span> +<span id="L463" class="LineNr">463 </span><span class="Delimiter">:(before "End routine States")</span> +<span id="L464" class="LineNr">464 </span>DISCONTINUED<span class="Delimiter">,</span> +<span id="L465" class="LineNr">465 </span><span class="Delimiter">:(before "End Scheduler State Transitions")</span> +<span id="L466" class="LineNr">466 </span><span class="Normal">if</span> <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>limit >= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L467" class="LineNr">467 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>limit <= Scheduling_interval<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L468" class="LineNr">468 </span> <a href='003trace.cc.html#L167'>trace</a><span class="Delimiter">(</span><span class="Constant">"schedule"</span><span class="Delimiter">)</span> << <span class="Constant">"discontinuing routine "</span> << Current_routine<span class="Delimiter">-></span>id << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> +<span id="L469" class="LineNr">469 </span> Current_routine<span class="Delimiter">-></span>state = DISCONTINUED<span class="Delimiter">;</span> +<span id="L470" class="LineNr">470 </span> Current_routine<span class="Delimiter">-></span>limit = <span class="Constant">0</span><span class="Delimiter">;</span> +<span id="L471" class="LineNr">471 </span> <span class="Delimiter">}</span> +<span id="L472" class="LineNr">472 </span> <span class="Normal">else</span> <span class="Delimiter">{</span> +<span id="L473" class="LineNr">473 </span> Current_routine<span class="Delimiter">-></span>limit -= Scheduling_interval<span class="Delimiter">;</span> +<span id="L474" class="LineNr">474 </span> <span class="Delimiter">}</span> +<span id="L475" class="LineNr">475 </span><span class="Delimiter">}</span> +<span id="L476" class="LineNr">476 </span> +<span id="L477" class="LineNr">477 </span><span class="Delimiter">:(before "End Test Teardown")</span> +<span id="L478" class="LineNr">478 </span><span class="Normal">if</span> <span class="Delimiter">(</span>Passed && any_routines_with_error<span class="Delimiter">())</span> +<span id="L479" class="LineNr">479 </span> <a href='003trace.cc.html#L174'>raise</a> << <span class="Constant">"some routines died with errors</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> +<span id="L480" class="LineNr">480 </span><span class="Delimiter">:(before "End Mu Test Teardown")</span> +<span id="L481" class="LineNr">481 </span><span class="Normal">if</span> <span class="Delimiter">(</span>Passed && any_routines_with_error<span class="Delimiter">())</span> +<span id="L482" class="LineNr">482 </span> <a href='003trace.cc.html#L174'>raise</a> << Current_scenario<span class="Delimiter">-></span>name << <span class="Constant">": some routines died with errors</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> +<span id="L483" class="LineNr">483 </span> +<span id="L484" class="LineNr">484 </span><span class="Delimiter">:(code)</span> +<span id="L485" class="LineNr">485 </span><span class="Normal">bool</span> any_routines_with_error<span class="Delimiter">()</span> <span class="Delimiter">{</span> +<span id="L486" class="LineNr">486 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L487" class="LineNr">487 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state == DISCONTINUED<span class="Delimiter">)</span> +<span id="L488" class="LineNr">488 </span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> +<span id="L489" class="LineNr">489 </span> <span class="Delimiter">}</span> +<span id="L490" class="LineNr">490 </span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span id="L491" class="LineNr">491 </span><span class="Delimiter">}</span> +<span id="L492" class="LineNr">492 </span> +<span id="L493" class="LineNr">493 </span><span class="Delimiter">:(before "End routine Fields")</span> +<span id="L494" class="LineNr">494 </span><span class="Normal">int</span> limit<span class="Delimiter">;</span> +<span id="L495" class="LineNr">495 </span><span class="Delimiter">:(before "End routine Constructor")</span> +<span id="L496" class="LineNr">496 </span>limit = -<span class="Constant">1</span><span class="Delimiter">;</span> <span class="Comment">/*</span><span class="Comment"> no limit </span><span class="Comment">*/</span> +<span id="L497" class="LineNr">497 </span> +<span id="L498" class="LineNr">498 </span><span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +<span id="L499" class="LineNr">499 </span>LIMIT_TIME<span class="Delimiter">,</span> +<span id="L500" class="LineNr">500 </span><span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +<span id="L501" class="LineNr">501 </span><a href='001help.cc.html#L221'>put</a><span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"limit-time"</span><span class="Delimiter">,</span> LIMIT_TIME<span class="Delimiter">);</span> +<span id="L502" class="LineNr">502 </span><span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span id="L503" class="LineNr">503 </span><span class="Normal">case</span> LIMIT_TIME: <span class="Delimiter">{</span> +<span id="L504" class="LineNr">504 </span> <span class="Normal">if</span> <span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L505" class="LineNr">505 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'limit-time' requires exactly two ingredient, but got '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> +<span id="L506" class="LineNr">506 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L507" class="LineNr">507 </span> <span class="Delimiter">}</span> +<span id="L508" class="LineNr">508 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> +<span id="L509" class="LineNr">509 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'limit-time' should be a routine id generated by 'start-running', but got '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> +<span id="L510" class="LineNr">510 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L511" class="LineNr">511 </span> <span class="Delimiter">}</span> +<span id="L512" class="LineNr">512 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> +<span id="L513" class="LineNr">513 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"second ingredient of 'limit-time' should be a number (of instructions to run for), but got '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> +<span id="L514" class="LineNr">514 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L515" class="LineNr">515 </span> <span class="Delimiter">}</span> +<span id="L516" class="LineNr">516 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L517" class="LineNr">517 </span><span class="Delimiter">}</span> +<span id="L518" class="LineNr">518 </span><span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span id="L519" class="LineNr">519 </span><span class="Normal">case</span> LIMIT_TIME: <span class="Delimiter">{</span> +<span id="L520" class="LineNr">520 </span> <span class="Normal">int</span> id = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> +<span id="L521" class="LineNr">521 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L522" class="LineNr">522 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>id == id<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L523" class="LineNr">523 </span> Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>limit = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> +<span id="L524" class="LineNr">524 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L525" class="LineNr">525 </span> <span class="Delimiter">}</span> +<span id="L526" class="LineNr">526 </span> <span class="Delimiter">}</span> +<span id="L527" class="LineNr">527 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L528" class="LineNr">528 </span><span class="Delimiter">}</span> +<span id="L529" class="LineNr">529 </span> +<span id="L530" class="LineNr">530 </span><span class="Delimiter">:(before "End routine Fields")</span> +<span id="L531" class="LineNr">531 </span><span class="Normal">int</span> instructions_run<span class="Delimiter">;</span> +<span id="L532" class="LineNr">532 </span><span class="Delimiter">:(before "End routine Constructor")</span> +<span id="L533" class="LineNr">533 </span>instructions_run = <span class="Constant">0</span><span class="Delimiter">;</span> +<span id="L534" class="LineNr">534 </span><span class="Delimiter">:(before "Reset instructions_run_this_scheduling_slice")</span> +<span id="L535" class="LineNr">535 </span>Current_routine<span class="Delimiter">-></span>instructions_run += Current_routine<span class="Delimiter">-></span>instructions_run_this_scheduling_slice<span class="Delimiter">;</span> +<span id="L536" class="LineNr">536 </span><span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +<span id="L537" class="LineNr">537 </span>NUMBER_OF_INSTRUCTIONS<span class="Delimiter">,</span> +<span id="L538" class="LineNr">538 </span><span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +<span id="L539" class="LineNr">539 </span><a href='001help.cc.html#L221'>put</a><span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"number-of-instructions"</span><span class="Delimiter">,</span> NUMBER_OF_INSTRUCTIONS<span class="Delimiter">);</span> +<span id="L540" class="LineNr">540 </span><span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span id="L541" class="LineNr">541 </span><span class="Normal">case</span> NUMBER_OF_INSTRUCTIONS: <span class="Delimiter">{</span> +<span id="L542" class="LineNr">542 </span> <span class="Normal">if</span> <span class="Delimiter">(</span><a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L543" class="LineNr">543 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'number-of-instructions' requires exactly one ingredient, but got '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> +<span id="L544" class="LineNr">544 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L545" class="LineNr">545 </span> <span class="Delimiter">}</span> +<span id="L546" class="LineNr">546 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> +<span id="L547" class="LineNr">547 </span> <a href='003trace.cc.html#L174'>raise</a> << <a href='013update_operation.cc.html#L25'>maybe</a><span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'number-of-instructions' should be a routine id generated by 'start-running', but got '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << <a href='003trace.cc.html#L203'>end</a><span class="Delimiter">();</span> +<span id="L548" class="LineNr">548 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L549" class="LineNr">549 </span> <span class="Delimiter">}</span> +<span id="L550" class="LineNr">550 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L551" class="LineNr">551 </span><span class="Delimiter">}</span> +<span id="L552" class="LineNr">552 </span><span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span id="L553" class="LineNr">553 </span><span class="Normal">case</span> NUMBER_OF_INSTRUCTIONS: <span class="Delimiter">{</span> +<span id="L554" class="LineNr">554 </span> <span class="Normal">int</span> id = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> +<span id="L555" class="LineNr">555 </span> <span class="Normal">int</span> result = -<span class="Constant">1</span><span class="Delimiter">;</span> +<span id="L556" class="LineNr">556 </span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < <a href='001help.cc.html#L141'>SIZE</a><span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L557" class="LineNr">557 </span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>id == id<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span id="L558" class="LineNr">558 </span> result = Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>instructions_run<span class="Delimiter">;</span> +<span id="L559" class="LineNr">559 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L560" class="LineNr">560 </span> <span class="Delimiter">}</span> +<span id="L561" class="LineNr">561 </span> <span class="Delimiter">}</span> +<span id="L562" class="LineNr">562 </span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> +<span id="L563" class="LineNr">563 </span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> +<span id="L564" class="LineNr">564 </span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span id="L565" class="LineNr">565 </span><span class="Delimiter">}</span> +<span id="L566" class="LineNr">566 </span> +<span id="L567" class="LineNr">567 </span><span class="Delimiter">:(scenario number_of_instructions)</span> +<span id="L568" class="LineNr">568 </span><span class="muRecipe">def</span> f1 [ +<span id="L569" class="LineNr">569 </span> <span class="Constant">10</span>:num/child-id<span class="Special"> <- </span>start-running f2 +<span id="L570" class="LineNr">570 </span> <span class="Delimiter">{</span> +<span id="L571" class="LineNr">571 </span> loop-unless <span class="Constant">20</span>:num +<span id="L572" class="LineNr">572 </span> <span class="Delimiter">}</span> +<span id="L573" class="LineNr">573 </span> <span class="Constant">11</span>:num<span class="Special"> <- </span>number-of-instructions <span class="Constant">10</span>:num +<span id="L574" class="LineNr">574 </span>] +<span id="L575" class="LineNr">575 </span><span class="muRecipe">def</span> f2 [ +<span id="L576" class="LineNr">576 </span> <span class="Comment"># 2 instructions worth of work</span> +<span id="L577" class="LineNr">577 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">34</span> +<span id="L578" class="LineNr">578 </span> <span class="Constant">20</span>:num<span class="Special"> <- </span>copy <span class="Constant">1</span> +<span id="L579" class="LineNr">579 </span>] +<span id="L580" class="LineNr">580 </span><span class="Comment"># f2 runs an extra instruction for the implicit return added by the</span> +<span id="L581" class="LineNr">581 </span><span class="Comment"># fill_in_return_ingredients transform</span> +<span id="L582" class="LineNr">582 </span><span class="traceContains">+mem: storing 3 in location 11</span> +<span id="L583" class="LineNr">583 </span> +<span id="L584" class="LineNr">584 </span><span class="Delimiter">:(scenario number_of_instructions_across_multiple_scheduling_intervals)</span> +<span id="L585" class="LineNr">585 </span><span class="Special">% Scheduling_interval = 1;</span> +<span id="L586" class="LineNr">586 </span><span class="muRecipe">def</span> f1 [ +<span id="L587" class="LineNr">587 </span> <span class="Constant">10</span>:num/child-id<span class="Special"> <- </span>start-running f2 +<span id="L588" class="LineNr">588 </span> <span class="Delimiter">{</span> +<span id="L589" class="LineNr">589 </span> loop-unless <span class="Constant">20</span>:num +<span id="L590" class="LineNr">590 </span> <span class="Delimiter">}</span> +<span id="L591" class="LineNr">591 </span> <span class="Constant">11</span>:num<span class="Special"> <- </span>number-of-instructions <span class="Constant">10</span>:num +<span id="L592" class="LineNr">592 </span>] +<span id="L593" class="LineNr">593 </span><span class="muRecipe">def</span> f2 [ +<span id="L594" class="LineNr">594 </span> <span class="Comment"># 4 instructions worth of work</span> +<span id="L595" class="LineNr">595 </span> <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">34</span> +<span id="L596" class="LineNr">596 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">1</span> +<span id="L597" class="LineNr">597 </span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">3</span> +<span id="L598" class="LineNr">598 </span> <span class="Constant">20</span>:num<span class="Special"> <- </span>copy <span class="Constant">1</span> +<span id="L599" class="LineNr">599 </span>] +<span id="L600" class="LineNr">600 </span><span class="Comment"># f2 runs an extra instruction for the implicit return added by the</span> +<span id="L601" class="LineNr">601 </span><span class="Comment"># fill_in_return_ingredients transform</span> +<span id="L602" class="LineNr">602 </span><span class="traceContains">+mem: storing 5 in location 11</span> +<span id="L603" class="LineNr">603 </span> +<span id="L604" class="LineNr">604 </span><span class="SalientComment">//:: make sure that each routine gets a different alloc to start</span> +<span id="L605" class="LineNr">605 </span> +<span id="L606" class="LineNr">606 </span><span class="Delimiter">:(scenario new_concurrent)</span> +<span id="L607" class="LineNr">607 </span><span class="muRecipe">def</span> f1 [ +<span id="L608" class="LineNr">608 </span> start-running f2 +<span id="L609" class="LineNr">609 </span> <span class="Constant">1</span>:&:num/<span class="Special">raw <- </span><span class="Normal">new</span> <span class="Constant">number:type</span> +<span id="L610" class="LineNr">610 </span> <span class="Comment"># wait for f2 to complete</span> +<span id="L611" class="LineNr">611 </span> <span class="Delimiter">{</span> +<span id="L612" class="LineNr">612 </span> loop-unless <span class="Constant">4</span>:num/<span class="Special">raw</span> +<span id="L613" class="LineNr">613 </span> <span class="Delimiter">}</span> +<span id="L614" class="LineNr">614 </span>] +<span id="L615" class="LineNr">615 </span><span class="muRecipe">def</span> f2 [ +<span id="L616" class="LineNr">616 </span> <span class="Constant">2</span>:&:num/<span class="Special">raw <- </span><span class="Normal">new</span> <span class="Constant">number:type</span> +<span id="L617" class="LineNr">617 </span> <span class="Comment"># hack: assumes scheduler implementation</span> +<span id="L618" class="LineNr">618 </span> <span class="Constant">3</span>:<span class="Normal">bool</span>/<span class="Special">raw <- </span>equal <span class="Constant">1</span>:&:num/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2</span>:&:num/<span class="Special">raw</span> +<span id="L619" class="LineNr">619 </span> <span class="Comment"># signal f2 complete</span> +<span id="L620" class="LineNr">620 </span> <span class="Constant">4</span>:num/<span class="Special">raw <- </span>copy <span class="Constant">1</span> +<span id="L621" class="LineNr">621 </span>] +<span id="L622" class="LineNr">622 </span><span class="traceContains">+mem: storing 0 in location 3</span> </pre> </body> </html> diff --git a/html/075channel.mu.html b/html/075channel.mu.html index ccbc5178..43180f17 100644 --- a/html/075channel.mu.html +++ b/html/075channel.mu.html @@ -64,521 +64,513 @@ if ('onhashchange' in window) { <span id="L1" class="LineNr"> 1 </span><span class="Comment"># Mu synchronizes between routines using channels rather than locks, like</span> <span id="L2" class="LineNr"> 2 </span><span class="Comment"># Erlang and Go.</span> <span id="L3" class="LineNr"> 3 </span><span class="Comment">#</span> -<span id="L4" class="LineNr"> 4 </span><span class="Comment"># Key properties of channels:</span> -<span id="L5" class="LineNr"> 5 </span><span class="Comment">#</span> -<span id="L6" class="LineNr"> 6 </span><span class="Comment"># a) Writing to a full channel or reading from an empty one will put the</span> -<span id="L7" class="LineNr"> 7 </span><span class="Comment"># current routine in 'waiting' state until the operation can be completed.</span> -<span id="L8" class="LineNr"> 8 </span><span class="Comment">#</span> -<span id="L9" class="LineNr"> 9 </span><span class="Comment"># b) Writing to a channel implicitly performs a deep copy. This prevents</span> -<span id="L10" class="LineNr"> 10 </span><span class="Comment"># addresses from being shared between routines, and therefore eliminates all</span> -<span id="L11" class="LineNr"> 11 </span><span class="Comment"># possibility of race conditions.</span> -<span id="L12" class="LineNr"> 12 </span><span class="Comment">#</span> -<span id="L13" class="LineNr"> 13 </span><span class="Comment"># There's still a narrow window for race conditions: the inputs passed in</span> -<span id="L14" class="LineNr"> 14 </span><span class="Comment"># to 'start-running'. Pass only channels into routines and you should be fine.</span> -<span id="L15" class="LineNr"> 15 </span><span class="Comment"># Any other mutable inputs will require locks.</span> -<span id="L16" class="LineNr"> 16 </span> -<span id="L17" class="LineNr"> 17 </span><span class="muScenario">scenario</span> channel [ -<span id="L18" class="LineNr"> 18 </span> run [ -<span id="L19" class="LineNr"> 19 </span> <span class="Constant">local-scope</span> -<span id="L20" class="LineNr"> 20 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:num, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">3/capacity</span> -<span id="L21" class="LineNr"> 21 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>,<span class="Constant"> 34</span> -<span id="L22" class="LineNr"> 22 </span> 10:num/<span class="Special">raw</span>, 11:bool/<span class="Special">raw</span>, <a href='075channel.mu.html#L43'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L43'>source</a> -<span id="L23" class="LineNr"> 23 </span> ] -<span id="L24" class="LineNr"> 24 </span> memory-should-contain [ -<span id="L25" class="LineNr"> 25 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 34</span> -<span id="L26" class="LineNr"> 26 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># read was successful</span> -<span id="L27" class="LineNr"> 27 </span> ] -<span id="L28" class="LineNr"> 28 </span>] -<span id="L29" class="LineNr"> 29 </span> -<span id="L30" class="LineNr"> 30 </span><span class="muData">container</span> channel:_elem [ -<span id="L31" class="LineNr"> 31 </span> lock:bool <span class="Comment"># inefficient but simple: serialize all reads as well as writes</span> -<span id="L32" class="LineNr"> 32 </span> first-full:num <span class="Comment"># for write</span> -<span id="L33" class="LineNr"> 33 </span> first-free:num <span class="Comment"># for read</span> -<span id="L34" class="LineNr"> 34 </span> <span class="Comment"># A circular buffer contains values from index first-full up to (but not</span> -<span id="L35" class="LineNr"> 35 </span> <span class="Comment"># including) index first-free. The reader always modifies it at first-full,</span> -<span id="L36" class="LineNr"> 36 </span> <span class="Comment"># while the writer always modifies it at first-free.</span> -<span id="L37" class="LineNr"> 37 </span> data:&:@:_elem +<span id="L4" class="LineNr"> 4 </span><span class="Comment"># The key property of channels: Writing to a full channel or reading from an</span> +<span id="L5" class="LineNr"> 5 </span><span class="Comment"># empty one will put the current routine in 'waiting' state until the</span> +<span id="L6" class="LineNr"> 6 </span><span class="Comment"># operation can be completed.</span> +<span id="L7" class="LineNr"> 7 </span><span class="Comment">#</span> +<span id="L8" class="LineNr"> 8 </span><span class="Comment"># Beware of addresses passed into channels. They can cause race conditions.</span> +<span id="L9" class="LineNr"> 9 </span> +<span id="L10" class="LineNr"> 10 </span><span class="muScenario">scenario</span> channel [ +<span id="L11" class="LineNr"> 11 </span> run [ +<span id="L12" class="LineNr"> 12 </span> <span class="Constant">local-scope</span> +<span id="L13" class="LineNr"> 13 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:num, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">3/capacity</span> +<span id="L14" class="LineNr"> 14 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>,<span class="Constant"> 34</span> +<span id="L15" class="LineNr"> 15 </span> 10:num/<span class="Special">raw</span>, 11:bool/<span class="Special">raw</span>, <a href='075channel.mu.html#L36'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L36'>source</a> +<span id="L16" class="LineNr"> 16 </span> ] +<span id="L17" class="LineNr"> 17 </span> memory-should-contain [ +<span id="L18" class="LineNr"> 18 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 34</span> +<span id="L19" class="LineNr"> 19 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># read was successful</span> +<span id="L20" class="LineNr"> 20 </span> ] +<span id="L21" class="LineNr"> 21 </span>] +<span id="L22" class="LineNr"> 22 </span> +<span id="L23" class="LineNr"> 23 </span><span class="muData">container</span> channel:_elem [ +<span id="L24" class="LineNr"> 24 </span> lock:bool <span class="Comment"># inefficient but simple: serialize all reads as well as writes</span> +<span id="L25" class="LineNr"> 25 </span> first-full:num <span class="Comment"># for write</span> +<span id="L26" class="LineNr"> 26 </span> first-free:num <span class="Comment"># for read</span> +<span id="L27" class="LineNr"> 27 </span> <span class="Comment"># A circular buffer contains values from index first-full up to (but not</span> +<span id="L28" class="LineNr"> 28 </span> <span class="Comment"># including) index first-free. The reader always modifies it at first-full,</span> +<span id="L29" class="LineNr"> 29 </span> <span class="Comment"># while the writer always modifies it at first-free.</span> +<span id="L30" class="LineNr"> 30 </span> data:&:@:_elem +<span id="L31" class="LineNr"> 31 </span>] +<span id="L32" class="LineNr"> 32 </span> +<span id="L33" class="LineNr"> 33 </span><span class="Comment"># Since channels have two ends, and since it's an error to use either end from</span> +<span id="L34" class="LineNr"> 34 </span><span class="Comment"># multiple routines, let's distinguish the ends.</span> +<span id="L35" class="LineNr"> 35 </span> +<span id="L36" class="LineNr"> 36 </span><span class="muData">container</span> <a href='075channel.mu.html#L36'>source</a>:_elem [ +<span id="L37" class="LineNr"> 37 </span> chan:&:channel:_elem <span id="L38" class="LineNr"> 38 </span>] <span id="L39" class="LineNr"> 39 </span> -<span id="L40" class="LineNr"> 40 </span><span class="Comment"># Since channels have two ends, and since it's an error to use either end from</span> -<span id="L41" class="LineNr"> 41 </span><span class="Comment"># multiple routines, let's distinguish the ends.</span> -<span id="L42" class="LineNr"> 42 </span> -<span id="L43" class="LineNr"> 43 </span><span class="muData">container</span> <a href='075channel.mu.html#L43'>source</a>:_elem [ -<span id="L44" class="LineNr"> 44 </span> chan:&:channel:_elem -<span id="L45" class="LineNr"> 45 </span>] -<span id="L46" class="LineNr"> 46 </span> -<span id="L47" class="LineNr"> 47 </span><span class="muData">container</span> <a href='075channel.mu.html#L47'>sink</a>:_elem [ -<span id="L48" class="LineNr"> 48 </span> chan:&:channel:_elem -<span id="L49" class="LineNr"> 49 </span>] -<span id="L50" class="LineNr"> 50 </span> -<span id="L51" class="LineNr"> 51 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L51'>new-channel</a> <a href='075channel.mu.html#L399'>capacity</a>:num<span class="muRecipe"> -> </span>in:&:<a href='075channel.mu.html#L43'>source</a>:_elem, out:&:<a href='075channel.mu.html#L47'>sink</a>:_elem [ -<span id="L52" class="LineNr"> 52 </span> <span class="Constant">local-scope</span> -<span id="L53" class="LineNr"> 53 </span> <span class="Constant">load-inputs</span> -<span id="L54" class="LineNr"> 54 </span> result:&:channel:_elem <span class="Special"><-</span> new <span class="Delimiter">{</span>(channel _elem): type<span class="Delimiter">}</span> -<span id="L55" class="LineNr"> 55 </span> *result <span class="Special"><-</span> put *result, <span class="Constant">first-full:offset</span>,<span class="Constant"> 0</span> -<span id="L56" class="LineNr"> 56 </span> *result <span class="Special"><-</span> put *result, <span class="Constant">first-free:offset</span>,<span class="Constant"> 0</span> -<span id="L57" class="LineNr"> 57 </span> <a href='075channel.mu.html#L399'>capacity</a> <span class="Special"><-</span> add <a href='075channel.mu.html#L399'>capacity</a>,<span class="Constant"> 1</span> <span class="Comment"># unused slot for 'full?' below</span> -<span id="L58" class="LineNr"> 58 </span> data:&:@:_elem <span class="Special"><-</span> new <span class="Constant">_elem:type</span>, <a href='075channel.mu.html#L399'>capacity</a> -<span id="L59" class="LineNr"> 59 </span> *result <span class="Special"><-</span> put *result, <span class="Constant">data:offset</span>, data -<span id="L60" class="LineNr"> 60 </span> in <span class="Special"><-</span> new <span class="Delimiter">{</span>(source _elem): type<span class="Delimiter">}</span> -<span id="L61" class="LineNr"> 61 </span> *in <span class="Special"><-</span> put *in, <span class="Constant">chan:offset</span>, result -<span id="L62" class="LineNr"> 62 </span> out <span class="Special"><-</span> new <span class="Delimiter">{</span>(sink _elem): type<span class="Delimiter">}</span> -<span id="L63" class="LineNr"> 63 </span> *out <span class="Special"><-</span> put *out, <span class="Constant">chan:offset</span>, result -<span id="L64" class="LineNr"> 64 </span>] -<span id="L65" class="LineNr"> 65 </span> -<span id="L66" class="LineNr"> 66 </span><span class="Comment"># write a value to a channel</span> -<span id="L67" class="LineNr"> 67 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L67'>write</a> out:&:<a href='075channel.mu.html#L47'>sink</a>:_elem, val:_elem<span class="muRecipe"> -> </span>out:&:<a href='075channel.mu.html#L47'>sink</a>:_elem [ -<span id="L68" class="LineNr"> 68 </span> <span class="Constant">local-scope</span> -<span id="L69" class="LineNr"> 69 </span> <span class="Constant">load-inputs</span> -<span id="L70" class="LineNr"> 70 </span> assert out, <span class="Constant">[write to null channel]</span> -<span id="L71" class="LineNr"> 71 </span> chan:&:channel:_elem <span class="Special"><-</span> get *out, <span class="Constant">chan:offset</span> -<span id="L72" class="LineNr"> 72 </span><span class="Constant"> <a href='075channel.mu.html#L72'><channel-write-initial></a></span> -<span id="L73" class="LineNr"> 73 </span> <span class="Comment"># block until lock is acquired AND queue has room</span> -<span id="L74" class="LineNr"> 74 </span> lock:location <span class="Special"><-</span> get-location *chan, <span class="Constant">lock:offset</span> -<span id="L75" class="LineNr"> 75 </span><span class="CommentedCode">#? $print [write], 10/newline</span> -<span id="L76" class="LineNr"> 76 </span> <span class="Delimiter">{</span> -<span id="L77" class="LineNr"> 77 </span><span class="CommentedCode">#? $print [trying to acquire lock for writing], 10/newline</span> -<span id="L78" class="LineNr"> 78 </span> wait-for-reset-then-set lock -<span id="L79" class="LineNr"> 79 </span><span class="CommentedCode">#? $print [lock acquired for writing], 10/newline</span> -<span id="L80" class="LineNr"> 80 </span> full?:bool <span class="Special"><-</span> <a href='075channel.mu.html#L381'>channel-full?</a> chan -<span id="L81" class="LineNr"> 81 </span> <span class="muControl">break-unless</span> full? -<span id="L82" class="LineNr"> 82 </span><span class="CommentedCode">#? $print [but channel is full; relinquishing lock], 10/newline</span> -<span id="L83" class="LineNr"> 83 </span> <span class="Comment"># channel is full; relinquish lock and give a reader the opportunity to</span> -<span id="L84" class="LineNr"> 84 </span> <span class="Comment"># create room on it</span> -<span id="L85" class="LineNr"> 85 </span> reset lock -<span id="L86" class="LineNr"> 86 </span> current-routine-is-blocked -<span id="L87" class="LineNr"> 87 </span> switch <span class="Comment"># avoid spinlocking</span> -<span id="L88" class="LineNr"> 88 </span> <span class="muControl"> loop</span> -<span id="L89" class="LineNr"> 89 </span> <span class="Delimiter">}</span> -<span id="L90" class="LineNr"> 90 </span> current-routine-is-unblocked -<span id="L91" class="LineNr"> 91 </span><span class="CommentedCode">#? $print [performing write], 10/newline</span> -<span id="L92" class="LineNr"> 92 </span> <span class="Comment"># store a deep copy of val</span> -<span id="L93" class="LineNr"> 93 </span> circular-buffer:&:@:_elem <span class="Special"><-</span> get *chan, <span class="Constant">data:offset</span> -<span id="L94" class="LineNr"> 94 </span> free:num <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> -<span id="L95" class="LineNr"> 95 </span> val-copy:_elem <span class="Special"><-</span> deep-copy val <span class="Comment"># on this instruction rests all Mu's concurrency-safety</span> -<span id="L96" class="LineNr"> 96 </span> *circular-buffer <span class="Special"><-</span> put-index *circular-buffer, free, val-copy -<span id="L97" class="LineNr"> 97 </span> <span class="Comment"># mark its slot as filled</span> -<span id="L98" class="LineNr"> 98 </span> free <span class="Special"><-</span> add free,<span class="Constant"> 1</span> -<span id="L99" class="LineNr"> 99 </span> <span class="Delimiter">{</span> -<span id="L100" class="LineNr">100 </span> <span class="Comment"># wrap free around to 0 if necessary</span> -<span id="L101" class="LineNr">101 </span> len:num <span class="Special"><-</span> length *circular-buffer -<span id="L102" class="LineNr">102 </span> at-end?:bool <span class="Special"><-</span> greater-or-equal free, len -<span id="L103" class="LineNr">103 </span> <span class="muControl">break-unless</span> at-end? -<span id="L104" class="LineNr">104 </span> free <span class="Special"><-</span> copy<span class="Constant"> 0</span> -<span id="L105" class="LineNr">105 </span> <span class="Delimiter">}</span> -<span id="L106" class="LineNr">106 </span> <span class="Comment"># write back</span> -<span id="L107" class="LineNr">107 </span> *chan <span class="Special"><-</span> put *chan, <span class="Constant">first-free:offset</span>, free -<span id="L108" class="LineNr">108 </span><span class="CommentedCode">#? $print [relinquishing lock after writing], 10/newline</span> -<span id="L109" class="LineNr">109 </span> reset lock -<span id="L110" class="LineNr">110 </span>] -<span id="L111" class="LineNr">111 </span> -<span id="L112" class="LineNr">112 </span><span class="Comment"># read a value from a channel</span> -<span id="L113" class="LineNr">113 </span><span class="muRecipe">def</span> read in:&:<a href='075channel.mu.html#L43'>source</a>:_elem<span class="muRecipe"> -> </span>result:_elem, eof?:bool, in:&:<a href='075channel.mu.html#L43'>source</a>:_elem [ -<span id="L114" class="LineNr">114 </span> <span class="Constant">local-scope</span> -<span id="L115" class="LineNr">115 </span> <span class="Constant">load-inputs</span> -<span id="L116" class="LineNr">116 </span> assert in, <span class="Constant">[read on null channel]</span> -<span id="L117" class="LineNr">117 </span> eof? <span class="Special"><-</span> copy <span class="Constant">0/false</span> <span class="Comment"># default result</span> -<span id="L118" class="LineNr">118 </span> chan:&:channel:_elem <span class="Special"><-</span> get *in, <span class="Constant">chan:offset</span> -<span id="L119" class="LineNr">119 </span> <span class="Comment"># block until lock is acquired AND queue has data</span> -<span id="L120" class="LineNr">120 </span> lock:location <span class="Special"><-</span> get-location *chan, <span class="Constant">lock:offset</span> -<span id="L121" class="LineNr">121 </span><span class="CommentedCode">#? $print [read], 10/newline</span> -<span id="L122" class="LineNr">122 </span> <span class="Delimiter">{</span> -<span id="L123" class="LineNr">123 </span><span class="CommentedCode">#? $print [trying to acquire lock for reading], 10/newline</span> -<span id="L124" class="LineNr">124 </span> wait-for-reset-then-set lock -<span id="L125" class="LineNr">125 </span><span class="CommentedCode">#? $print [lock acquired for reading], 10/newline</span> -<span id="L126" class="LineNr">126 </span> empty?:bool <span class="Special"><-</span> <a href='075channel.mu.html#L370'>channel-empty?</a> chan -<span id="L127" class="LineNr">127 </span> <span class="muControl">break-unless</span> empty? -<span id="L128" class="LineNr">128 </span><span class="CommentedCode">#? $print [but channel is empty; relinquishing lock], 10/newline</span> -<span id="L129" class="LineNr">129 </span> <span class="Comment"># channel is empty; relinquish lock and give a writer the opportunity to</span> -<span id="L130" class="LineNr">130 </span> <span class="Comment"># add to it</span> -<span id="L131" class="LineNr">131 </span> reset lock -<span id="L132" class="LineNr">132 </span> current-routine-is-blocked -<span id="L133" class="LineNr">133 </span><span class="Constant"> <a href='075channel.mu.html#L133'><channel-read-empty></a></span> -<span id="L134" class="LineNr">134 </span> switch <span class="Comment"># avoid spinlocking</span> -<span id="L135" class="LineNr">135 </span> <span class="muControl"> loop</span> -<span id="L136" class="LineNr">136 </span> <span class="Delimiter">}</span> -<span id="L137" class="LineNr">137 </span> current-routine-is-unblocked -<span id="L138" class="LineNr">138 </span> <span class="Comment"># pull result off</span> -<span id="L139" class="LineNr">139 </span> full:num <span class="Special"><-</span> get *chan, <span class="Constant">first-full:offset</span> -<span id="L140" class="LineNr">140 </span> circular-buffer:&:@:_elem <span class="Special"><-</span> get *chan, <span class="Constant">data:offset</span> -<span id="L141" class="LineNr">141 </span> result <span class="Special"><-</span> index *circular-buffer, full -<span id="L142" class="LineNr">142 </span> <span class="Comment"># clear the slot</span> -<span id="L143" class="LineNr">143 </span> empty:&:_elem <span class="Special"><-</span> new <span class="Constant">_elem:type</span> -<span id="L144" class="LineNr">144 </span> *circular-buffer <span class="Special"><-</span> put-index *circular-buffer, full, *empty -<span id="L145" class="LineNr">145 </span> <span class="Comment"># mark its slot as empty</span> -<span id="L146" class="LineNr">146 </span> full <span class="Special"><-</span> add full,<span class="Constant"> 1</span> -<span id="L147" class="LineNr">147 </span> <span class="Delimiter">{</span> -<span id="L148" class="LineNr">148 </span> <span class="Comment"># wrap full around to 0 if necessary</span> -<span id="L149" class="LineNr">149 </span> len:num <span class="Special"><-</span> length *circular-buffer -<span id="L150" class="LineNr">150 </span> at-end?:bool <span class="Special"><-</span> greater-or-equal full, len -<span id="L151" class="LineNr">151 </span> <span class="muControl">break-unless</span> at-end? -<span id="L152" class="LineNr">152 </span> full <span class="Special"><-</span> copy<span class="Constant"> 0</span> -<span id="L153" class="LineNr">153 </span> <span class="Delimiter">}</span> -<span id="L154" class="LineNr">154 </span> <span class="Comment"># write back</span> -<span id="L155" class="LineNr">155 </span> *chan <span class="Special"><-</span> put *chan, <span class="Constant">first-full:offset</span>, full -<span id="L156" class="LineNr">156 </span><span class="CommentedCode">#? $print [relinquishing lock after reading], 10/newline</span> -<span id="L157" class="LineNr">157 </span> reset lock -<span id="L158" class="LineNr">158 </span>] -<span id="L159" class="LineNr">159 </span> -<span id="L160" class="LineNr">160 </span><span class="Comment"># todo: create a notion of iterator and iterable so we can read/write whole</span> -<span id="L161" class="LineNr">161 </span><span class="Comment"># aggregates (arrays, lists, ..) of _elems at once.</span> -<span id="L162" class="LineNr">162 </span> -<span id="L163" class="LineNr">163 </span><span class="muScenario">scenario</span> channel-initialization [ -<span id="L164" class="LineNr">164 </span> run [ -<span id="L165" class="LineNr">165 </span> <span class="Constant">local-scope</span> -<span id="L166" class="LineNr">166 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">3/capacity</span> -<span id="L167" class="LineNr">167 </span> chan:&:channel:num <span class="Special"><-</span> get *source, <span class="Constant">chan:offset</span> -<span id="L168" class="LineNr">168 </span> 10:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-full:offset</span> -<span id="L169" class="LineNr">169 </span> 11:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> -<span id="L170" class="LineNr">170 </span> ] -<span id="L171" class="LineNr">171 </span> memory-should-contain [ -<span id="L172" class="LineNr">172 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># first-full</span> -<span id="L173" class="LineNr">173 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># first-free</span> -<span id="L174" class="LineNr">174 </span> ] -<span id="L175" class="LineNr">175 </span>] -<span id="L176" class="LineNr">176 </span> -<span id="L177" class="LineNr">177 </span><span class="muScenario">scenario</span> channel-write-increments-free [ -<span id="L178" class="LineNr">178 </span> <span class="Constant">local-scope</span> -<span id="L179" class="LineNr">179 </span> _, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">3/capacity</span> -<span id="L180" class="LineNr">180 </span> run [ -<span id="L181" class="LineNr">181 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>,<span class="Constant"> 34</span> -<span id="L182" class="LineNr">182 </span> chan:&:channel:num <span class="Special"><-</span> get *sink, <span class="Constant">chan:offset</span> -<span id="L183" class="LineNr">183 </span> 10:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-full:offset</span> -<span id="L184" class="LineNr">184 </span> 11:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> -<span id="L185" class="LineNr">185 </span> ] -<span id="L186" class="LineNr">186 </span> memory-should-contain [ -<span id="L187" class="LineNr">187 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># first-full</span> -<span id="L188" class="LineNr">188 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># first-free</span> -<span id="L189" class="LineNr">189 </span> ] -<span id="L190" class="LineNr">190 </span>] -<span id="L191" class="LineNr">191 </span> -<span id="L192" class="LineNr">192 </span><span class="muScenario">scenario</span> channel-read-increments-full [ -<span id="L193" class="LineNr">193 </span> <span class="Constant">local-scope</span> -<span id="L194" class="LineNr">194 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:num, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">3/capacity</span> -<span id="L195" class="LineNr">195 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>,<span class="Constant"> 34</span> -<span id="L196" class="LineNr">196 </span> run [ -<span id="L197" class="LineNr">197 </span> _, _, <a href='075channel.mu.html#L43'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L43'>source</a> -<span id="L198" class="LineNr">198 </span> chan:&:channel:num <span class="Special"><-</span> get *source, <span class="Constant">chan:offset</span> -<span id="L199" class="LineNr">199 </span> 10:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-full:offset</span> -<span id="L200" class="LineNr">200 </span> 11:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> -<span id="L201" class="LineNr">201 </span> ] -<span id="L202" class="LineNr">202 </span> memory-should-contain [ -<span id="L203" class="LineNr">203 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># first-full</span> -<span id="L204" class="LineNr">204 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># first-free</span> -<span id="L205" class="LineNr">205 </span> ] -<span id="L206" class="LineNr">206 </span>] -<span id="L207" class="LineNr">207 </span> -<span id="L208" class="LineNr">208 </span><span class="muScenario">scenario</span> channel-wrap [ -<span id="L209" class="LineNr">209 </span> <span class="Constant">local-scope</span> -<span id="L210" class="LineNr">210 </span> <span class="Comment"># channel with just 1 slot</span> -<span id="L211" class="LineNr">211 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:num, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">1/capacity</span> -<span id="L212" class="LineNr">212 </span> chan:&:channel:num <span class="Special"><-</span> get *source, <span class="Constant">chan:offset</span> -<span id="L213" class="LineNr">213 </span> <span class="Comment"># write and read a value</span> -<span id="L214" class="LineNr">214 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>,<span class="Constant"> 34</span> -<span id="L215" class="LineNr">215 </span> _, _, <a href='075channel.mu.html#L43'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L43'>source</a> -<span id="L216" class="LineNr">216 </span> run [ -<span id="L217" class="LineNr">217 </span> <span class="Comment"># first-free will now be 1</span> -<span id="L218" class="LineNr">218 </span> 10:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> -<span id="L219" class="LineNr">219 </span> 11:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> -<span id="L220" class="LineNr">220 </span> <span class="Comment"># write second value, verify that first-free wraps</span> -<span id="L221" class="LineNr">221 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>,<span class="Constant"> 34</span> -<span id="L222" class="LineNr">222 </span> 20:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> -<span id="L223" class="LineNr">223 </span> <span class="Comment"># read second value, verify that first-full wraps</span> -<span id="L224" class="LineNr">224 </span> _, _, <a href='075channel.mu.html#L43'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L43'>source</a> -<span id="L225" class="LineNr">225 </span> 30:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-full:offset</span> -<span id="L226" class="LineNr">226 </span> ] -<span id="L227" class="LineNr">227 </span> memory-should-contain [ -<span id="L228" class="LineNr">228 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># first-free after first write</span> -<span id="L229" class="LineNr">229 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># first-full after first read</span> -<span id="L230" class="LineNr">230 </span> <span class="Constant"> 20</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># first-free after second write, wrapped</span> -<span id="L231" class="LineNr">231 </span> <span class="Constant"> 30</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># first-full after second read, wrapped</span> -<span id="L232" class="LineNr">232 </span> ] -<span id="L233" class="LineNr">233 </span>] -<span id="L234" class="LineNr">234 </span> -<span id="L235" class="LineNr">235 </span><span class="muScenario">scenario</span> channel-new-empty-not-full [ -<span id="L236" class="LineNr">236 </span> run [ -<span id="L237" class="LineNr">237 </span> <span class="Constant">local-scope</span> -<span id="L238" class="LineNr">238 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">3/capacity</span> -<span id="L239" class="LineNr">239 </span> chan:&:channel:num <span class="Special"><-</span> get *source, <span class="Constant">chan:offset</span> -<span id="L240" class="LineNr">240 </span> 10:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L370'>channel-empty?</a> chan -<span id="L241" class="LineNr">241 </span> 11:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L381'>channel-full?</a> chan -<span id="L242" class="LineNr">242 </span> ] -<span id="L243" class="LineNr">243 </span> memory-should-contain [ -<span id="L244" class="LineNr">244 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># empty?</span> -<span id="L245" class="LineNr">245 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># full?</span> -<span id="L246" class="LineNr">246 </span> ] -<span id="L247" class="LineNr">247 </span>] -<span id="L248" class="LineNr">248 </span> -<span id="L249" class="LineNr">249 </span><span class="muScenario">scenario</span> channel-write-not-empty [ -<span id="L250" class="LineNr">250 </span> <span class="Constant">local-scope</span> -<span id="L251" class="LineNr">251 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:num, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">3/capacity</span> -<span id="L252" class="LineNr">252 </span> chan:&:channel:num <span class="Special"><-</span> get *source, <span class="Constant">chan:offset</span> -<span id="L253" class="LineNr">253 </span> run [ -<span id="L254" class="LineNr">254 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>,<span class="Constant"> 34</span> -<span id="L255" class="LineNr">255 </span> 10:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L370'>channel-empty?</a> chan -<span id="L256" class="LineNr">256 </span> 11:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L381'>channel-full?</a> chan -<span id="L257" class="LineNr">257 </span> ] -<span id="L258" class="LineNr">258 </span> memory-should-contain [ -<span id="L259" class="LineNr">259 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># empty?</span> -<span id="L260" class="LineNr">260 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># full?</span> -<span id="L261" class="LineNr">261 </span> ] -<span id="L262" class="LineNr">262 </span>] -<span id="L263" class="LineNr">263 </span> -<span id="L264" class="LineNr">264 </span><span class="muScenario">scenario</span> channel-write-full [ -<span id="L265" class="LineNr">265 </span> <span class="Constant">local-scope</span> -<span id="L266" class="LineNr">266 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:num, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">1/capacity</span> -<span id="L267" class="LineNr">267 </span> chan:&:channel:num <span class="Special"><-</span> get *source, <span class="Constant">chan:offset</span> -<span id="L268" class="LineNr">268 </span> run [ -<span id="L269" class="LineNr">269 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>,<span class="Constant"> 34</span> -<span id="L270" class="LineNr">270 </span> 10:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L370'>channel-empty?</a> chan -<span id="L271" class="LineNr">271 </span> 11:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L381'>channel-full?</a> chan -<span id="L272" class="LineNr">272 </span> ] -<span id="L273" class="LineNr">273 </span> memory-should-contain [ -<span id="L274" class="LineNr">274 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># empty?</span> -<span id="L275" class="LineNr">275 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># full?</span> -<span id="L276" class="LineNr">276 </span> ] -<span id="L277" class="LineNr">277 </span>] -<span id="L278" class="LineNr">278 </span> -<span id="L279" class="LineNr">279 </span><span class="muScenario">scenario</span> channel-read-not-full [ -<span id="L280" class="LineNr">280 </span> <span class="Constant">local-scope</span> -<span id="L281" class="LineNr">281 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:num, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">1/capacity</span> -<span id="L282" class="LineNr">282 </span> chan:&:channel:num <span class="Special"><-</span> get *source, <span class="Constant">chan:offset</span> -<span id="L283" class="LineNr">283 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>,<span class="Constant"> 34</span> -<span id="L284" class="LineNr">284 </span> run [ -<span id="L285" class="LineNr">285 </span> _, _, <a href='075channel.mu.html#L43'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L43'>source</a> -<span id="L286" class="LineNr">286 </span> 10:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L370'>channel-empty?</a> chan -<span id="L287" class="LineNr">287 </span> 11:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L381'>channel-full?</a> chan -<span id="L288" class="LineNr">288 </span> ] -<span id="L289" class="LineNr">289 </span> memory-should-contain [ -<span id="L290" class="LineNr">290 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># empty?</span> -<span id="L291" class="LineNr">291 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># full?</span> -<span id="L292" class="LineNr">292 </span> ] -<span id="L293" class="LineNr">293 </span>] -<span id="L294" class="LineNr">294 </span> -<span id="L295" class="LineNr">295 </span><span class="muScenario">scenario</span> channel-clear [ -<span id="L296" class="LineNr">296 </span> <span class="Constant">local-scope</span> -<span id="L297" class="LineNr">297 </span> <span class="Comment"># create a channel with a few items</span> -<span id="L298" class="LineNr">298 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:num, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">3/capacity</span> -<span id="L299" class="LineNr">299 </span> chan:&:channel:num <span class="Special"><-</span> get *sink, <span class="Constant">chan:offset</span> -<span id="L300" class="LineNr">300 </span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>,<span class="Constant"> 30</span> -<span id="L301" class="LineNr">301 </span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>,<span class="Constant"> 31</span> -<span id="L302" class="LineNr">302 </span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>,<span class="Constant"> 32</span> -<span id="L303" class="LineNr">303 </span> run [ -<span id="L304" class="LineNr">304 </span> <a href='075channel.mu.html#L312'>clear</a> <a href='075channel.mu.html#L43'>source</a> -<span id="L305" class="LineNr">305 </span> 10:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L370'>channel-empty?</a> chan -<span id="L306" class="LineNr">306 </span> ] -<span id="L307" class="LineNr">307 </span> memory-should-contain [ -<span id="L308" class="LineNr">308 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># after the call to 'clear', the channel should be empty</span> -<span id="L309" class="LineNr">309 </span> ] -<span id="L310" class="LineNr">310 </span>] -<span id="L311" class="LineNr">311 </span> -<span id="L312" class="LineNr">312 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L312'>clear</a> in:&:<a href='075channel.mu.html#L43'>source</a>:_elem<span class="muRecipe"> -> </span>in:&:<a href='075channel.mu.html#L43'>source</a>:_elem [ -<span id="L313" class="LineNr">313 </span> <span class="Constant">local-scope</span> -<span id="L314" class="LineNr">314 </span> <span class="Constant">load-inputs</span> -<span id="L315" class="LineNr">315 </span> chan:&:channel:_elem <span class="Special"><-</span> get *in, <span class="Constant">chan:offset</span> -<span id="L316" class="LineNr">316 </span> <span class="Delimiter">{</span> -<span id="L317" class="LineNr">317 </span> empty?:bool <span class="Special"><-</span> <a href='075channel.mu.html#L370'>channel-empty?</a> chan -<span id="L318" class="LineNr">318 </span> <span class="muControl">break-if</span> empty? -<span id="L319" class="LineNr">319 </span> _, _, in <span class="Special"><-</span> read in -<span id="L320" class="LineNr">320 </span> <span class="muControl"> loop</span> -<span id="L321" class="LineNr">321 </span> <span class="Delimiter">}</span> +<span id="L40" class="LineNr"> 40 </span><span class="muData">container</span> <a href='075channel.mu.html#L40'>sink</a>:_elem [ +<span id="L41" class="LineNr"> 41 </span> chan:&:channel:_elem +<span id="L42" class="LineNr"> 42 </span>] +<span id="L43" class="LineNr"> 43 </span> +<span id="L44" class="LineNr"> 44 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L44'>new-channel</a> <a href='075channel.mu.html#L391'>capacity</a>:num<span class="muRecipe"> -> </span>in:&:<a href='075channel.mu.html#L36'>source</a>:_elem, out:&:<a href='075channel.mu.html#L40'>sink</a>:_elem [ +<span id="L45" class="LineNr"> 45 </span> <span class="Constant">local-scope</span> +<span id="L46" class="LineNr"> 46 </span> <span class="Constant">load-inputs</span> +<span id="L47" class="LineNr"> 47 </span> result:&:channel:_elem <span class="Special"><-</span> new <span class="Delimiter">{</span>(channel _elem): type<span class="Delimiter">}</span> +<span id="L48" class="LineNr"> 48 </span> *result <span class="Special"><-</span> put *result, <span class="Constant">first-full:offset</span>,<span class="Constant"> 0</span> +<span id="L49" class="LineNr"> 49 </span> *result <span class="Special"><-</span> put *result, <span class="Constant">first-free:offset</span>,<span class="Constant"> 0</span> +<span id="L50" class="LineNr"> 50 </span> <a href='075channel.mu.html#L391'>capacity</a> <span class="Special"><-</span> add <a href='075channel.mu.html#L391'>capacity</a>,<span class="Constant"> 1</span> <span class="Comment"># unused slot for 'full?' below</span> +<span id="L51" class="LineNr"> 51 </span> data:&:@:_elem <span class="Special"><-</span> new <span class="Constant">_elem:type</span>, <a href='075channel.mu.html#L391'>capacity</a> +<span id="L52" class="LineNr"> 52 </span> *result <span class="Special"><-</span> put *result, <span class="Constant">data:offset</span>, data +<span id="L53" class="LineNr"> 53 </span> in <span class="Special"><-</span> new <span class="Delimiter">{</span>(source _elem): type<span class="Delimiter">}</span> +<span id="L54" class="LineNr"> 54 </span> *in <span class="Special"><-</span> put *in, <span class="Constant">chan:offset</span>, result +<span id="L55" class="LineNr"> 55 </span> out <span class="Special"><-</span> new <span class="Delimiter">{</span>(sink _elem): type<span class="Delimiter">}</span> +<span id="L56" class="LineNr"> 56 </span> *out <span class="Special"><-</span> put *out, <span class="Constant">chan:offset</span>, result +<span id="L57" class="LineNr"> 57 </span>] +<span id="L58" class="LineNr"> 58 </span> +<span id="L59" class="LineNr"> 59 </span><span class="Comment"># write a value to a channel</span> +<span id="L60" class="LineNr"> 60 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L60'>write</a> out:&:<a href='075channel.mu.html#L40'>sink</a>:_elem, val:_elem<span class="muRecipe"> -> </span>out:&:<a href='075channel.mu.html#L40'>sink</a>:_elem [ +<span id="L61" class="LineNr"> 61 </span> <span class="Constant">local-scope</span> +<span id="L62" class="LineNr"> 62 </span> <span class="Constant">load-inputs</span> +<span id="L63" class="LineNr"> 63 </span> assert out, <span class="Constant">[write to null channel]</span> +<span id="L64" class="LineNr"> 64 </span> chan:&:channel:_elem <span class="Special"><-</span> get *out, <span class="Constant">chan:offset</span> +<span id="L65" class="LineNr"> 65 </span><span class="Constant"> <a href='075channel.mu.html#L65'><channel-write-initial></a></span> +<span id="L66" class="LineNr"> 66 </span> <span class="Comment"># block until lock is acquired AND queue has room</span> +<span id="L67" class="LineNr"> 67 </span> lock:location <span class="Special"><-</span> get-location *chan, <span class="Constant">lock:offset</span> +<span id="L68" class="LineNr"> 68 </span><span class="CommentedCode">#? $print [write], 10/newline</span> +<span id="L69" class="LineNr"> 69 </span> <span class="Delimiter">{</span> +<span id="L70" class="LineNr"> 70 </span><span class="CommentedCode">#? $print [trying to acquire lock for writing], 10/newline</span> +<span id="L71" class="LineNr"> 71 </span> wait-for-reset-then-set lock +<span id="L72" class="LineNr"> 72 </span><span class="CommentedCode">#? $print [lock acquired for writing], 10/newline</span> +<span id="L73" class="LineNr"> 73 </span> full?:bool <span class="Special"><-</span> <a href='075channel.mu.html#L373'>channel-full?</a> chan +<span id="L74" class="LineNr"> 74 </span> <span class="muControl">break-unless</span> full? +<span id="L75" class="LineNr"> 75 </span><span class="CommentedCode">#? $print [but channel is full; relinquishing lock], 10/newline</span> +<span id="L76" class="LineNr"> 76 </span> <span class="Comment"># channel is full; relinquish lock and give a reader the opportunity to</span> +<span id="L77" class="LineNr"> 77 </span> <span class="Comment"># create room on it</span> +<span id="L78" class="LineNr"> 78 </span> reset lock +<span id="L79" class="LineNr"> 79 </span> current-routine-is-blocked +<span id="L80" class="LineNr"> 80 </span> switch <span class="Comment"># avoid spinlocking</span> +<span id="L81" class="LineNr"> 81 </span> <span class="muControl"> loop</span> +<span id="L82" class="LineNr"> 82 </span> <span class="Delimiter">}</span> +<span id="L83" class="LineNr"> 83 </span> current-routine-is-unblocked +<span id="L84" class="LineNr"> 84 </span><span class="CommentedCode">#? $print [performing write], 10/newline</span> +<span id="L85" class="LineNr"> 85 </span> <span class="Comment"># store a deep copy of val</span> +<span id="L86" class="LineNr"> 86 </span> circular-buffer:&:@:_elem <span class="Special"><-</span> get *chan, <span class="Constant">data:offset</span> +<span id="L87" class="LineNr"> 87 </span> free:num <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> +<span id="L88" class="LineNr"> 88 </span> *circular-buffer <span class="Special"><-</span> put-index *circular-buffer, free, val +<span id="L89" class="LineNr"> 89 </span> <span class="Comment"># mark its slot as filled</span> +<span id="L90" class="LineNr"> 90 </span> free <span class="Special"><-</span> add free,<span class="Constant"> 1</span> +<span id="L91" class="LineNr"> 91 </span> <span class="Delimiter">{</span> +<span id="L92" class="LineNr"> 92 </span> <span class="Comment"># wrap free around to 0 if necessary</span> +<span id="L93" class="LineNr"> 93 </span> len:num <span class="Special"><-</span> length *circular-buffer +<span id="L94" class="LineNr"> 94 </span> at-end?:bool <span class="Special"><-</span> greater-or-equal free, len +<span id="L95" class="LineNr"> 95 </span> <span class="muControl">break-unless</span> at-end? +<span id="L96" class="LineNr"> 96 </span> free <span class="Special"><-</span> copy<span class="Constant"> 0</span> +<span id="L97" class="LineNr"> 97 </span> <span class="Delimiter">}</span> +<span id="L98" class="LineNr"> 98 </span> <span class="Comment"># write back</span> +<span id="L99" class="LineNr"> 99 </span> *chan <span class="Special"><-</span> put *chan, <span class="Constant">first-free:offset</span>, free +<span id="L100" class="LineNr">100 </span><span class="CommentedCode">#? $print [relinquishing lock after writing], 10/newline</span> +<span id="L101" class="LineNr">101 </span> reset lock +<span id="L102" class="LineNr">102 </span>] +<span id="L103" class="LineNr">103 </span> +<span id="L104" class="LineNr">104 </span><span class="Comment"># read a value from a channel</span> +<span id="L105" class="LineNr">105 </span><span class="muRecipe">def</span> read in:&:<a href='075channel.mu.html#L36'>source</a>:_elem<span class="muRecipe"> -> </span>result:_elem, eof?:bool, in:&:<a href='075channel.mu.html#L36'>source</a>:_elem [ +<span id="L106" class="LineNr">106 </span> <span class="Constant">local-scope</span> +<span id="L107" class="LineNr">107 </span> <span class="Constant">load-inputs</span> +<span id="L108" class="LineNr">108 </span> assert in, <span class="Constant">[read on null channel]</span> +<span id="L109" class="LineNr">109 </span> eof? <span class="Special"><-</span> copy <span class="Constant">0/false</span> <span class="Comment"># default result</span> +<span id="L110" class="LineNr">110 </span> chan:&:channel:_elem <span class="Special"><-</span> get *in, <span class="Constant">chan:offset</span> +<span id="L111" class="LineNr">111 </span> <span class="Comment"># block until lock is acquired AND queue has data</span> +<span id="L112" class="LineNr">112 </span> lock:location <span class="Special"><-</span> get-location *chan, <span class="Constant">lock:offset</span> +<span id="L113" class="LineNr">113 </span><span class="CommentedCode">#? $print [read], 10/newline</span> +<span id="L114" class="LineNr">114 </span> <span class="Delimiter">{</span> +<span id="L115" class="LineNr">115 </span><span class="CommentedCode">#? $print [trying to acquire lock for reading], 10/newline</span> +<span id="L116" class="LineNr">116 </span> wait-for-reset-then-set lock +<span id="L117" class="LineNr">117 </span><span class="CommentedCode">#? $print [lock acquired for reading], 10/newline</span> +<span id="L118" class="LineNr">118 </span> empty?:bool <span class="Special"><-</span> <a href='075channel.mu.html#L362'>channel-empty?</a> chan +<span id="L119" class="LineNr">119 </span> <span class="muControl">break-unless</span> empty? +<span id="L120" class="LineNr">120 </span><span class="CommentedCode">#? $print [but channel is empty; relinquishing lock], 10/newline</span> +<span id="L121" class="LineNr">121 </span> <span class="Comment"># channel is empty; relinquish lock and give a writer the opportunity to</span> +<span id="L122" class="LineNr">122 </span> <span class="Comment"># add to it</span> +<span id="L123" class="LineNr">123 </span> reset lock +<span id="L124" class="LineNr">124 </span> current-routine-is-blocked +<span id="L125" class="LineNr">125 </span><span class="Constant"> <a href='075channel.mu.html#L125'><channel-read-empty></a></span> +<span id="L126" class="LineNr">126 </span> switch <span class="Comment"># avoid spinlocking</span> +<span id="L127" class="LineNr">127 </span> <span class="muControl"> loop</span> +<span id="L128" class="LineNr">128 </span> <span class="Delimiter">}</span> +<span id="L129" class="LineNr">129 </span> current-routine-is-unblocked +<span id="L130" class="LineNr">130 </span> <span class="Comment"># pull result off</span> +<span id="L131" class="LineNr">131 </span> full:num <span class="Special"><-</span> get *chan, <span class="Constant">first-full:offset</span> +<span id="L132" class="LineNr">132 </span> circular-buffer:&:@:_elem <span class="Special"><-</span> get *chan, <span class="Constant">data:offset</span> +<span id="L133" class="LineNr">133 </span> result <span class="Special"><-</span> index *circular-buffer, full +<span id="L134" class="LineNr">134 </span> <span class="Comment"># clear the slot</span> +<span id="L135" class="LineNr">135 </span> empty:&:_elem <span class="Special"><-</span> new <span class="Constant">_elem:type</span> +<span id="L136" class="LineNr">136 </span> *circular-buffer <span class="Special"><-</span> put-index *circular-buffer, full, *empty +<span id="L137" class="LineNr">137 </span> <span class="Comment"># mark its slot as empty</span> +<span id="L138" class="LineNr">138 </span> full <span class="Special"><-</span> add full,<span class="Constant"> 1</span> +<span id="L139" class="LineNr">139 </span> <span class="Delimiter">{</span> +<span id="L140" class="LineNr">140 </span> <span class="Comment"># wrap full around to 0 if necessary</span> +<span id="L141" class="LineNr">141 </span> len:num <span class="Special"><-</span> length *circular-buffer +<span id="L142" class="LineNr">142 </span> at-end?:bool <span class="Special"><-</span> greater-or-equal full, len +<span id="L143" class="LineNr">143 </span> <span class="muControl">break-unless</span> at-end? +<span id="L144" class="LineNr">144 </span> full <span class="Special"><-</span> copy<span class="Constant"> 0</span> +<span id="L145" class="LineNr">145 </span> <span class="Delimiter">}</span> +<span id="L146" class="LineNr">146 </span> <span class="Comment"># write back</span> +<span id="L147" class="LineNr">147 </span> *chan <span class="Special"><-</span> put *chan, <span class="Constant">first-full:offset</span>, full +<span id="L148" class="LineNr">148 </span><span class="CommentedCode">#? $print [relinquishing lock after reading], 10/newline</span> +<span id="L149" class="LineNr">149 </span> reset lock +<span id="L150" class="LineNr">150 </span>] +<span id="L151" class="LineNr">151 </span> +<span id="L152" class="LineNr">152 </span><span class="Comment"># todo: create a notion of iterator and iterable so we can read/write whole</span> +<span id="L153" class="LineNr">153 </span><span class="Comment"># aggregates (arrays, lists, ..) of _elems at once.</span> +<span id="L154" class="LineNr">154 </span> +<span id="L155" class="LineNr">155 </span><span class="muScenario">scenario</span> channel-initialization [ +<span id="L156" class="LineNr">156 </span> run [ +<span id="L157" class="LineNr">157 </span> <span class="Constant">local-scope</span> +<span id="L158" class="LineNr">158 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">3/capacity</span> +<span id="L159" class="LineNr">159 </span> chan:&:channel:num <span class="Special"><-</span> get *source, <span class="Constant">chan:offset</span> +<span id="L160" class="LineNr">160 </span> 10:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-full:offset</span> +<span id="L161" class="LineNr">161 </span> 11:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> +<span id="L162" class="LineNr">162 </span> ] +<span id="L163" class="LineNr">163 </span> memory-should-contain [ +<span id="L164" class="LineNr">164 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># first-full</span> +<span id="L165" class="LineNr">165 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># first-free</span> +<span id="L166" class="LineNr">166 </span> ] +<span id="L167" class="LineNr">167 </span>] +<span id="L168" class="LineNr">168 </span> +<span id="L169" class="LineNr">169 </span><span class="muScenario">scenario</span> channel-write-increments-free [ +<span id="L170" class="LineNr">170 </span> <span class="Constant">local-scope</span> +<span id="L171" class="LineNr">171 </span> _, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">3/capacity</span> +<span id="L172" class="LineNr">172 </span> run [ +<span id="L173" class="LineNr">173 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>,<span class="Constant"> 34</span> +<span id="L174" class="LineNr">174 </span> chan:&:channel:num <span class="Special"><-</span> get *sink, <span class="Constant">chan:offset</span> +<span id="L175" class="LineNr">175 </span> 10:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-full:offset</span> +<span id="L176" class="LineNr">176 </span> 11:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> +<span id="L177" class="LineNr">177 </span> ] +<span id="L178" class="LineNr">178 </span> memory-should-contain [ +<span id="L179" class="LineNr">179 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># first-full</span> +<span id="L180" class="LineNr">180 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># first-free</span> +<span id="L181" class="LineNr">181 </span> ] +<span id="L182" class="LineNr">182 </span>] +<span id="L183" class="LineNr">183 </span> +<span id="L184" class="LineNr">184 </span><span class="muScenario">scenario</span> channel-read-increments-full [ +<span id="L185" class="LineNr">185 </span> <span class="Constant">local-scope</span> +<span id="L186" class="LineNr">186 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:num, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">3/capacity</span> +<span id="L187" class="LineNr">187 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>,<span class="Constant"> 34</span> +<span id="L188" class="LineNr">188 </span> run [ +<span id="L189" class="LineNr">189 </span> _, _, <a href='075channel.mu.html#L36'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L36'>source</a> +<span id="L190" class="LineNr">190 </span> chan:&:channel:num <span class="Special"><-</span> get *source, <span class="Constant">chan:offset</span> +<span id="L191" class="LineNr">191 </span> 10:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-full:offset</span> +<span id="L192" class="LineNr">192 </span> 11:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> +<span id="L193" class="LineNr">193 </span> ] +<span id="L194" class="LineNr">194 </span> memory-should-contain [ +<span id="L195" class="LineNr">195 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># first-full</span> +<span id="L196" class="LineNr">196 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># first-free</span> +<span id="L197" class="LineNr">197 </span> ] +<span id="L198" class="LineNr">198 </span>] +<span id="L199" class="LineNr">199 </span> +<span id="L200" class="LineNr">200 </span><span class="muScenario">scenario</span> channel-wrap [ +<span id="L201" class="LineNr">201 </span> <span class="Constant">local-scope</span> +<span id="L202" class="LineNr">202 </span> <span class="Comment"># channel with just 1 slot</span> +<span id="L203" class="LineNr">203 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:num, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">1/capacity</span> +<span id="L204" class="LineNr">204 </span> chan:&:channel:num <span class="Special"><-</span> get *source, <span class="Constant">chan:offset</span> +<span id="L205" class="LineNr">205 </span> <span class="Comment"># write and read a value</span> +<span id="L206" class="LineNr">206 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>,<span class="Constant"> 34</span> +<span id="L207" class="LineNr">207 </span> _, _, <a href='075channel.mu.html#L36'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L36'>source</a> +<span id="L208" class="LineNr">208 </span> run [ +<span id="L209" class="LineNr">209 </span> <span class="Comment"># first-free will now be 1</span> +<span id="L210" class="LineNr">210 </span> 10:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> +<span id="L211" class="LineNr">211 </span> 11:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> +<span id="L212" class="LineNr">212 </span> <span class="Comment"># write second value, verify that first-free wraps</span> +<span id="L213" class="LineNr">213 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>,<span class="Constant"> 34</span> +<span id="L214" class="LineNr">214 </span> 20:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> +<span id="L215" class="LineNr">215 </span> <span class="Comment"># read second value, verify that first-full wraps</span> +<span id="L216" class="LineNr">216 </span> _, _, <a href='075channel.mu.html#L36'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L36'>source</a> +<span id="L217" class="LineNr">217 </span> 30:num/<span class="Special">raw</span> <span class="Special"><-</span> get *chan, <span class="Constant">first-full:offset</span> +<span id="L218" class="LineNr">218 </span> ] +<span id="L219" class="LineNr">219 </span> memory-should-contain [ +<span id="L220" class="LineNr">220 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># first-free after first write</span> +<span id="L221" class="LineNr">221 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># first-full after first read</span> +<span id="L222" class="LineNr">222 </span> <span class="Constant"> 20</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># first-free after second write, wrapped</span> +<span id="L223" class="LineNr">223 </span> <span class="Constant"> 30</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># first-full after second read, wrapped</span> +<span id="L224" class="LineNr">224 </span> ] +<span id="L225" class="LineNr">225 </span>] +<span id="L226" class="LineNr">226 </span> +<span id="L227" class="LineNr">227 </span><span class="muScenario">scenario</span> channel-new-empty-not-full [ +<span id="L228" class="LineNr">228 </span> run [ +<span id="L229" class="LineNr">229 </span> <span class="Constant">local-scope</span> +<span id="L230" class="LineNr">230 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">3/capacity</span> +<span id="L231" class="LineNr">231 </span> chan:&:channel:num <span class="Special"><-</span> get *source, <span class="Constant">chan:offset</span> +<span id="L232" class="LineNr">232 </span> 10:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L362'>channel-empty?</a> chan +<span id="L233" class="LineNr">233 </span> 11:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L373'>channel-full?</a> chan +<span id="L234" class="LineNr">234 </span> ] +<span id="L235" class="LineNr">235 </span> memory-should-contain [ +<span id="L236" class="LineNr">236 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># empty?</span> +<span id="L237" class="LineNr">237 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># full?</span> +<span id="L238" class="LineNr">238 </span> ] +<span id="L239" class="LineNr">239 </span>] +<span id="L240" class="LineNr">240 </span> +<span id="L241" class="LineNr">241 </span><span class="muScenario">scenario</span> channel-write-not-empty [ +<span id="L242" class="LineNr">242 </span> <span class="Constant">local-scope</span> +<span id="L243" class="LineNr">243 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:num, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">3/capacity</span> +<span id="L244" class="LineNr">244 </span> chan:&:channel:num <span class="Special"><-</span> get *source, <span class="Constant">chan:offset</span> +<span id="L245" class="LineNr">245 </span> run [ +<span id="L246" class="LineNr">246 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>,<span class="Constant"> 34</span> +<span id="L247" class="LineNr">247 </span> 10:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L362'>channel-empty?</a> chan +<span id="L248" class="LineNr">248 </span> 11:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L373'>channel-full?</a> chan +<span id="L249" class="LineNr">249 </span> ] +<span id="L250" class="LineNr">250 </span> memory-should-contain [ +<span id="L251" class="LineNr">251 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># empty?</span> +<span id="L252" class="LineNr">252 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># full?</span> +<span id="L253" class="LineNr">253 </span> ] +<span id="L254" class="LineNr">254 </span>] +<span id="L255" class="LineNr">255 </span> +<span id="L256" class="LineNr">256 </span><span class="muScenario">scenario</span> channel-write-full [ +<span id="L257" class="LineNr">257 </span> <span class="Constant">local-scope</span> +<span id="L258" class="LineNr">258 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:num, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">1/capacity</span> +<span id="L259" class="LineNr">259 </span> chan:&:channel:num <span class="Special"><-</span> get *source, <span class="Constant">chan:offset</span> +<span id="L260" class="LineNr">260 </span> run [ +<span id="L261" class="LineNr">261 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>,<span class="Constant"> 34</span> +<span id="L262" class="LineNr">262 </span> 10:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L362'>channel-empty?</a> chan +<span id="L263" class="LineNr">263 </span> 11:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L373'>channel-full?</a> chan +<span id="L264" class="LineNr">264 </span> ] +<span id="L265" class="LineNr">265 </span> memory-should-contain [ +<span id="L266" class="LineNr">266 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># empty?</span> +<span id="L267" class="LineNr">267 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># full?</span> +<span id="L268" class="LineNr">268 </span> ] +<span id="L269" class="LineNr">269 </span>] +<span id="L270" class="LineNr">270 </span> +<span id="L271" class="LineNr">271 </span><span class="muScenario">scenario</span> channel-read-not-full [ +<span id="L272" class="LineNr">272 </span> <span class="Constant">local-scope</span> +<span id="L273" class="LineNr">273 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:num, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">1/capacity</span> +<span id="L274" class="LineNr">274 </span> chan:&:channel:num <span class="Special"><-</span> get *source, <span class="Constant">chan:offset</span> +<span id="L275" class="LineNr">275 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>,<span class="Constant"> 34</span> +<span id="L276" class="LineNr">276 </span> run [ +<span id="L277" class="LineNr">277 </span> _, _, <a href='075channel.mu.html#L36'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L36'>source</a> +<span id="L278" class="LineNr">278 </span> 10:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L362'>channel-empty?</a> chan +<span id="L279" class="LineNr">279 </span> 11:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L373'>channel-full?</a> chan +<span id="L280" class="LineNr">280 </span> ] +<span id="L281" class="LineNr">281 </span> memory-should-contain [ +<span id="L282" class="LineNr">282 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># empty?</span> +<span id="L283" class="LineNr">283 </span> <span class="Constant"> 11</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># full?</span> +<span id="L284" class="LineNr">284 </span> ] +<span id="L285" class="LineNr">285 </span>] +<span id="L286" class="LineNr">286 </span> +<span id="L287" class="LineNr">287 </span><span class="muScenario">scenario</span> channel-clear [ +<span id="L288" class="LineNr">288 </span> <span class="Constant">local-scope</span> +<span id="L289" class="LineNr">289 </span> <span class="Comment"># create a channel with a few items</span> +<span id="L290" class="LineNr">290 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:num, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:num <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">3/capacity</span> +<span id="L291" class="LineNr">291 </span> chan:&:channel:num <span class="Special"><-</span> get *sink, <span class="Constant">chan:offset</span> +<span id="L292" class="LineNr">292 </span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>,<span class="Constant"> 30</span> +<span id="L293" class="LineNr">293 </span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>,<span class="Constant"> 31</span> +<span id="L294" class="LineNr">294 </span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>,<span class="Constant"> 32</span> +<span id="L295" class="LineNr">295 </span> run [ +<span id="L296" class="LineNr">296 </span> <a href='075channel.mu.html#L304'>clear</a> <a href='075channel.mu.html#L36'>source</a> +<span id="L297" class="LineNr">297 </span> 10:bool/<span class="Special">raw</span> <span class="Special"><-</span> <a href='075channel.mu.html#L362'>channel-empty?</a> chan +<span id="L298" class="LineNr">298 </span> ] +<span id="L299" class="LineNr">299 </span> memory-should-contain [ +<span id="L300" class="LineNr">300 </span> <span class="Constant"> 10</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># after the call to 'clear', the channel should be empty</span> +<span id="L301" class="LineNr">301 </span> ] +<span id="L302" class="LineNr">302 </span>] +<span id="L303" class="LineNr">303 </span> +<span id="L304" class="LineNr">304 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L304'>clear</a> in:&:<a href='075channel.mu.html#L36'>source</a>:_elem<span class="muRecipe"> -> </span>in:&:<a href='075channel.mu.html#L36'>source</a>:_elem [ +<span id="L305" class="LineNr">305 </span> <span class="Constant">local-scope</span> +<span id="L306" class="LineNr">306 </span> <span class="Constant">load-inputs</span> +<span id="L307" class="LineNr">307 </span> chan:&:channel:_elem <span class="Special"><-</span> get *in, <span class="Constant">chan:offset</span> +<span id="L308" class="LineNr">308 </span> <span class="Delimiter">{</span> +<span id="L309" class="LineNr">309 </span> empty?:bool <span class="Special"><-</span> <a href='075channel.mu.html#L362'>channel-empty?</a> chan +<span id="L310" class="LineNr">310 </span> <span class="muControl">break-if</span> empty? +<span id="L311" class="LineNr">311 </span> _, _, in <span class="Special"><-</span> read in +<span id="L312" class="LineNr">312 </span> <span class="muControl"> loop</span> +<span id="L313" class="LineNr">313 </span> <span class="Delimiter">}</span> +<span id="L314" class="LineNr">314 </span>] +<span id="L315" class="LineNr">315 </span> +<span id="L316" class="LineNr">316 </span><span class="SalientComment">## cancelling channels</span> +<span id="L317" class="LineNr">317 </span> +<span id="L318" class="LineNr">318 </span><span class="Comment"># every channel comes with a boolean signifying if it's been closed</span> +<span id="L319" class="LineNr">319 </span><span class="Comment"># initially this boolean is false</span> +<span id="L320" class="LineNr">320 </span><span class="muData">container</span> channel:_elem [ +<span id="L321" class="LineNr">321 </span> closed?:bool <span id="L322" class="LineNr">322 </span>] <span id="L323" class="LineNr">323 </span> -<span id="L324" class="LineNr">324 </span><span class="SalientComment">## cancelling channels</span> -<span id="L325" class="LineNr">325 </span> -<span id="L326" class="LineNr">326 </span><span class="Comment"># every channel comes with a boolean signifying if it's been closed</span> -<span id="L327" class="LineNr">327 </span><span class="Comment"># initially this boolean is false</span> -<span id="L328" class="LineNr">328 </span><span class="muData">container</span> channel:_elem [ -<span id="L329" class="LineNr">329 </span> closed?:bool -<span id="L330" class="LineNr">330 </span>] -<span id="L331" class="LineNr">331 </span> -<span id="L332" class="LineNr">332 </span><span class="Comment"># a channel can be closed from either the source or the sink</span> -<span id="L333" class="LineNr">333 </span><span class="Comment"># both routines can modify the 'closed?' bit, but they can only ever set it, so this is a benign race</span> -<span id="L334" class="LineNr">334 </span><span class="muRecipe">def</span> close x:&:<a href='075channel.mu.html#L43'>source</a>:_elem<span class="muRecipe"> -> </span>x:&:<a href='075channel.mu.html#L43'>source</a>:_elem [ -<span id="L335" class="LineNr">335 </span> <span class="Constant">local-scope</span> -<span id="L336" class="LineNr">336 </span> <span class="Constant">load-inputs</span> -<span id="L337" class="LineNr">337 </span> chan:&:channel:_elem <span class="Special"><-</span> get *x, <span class="Constant">chan:offset</span> -<span id="L338" class="LineNr">338 </span> *chan <span class="Special"><-</span> put *chan, <span class="Constant">closed?:offset</span>, <span class="Constant">1/true</span> -<span id="L339" class="LineNr">339 </span>] -<span id="L340" class="LineNr">340 </span><span class="muRecipe">def</span> close x:&:<a href='075channel.mu.html#L47'>sink</a>:_elem<span class="muRecipe"> -> </span>x:&:<a href='075channel.mu.html#L47'>sink</a>:_elem [ -<span id="L341" class="LineNr">341 </span> <span class="Constant">local-scope</span> -<span id="L342" class="LineNr">342 </span> <span class="Constant">load-inputs</span> -<span id="L343" class="LineNr">343 </span> chan:&:channel:_elem <span class="Special"><-</span> get *x, <span class="Constant">chan:offset</span> -<span id="L344" class="LineNr">344 </span> *chan <span class="Special"><-</span> put *chan, <span class="Constant">closed?:offset</span>, <span class="Constant">1/true</span> -<span id="L345" class="LineNr">345 </span>] -<span id="L346" class="LineNr">346 </span> -<span id="L347" class="LineNr">347 </span><span class="Comment"># once a channel is closed from one side, no further operations are expected from that side</span> -<span id="L348" class="LineNr">348 </span><span class="Comment"># if a channel is closed for reading,</span> -<span id="L349" class="LineNr">349 </span><span class="Comment"># no further writes will be let through</span> -<span id="L350" class="LineNr">350 </span><span class="Comment"># if a channel is closed for writing,</span> -<span id="L351" class="LineNr">351 </span><span class="Comment"># future reads continue until the channel empties,</span> -<span id="L352" class="LineNr">352 </span><span class="Comment"># then the channel is also closed for reading</span> -<span id="L353" class="LineNr">353 </span><span class="muRecipe">after</span> <span class="Constant"><a href='075channel.mu.html#L72'><channel-write-initial></a></span> [ -<span id="L354" class="LineNr">354 </span> closed?:bool <span class="Special"><-</span> get *chan, <span class="Constant">closed?:offset</span> -<span id="L355" class="LineNr">355 </span> <span class="muControl">return-if</span> closed? -<span id="L356" class="LineNr">356 </span>] -<span id="L357" class="LineNr">357 </span><span class="muRecipe">after</span> <span class="Constant"><a href='075channel.mu.html#L133'><channel-read-empty></a></span> [ -<span id="L358" class="LineNr">358 </span> closed?:bool <span class="Special"><-</span> get *chan, <span class="Constant">closed?:offset</span> -<span id="L359" class="LineNr">359 </span> <span class="Delimiter">{</span> -<span id="L360" class="LineNr">360 </span> <span class="muControl">break-unless</span> closed? -<span id="L361" class="LineNr">361 </span> empty-result:&:_elem <span class="Special"><-</span> new <span class="Constant">_elem:type</span> -<span id="L362" class="LineNr">362 </span> current-routine-is-unblocked -<span id="L363" class="LineNr">363 </span> <span class="muControl"> return</span> *empty-result, <span class="Constant">1/true</span> -<span id="L364" class="LineNr">364 </span> <span class="Delimiter">}</span> -<span id="L365" class="LineNr">365 </span>] -<span id="L366" class="LineNr">366 </span> -<span id="L367" class="LineNr">367 </span><span class="SalientComment">## helpers</span> -<span id="L368" class="LineNr">368 </span> -<span id="L369" class="LineNr">369 </span><span class="Comment"># An empty channel has first-free and first-full both at the same value.</span> -<span id="L370" class="LineNr">370 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L370'>channel-empty?</a> chan:&:channel:_elem<span class="muRecipe"> -> </span>result:bool [ -<span id="L371" class="LineNr">371 </span> <span class="Constant">local-scope</span> -<span id="L372" class="LineNr">372 </span> <span class="Constant">load-inputs</span> -<span id="L373" class="LineNr">373 </span> <span class="Comment"># return chan.first-full == chan.first-free</span> -<span id="L374" class="LineNr">374 </span> full:num <span class="Special"><-</span> get *chan, <span class="Constant">first-full:offset</span> -<span id="L375" class="LineNr">375 </span> free:num <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> -<span id="L376" class="LineNr">376 </span> result <span class="Special"><-</span> equal full, free -<span id="L377" class="LineNr">377 </span>] -<span id="L378" class="LineNr">378 </span> -<span id="L379" class="LineNr">379 </span><span class="Comment"># A full channel has first-free just before first-full, wasting one slot.</span> -<span id="L380" class="LineNr">380 </span><span class="Comment"># (Other alternatives: <a href="https://www.snellman.net/blog/archive/2016-12-13-ring-buffers">https://www.snellman.net/blog/archive/2016-12-13-ring-buffers</a>)</span> -<span id="L381" class="LineNr">381 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L381'>channel-full?</a> chan:&:channel:_elem<span class="muRecipe"> -> </span>result:bool [ -<span id="L382" class="LineNr">382 </span> <span class="Constant">local-scope</span> -<span id="L383" class="LineNr">383 </span> <span class="Constant">load-inputs</span> -<span id="L384" class="LineNr">384 </span> <span class="Comment"># tmp = chan.first-free + 1</span> -<span id="L385" class="LineNr">385 </span> tmp:num <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> -<span id="L386" class="LineNr">386 </span> tmp <span class="Special"><-</span> add tmp,<span class="Constant"> 1</span> -<span id="L387" class="LineNr">387 </span> <span class="Delimiter">{</span> -<span id="L388" class="LineNr">388 </span> <span class="Comment"># if tmp == chan.capacity, tmp = 0</span> -<span id="L389" class="LineNr">389 </span> len:num <span class="Special"><-</span> <a href='075channel.mu.html#L399'>capacity</a> chan -<span id="L390" class="LineNr">390 </span> at-end?:bool <span class="Special"><-</span> greater-or-equal tmp, len -<span id="L391" class="LineNr">391 </span> <span class="muControl">break-unless</span> at-end? -<span id="L392" class="LineNr">392 </span> tmp <span class="Special"><-</span> copy<span class="Constant"> 0</span> -<span id="L393" class="LineNr">393 </span> <span class="Delimiter">}</span> -<span id="L394" class="LineNr">394 </span> <span class="Comment"># return chan.first-full == tmp</span> -<span id="L395" class="LineNr">395 </span> full:num <span class="Special"><-</span> get *chan, <span class="Constant">first-full:offset</span> -<span id="L396" class="LineNr">396 </span> result <span class="Special"><-</span> equal full, tmp -<span id="L397" class="LineNr">397 </span>] -<span id="L398" class="LineNr">398 </span> -<span id="L399" class="LineNr">399 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L399'>capacity</a> chan:&:channel:_elem<span class="muRecipe"> -> </span>result:num [ -<span id="L400" class="LineNr">400 </span> <span class="Constant">local-scope</span> -<span id="L401" class="LineNr">401 </span> <span class="Constant">load-inputs</span> -<span id="L402" class="LineNr">402 </span> q:&:@:_elem <span class="Special"><-</span> get *chan, <span class="Constant">data:offset</span> -<span id="L403" class="LineNr">403 </span> result <span class="Special"><-</span> length *q -<span id="L404" class="LineNr">404 </span>] -<span id="L405" class="LineNr">405 </span> -<span id="L406" class="LineNr">406 </span><span class="SalientComment">## helpers for channels of characters in particular</span> -<span id="L407" class="LineNr">407 </span> -<span id="L408" class="LineNr">408 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L408'>buffer-lines</a> in:&:<a href='075channel.mu.html#L43'>source</a>:char, buffered-out:&:<a href='075channel.mu.html#L47'>sink</a>:char<span class="muRecipe"> -> </span>buffered-out:&:<a href='075channel.mu.html#L47'>sink</a>:char, in:&:<a href='075channel.mu.html#L43'>source</a>:char [ -<span id="L409" class="LineNr">409 </span> <span class="Constant">local-scope</span> -<span id="L410" class="LineNr">410 </span> <span class="Constant">load-inputs</span> -<span id="L411" class="LineNr">411 </span> <span class="Comment"># repeat forever</span> -<span id="L412" class="LineNr">412 </span> eof?:bool <span class="Special"><-</span> copy <span class="Constant">0/false</span> -<span id="L413" class="LineNr">413 </span> <span class="Delimiter">{</span> -<span id="L414" class="LineNr">414 </span> line:&:<a href='061text.mu.html#L120'>buffer</a>:char <span class="Special"><-</span> <a href='061text.mu.html#L125'>new-buffer</a><span class="Constant"> 30</span> -<span id="L415" class="LineNr">415 </span> <span class="Comment"># read characters from 'in' until newline, copy into line</span> -<span id="L416" class="LineNr">416 </span> <span class="Delimiter">{</span> -<span id="L417" class="LineNr">417 </span><span class="Constant"> +next-character</span> -<span id="L418" class="LineNr">418 </span> c:char, eof?:bool, in <span class="Special"><-</span> read in -<span id="L419" class="LineNr">419 </span> <span class="muControl">break-if</span> eof? -<span id="L420" class="LineNr">420 </span> <span class="Comment"># drop a character on backspace</span> -<span id="L421" class="LineNr">421 </span> <span class="Delimiter">{</span> -<span id="L422" class="LineNr">422 </span> <span class="Comment"># special-case: if it's a backspace</span> -<span id="L423" class="LineNr">423 </span> backspace?:bool <span class="Special"><-</span> equal c,<span class="Constant"> 8</span> -<span id="L424" class="LineNr">424 </span> <span class="muControl">break-unless</span> backspace? -<span id="L425" class="LineNr">425 </span> <span class="Comment"># drop previous character</span> -<span id="L426" class="LineNr">426 </span> <span class="Delimiter">{</span> -<span id="L427" class="LineNr">427 </span> buffer-length:num <span class="Special"><-</span> get *line, <span class="Constant">length:offset</span> -<span id="L428" class="LineNr">428 </span> buffer-empty?:bool <span class="Special"><-</span> equal buffer-length,<span class="Constant"> 0</span> -<span id="L429" class="LineNr">429 </span> <span class="muControl">break-if</span> buffer-empty? -<span id="L430" class="LineNr">430 </span> buffer-length <span class="Special"><-</span> subtract buffer-length,<span class="Constant"> 1</span> -<span id="L431" class="LineNr">431 </span> *line <span class="Special"><-</span> put *line, <span class="Constant">length:offset</span>, buffer-length -<span id="L432" class="LineNr">432 </span> <span class="Delimiter">}</span> -<span id="L433" class="LineNr">433 </span> <span class="Comment"># and don't append this one</span> -<span id="L434" class="LineNr">434 </span> <span class="muControl"> loop</span> <span class="Constant">+next-character</span> -<span id="L435" class="LineNr">435 </span> <span class="Delimiter">}</span> -<span id="L436" class="LineNr">436 </span> <span class="Comment"># append anything else</span> -<span id="L437" class="LineNr">437 </span> line <span class="Special"><-</span> append line, c -<span id="L438" class="LineNr">438 </span> line-done?:bool <span class="Special"><-</span> equal c, <span class="Constant">10/newline</span> -<span id="L439" class="LineNr">439 </span> <span class="muControl">break-if</span> line-done? -<span id="L440" class="LineNr">440 </span> <span class="muControl"> loop</span> -<span id="L441" class="LineNr">441 </span> <span class="Delimiter">}</span> -<span id="L442" class="LineNr">442 </span> <span class="Comment"># copy line into 'buffered-out'</span> -<span id="L443" class="LineNr">443 </span> i:num <span class="Special"><-</span> copy<span class="Constant"> 0</span> -<span id="L444" class="LineNr">444 </span> line-contents:text <span class="Special"><-</span> get *line, <span class="Constant">data:offset</span> -<span id="L445" class="LineNr">445 </span> max:num <span class="Special"><-</span> get *line, <span class="Constant">length:offset</span> +<span id="L324" class="LineNr">324 </span><span class="Comment"># a channel can be closed from either the source or the sink</span> +<span id="L325" class="LineNr">325 </span><span class="Comment"># both routines can modify the 'closed?' bit, but they can only ever set it, so this is a benign race</span> +<span id="L326" class="LineNr">326 </span><span class="muRecipe">def</span> close x:&:<a href='075channel.mu.html#L36'>source</a>:_elem<span class="muRecipe"> -> </span>x:&:<a href='075channel.mu.html#L36'>source</a>:_elem [ +<span id="L327" class="LineNr">327 </span> <span class="Constant">local-scope</span> +<span id="L328" class="LineNr">328 </span> <span class="Constant">load-inputs</span> +<span id="L329" class="LineNr">329 </span> chan:&:channel:_elem <span class="Special"><-</span> get *x, <span class="Constant">chan:offset</span> +<span id="L330" class="LineNr">330 </span> *chan <span class="Special"><-</span> put *chan, <span class="Constant">closed?:offset</span>, <span class="Constant">1/true</span> +<span id="L331" class="LineNr">331 </span>] +<span id="L332" class="LineNr">332 </span><span class="muRecipe">def</span> close x:&:<a href='075channel.mu.html#L40'>sink</a>:_elem<span class="muRecipe"> -> </span>x:&:<a href='075channel.mu.html#L40'>sink</a>:_elem [ +<span id="L333" class="LineNr">333 </span> <span class="Constant">local-scope</span> +<span id="L334" class="LineNr">334 </span> <span class="Constant">load-inputs</span> +<span id="L335" class="LineNr">335 </span> chan:&:channel:_elem <span class="Special"><-</span> get *x, <span class="Constant">chan:offset</span> +<span id="L336" class="LineNr">336 </span> *chan <span class="Special"><-</span> put *chan, <span class="Constant">closed?:offset</span>, <span class="Constant">1/true</span> +<span id="L337" class="LineNr">337 </span>] +<span id="L338" class="LineNr">338 </span> +<span id="L339" class="LineNr">339 </span><span class="Comment"># once a channel is closed from one side, no further operations are expected from that side</span> +<span id="L340" class="LineNr">340 </span><span class="Comment"># if a channel is closed for reading,</span> +<span id="L341" class="LineNr">341 </span><span class="Comment"># no further writes will be let through</span> +<span id="L342" class="LineNr">342 </span><span class="Comment"># if a channel is closed for writing,</span> +<span id="L343" class="LineNr">343 </span><span class="Comment"># future reads continue until the channel empties,</span> +<span id="L344" class="LineNr">344 </span><span class="Comment"># then the channel is also closed for reading</span> +<span id="L345" class="LineNr">345 </span><span class="muRecipe">after</span> <span class="Constant"><a href='075channel.mu.html#L65'><channel-write-initial></a></span> [ +<span id="L346" class="LineNr">346 </span> closed?:bool <span class="Special"><-</span> get *chan, <span class="Constant">closed?:offset</span> +<span id="L347" class="LineNr">347 </span> <span class="muControl">return-if</span> closed? +<span id="L348" class="LineNr">348 </span>] +<span id="L349" class="LineNr">349 </span><span class="muRecipe">after</span> <span class="Constant"><a href='075channel.mu.html#L125'><channel-read-empty></a></span> [ +<span id="L350" class="LineNr">350 </span> closed?:bool <span class="Special"><-</span> get *chan, <span class="Constant">closed?:offset</span> +<span id="L351" class="LineNr">351 </span> <span class="Delimiter">{</span> +<span id="L352" class="LineNr">352 </span> <span class="muControl">break-unless</span> closed? +<span id="L353" class="LineNr">353 </span> empty-result:&:_elem <span class="Special"><-</span> new <span class="Constant">_elem:type</span> +<span id="L354" class="LineNr">354 </span> current-routine-is-unblocked +<span id="L355" class="LineNr">355 </span> <span class="muControl"> return</span> *empty-result, <span class="Constant">1/true</span> +<span id="L356" class="LineNr">356 </span> <span class="Delimiter">}</span> +<span id="L357" class="LineNr">357 </span>] +<span id="L358" class="LineNr">358 </span> +<span id="L359" class="LineNr">359 </span><span class="SalientComment">## helpers</span> +<span id="L360" class="LineNr">360 </span> +<span id="L361" class="LineNr">361 </span><span class="Comment"># An empty channel has first-free and first-full both at the same value.</span> +<span id="L362" class="LineNr">362 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L362'>channel-empty?</a> chan:&:channel:_elem<span class="muRecipe"> -> </span>result:bool [ +<span id="L363" class="LineNr">363 </span> <span class="Constant">local-scope</span> +<span id="L364" class="LineNr">364 </span> <span class="Constant">load-inputs</span> +<span id="L365" class="LineNr">365 </span> <span class="Comment"># return chan.first-full == chan.first-free</span> +<span id="L366" class="LineNr">366 </span> full:num <span class="Special"><-</span> get *chan, <span class="Constant">first-full:offset</span> +<span id="L367" class="LineNr">367 </span> free:num <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> +<span id="L368" class="LineNr">368 </span> result <span class="Special"><-</span> equal full, free +<span id="L369" class="LineNr">369 </span>] +<span id="L370" class="LineNr">370 </span> +<span id="L371" class="LineNr">371 </span><span class="Comment"># A full channel has first-free just before first-full, wasting one slot.</span> +<span id="L372" class="LineNr">372 </span><span class="Comment"># (Other alternatives: <a href="https://www.snellman.net/blog/archive/2016-12-13-ring-buffers">https://www.snellman.net/blog/archive/2016-12-13-ring-buffers</a>)</span> +<span id="L373" class="LineNr">373 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L373'>channel-full?</a> chan:&:channel:_elem<span class="muRecipe"> -> </span>result:bool [ +<span id="L374" class="LineNr">374 </span> <span class="Constant">local-scope</span> +<span id="L375" class="LineNr">375 </span> <span class="Constant">load-inputs</span> +<span id="L376" class="LineNr">376 </span> <span class="Comment"># tmp = chan.first-free + 1</span> +<span id="L377" class="LineNr">377 </span> tmp:num <span class="Special"><-</span> get *chan, <span class="Constant">first-free:offset</span> +<span id="L378" class="LineNr">378 </span> tmp <span class="Special"><-</span> add tmp,<span class="Constant"> 1</span> +<span id="L379" class="LineNr">379 </span> <span class="Delimiter">{</span> +<span id="L380" class="LineNr">380 </span> <span class="Comment"># if tmp == chan.capacity, tmp = 0</span> +<span id="L381" class="LineNr">381 </span> len:num <span class="Special"><-</span> <a href='075channel.mu.html#L391'>capacity</a> chan +<span id="L382" class="LineNr">382 </span> at-end?:bool <span class="Special"><-</span> greater-or-equal tmp, len +<span id="L383" class="LineNr">383 </span> <span class="muControl">break-unless</span> at-end? +<span id="L384" class="LineNr">384 </span> tmp <span class="Special"><-</span> copy<span class="Constant"> 0</span> +<span id="L385" class="LineNr">385 </span> <span class="Delimiter">}</span> +<span id="L386" class="LineNr">386 </span> <span class="Comment"># return chan.first-full == tmp</span> +<span id="L387" class="LineNr">387 </span> full:num <span class="Special"><-</span> get *chan, <span class="Constant">first-full:offset</span> +<span id="L388" class="LineNr">388 </span> result <span class="Special"><-</span> equal full, tmp +<span id="L389" class="LineNr">389 </span>] +<span id="L390" class="LineNr">390 </span> +<span id="L391" class="LineNr">391 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L391'>capacity</a> chan:&:channel:_elem<span class="muRecipe"> -> </span>result:num [ +<span id="L392" class="LineNr">392 </span> <span class="Constant">local-scope</span> +<span id="L393" class="LineNr">393 </span> <span class="Constant">load-inputs</span> +<span id="L394" class="LineNr">394 </span> q:&:@:_elem <span class="Special"><-</span> get *chan, <span class="Constant">data:offset</span> +<span id="L395" class="LineNr">395 </span> result <span class="Special"><-</span> length *q +<span id="L396" class="LineNr">396 </span>] +<span id="L397" class="LineNr">397 </span> +<span id="L398" class="LineNr">398 </span><span class="SalientComment">## helpers for channels of characters in particular</span> +<span id="L399" class="LineNr">399 </span> +<span id="L400" class="LineNr">400 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L400'>buffer-lines</a> in:&:<a href='075channel.mu.html#L36'>source</a>:char, buffered-out:&:<a href='075channel.mu.html#L40'>sink</a>:char<span class="muRecipe"> -> </span>buffered-out:&:<a href='075channel.mu.html#L40'>sink</a>:char, in:&:<a href='075channel.mu.html#L36'>source</a>:char [ +<span id="L401" class="LineNr">401 </span> <span class="Constant">local-scope</span> +<span id="L402" class="LineNr">402 </span> <span class="Constant">load-inputs</span> +<span id="L403" class="LineNr">403 </span> <span class="Comment"># repeat forever</span> +<span id="L404" class="LineNr">404 </span> eof?:bool <span class="Special"><-</span> copy <span class="Constant">0/false</span> +<span id="L405" class="LineNr">405 </span> <span class="Delimiter">{</span> +<span id="L406" class="LineNr">406 </span> line:&:<a href='061text.mu.html#L120'>buffer</a>:char <span class="Special"><-</span> <a href='061text.mu.html#L125'>new-buffer</a><span class="Constant"> 30</span> +<span id="L407" class="LineNr">407 </span> <span class="Comment"># read characters from 'in' until newline, copy into line</span> +<span id="L408" class="LineNr">408 </span> <span class="Delimiter">{</span> +<span id="L409" class="LineNr">409 </span><span class="Constant"> +next-character</span> +<span id="L410" class="LineNr">410 </span> c:char, eof?:bool, in <span class="Special"><-</span> read in +<span id="L411" class="LineNr">411 </span> <span class="muControl">break-if</span> eof? +<span id="L412" class="LineNr">412 </span> <span class="Comment"># drop a character on backspace</span> +<span id="L413" class="LineNr">413 </span> <span class="Delimiter">{</span> +<span id="L414" class="LineNr">414 </span> <span class="Comment"># special-case: if it's a backspace</span> +<span id="L415" class="LineNr">415 </span> backspace?:bool <span class="Special"><-</span> equal c,<span class="Constant"> 8</span> +<span id="L416" class="LineNr">416 </span> <span class="muControl">break-unless</span> backspace? +<span id="L417" class="LineNr">417 </span> <span class="Comment"># drop previous character</span> +<span id="L418" class="LineNr">418 </span> <span class="Delimiter">{</span> +<span id="L419" class="LineNr">419 </span> buffer-length:num <span class="Special"><-</span> get *line, <span class="Constant">length:offset</span> +<span id="L420" class="LineNr">420 </span> buffer-empty?:bool <span class="Special"><-</span> equal buffer-length,<span class="Constant"> 0</span> +<span id="L421" class="LineNr">421 </span> <span class="muControl">break-if</span> buffer-empty? +<span id="L422" class="LineNr">422 </span> buffer-length <span class="Special"><-</span> subtract buffer-length,<span class="Constant"> 1</span> +<span id="L423" class="LineNr">423 </span> *line <span class="Special"><-</span> put *line, <span class="Constant">length:offset</span>, buffer-length +<span id="L424" class="LineNr">424 </span> <span class="Delimiter">}</span> +<span id="L425" class="LineNr">425 </span> <span class="Comment"># and don't append this one</span> +<span id="L426" class="LineNr">426 </span> <span class="muControl"> loop</span> <span class="Constant">+next-character</span> +<span id="L427" class="LineNr">427 </span> <span class="Delimiter">}</span> +<span id="L428" class="LineNr">428 </span> <span class="Comment"># append anything else</span> +<span id="L429" class="LineNr">429 </span> line <span class="Special"><-</span> append line, c +<span id="L430" class="LineNr">430 </span> line-done?:bool <span class="Special"><-</span> equal c, <span class="Constant">10/newline</span> +<span id="L431" class="LineNr">431 </span> <span class="muControl">break-if</span> line-done? +<span id="L432" class="LineNr">432 </span> <span class="muControl"> loop</span> +<span id="L433" class="LineNr">433 </span> <span class="Delimiter">}</span> +<span id="L434" class="LineNr">434 </span> <span class="Comment"># copy line into 'buffered-out'</span> +<span id="L435" class="LineNr">435 </span> i:num <span class="Special"><-</span> copy<span class="Constant"> 0</span> +<span id="L436" class="LineNr">436 </span> line-contents:text <span class="Special"><-</span> get *line, <span class="Constant">data:offset</span> +<span id="L437" class="LineNr">437 </span> max:num <span class="Special"><-</span> get *line, <span class="Constant">length:offset</span> +<span id="L438" class="LineNr">438 </span> <span class="Delimiter">{</span> +<span id="L439" class="LineNr">439 </span> done?:bool <span class="Special"><-</span> greater-or-equal i, max +<span id="L440" class="LineNr">440 </span> <span class="muControl">break-if</span> done? +<span id="L441" class="LineNr">441 </span> c:char <span class="Special"><-</span> index *line-contents, i +<span id="L442" class="LineNr">442 </span> buffered-out <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> buffered-out, c +<span id="L443" class="LineNr">443 </span> i <span class="Special"><-</span> add i,<span class="Constant"> 1</span> +<span id="L444" class="LineNr">444 </span> <span class="muControl"> loop</span> +<span id="L445" class="LineNr">445 </span> <span class="Delimiter">}</span> <span id="L446" class="LineNr">446 </span> <span class="Delimiter">{</span> -<span id="L447" class="LineNr">447 </span> done?:bool <span class="Special"><-</span> greater-or-equal i, max -<span id="L448" class="LineNr">448 </span> <span class="muControl">break-if</span> done? -<span id="L449" class="LineNr">449 </span> c:char <span class="Special"><-</span> index *line-contents, i -<span id="L450" class="LineNr">450 </span> buffered-out <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> buffered-out, c -<span id="L451" class="LineNr">451 </span> i <span class="Special"><-</span> add i,<span class="Constant"> 1</span> -<span id="L452" class="LineNr">452 </span> <span class="muControl"> loop</span> -<span id="L453" class="LineNr">453 </span> <span class="Delimiter">}</span> -<span id="L454" class="LineNr">454 </span> <span class="Delimiter">{</span> -<span id="L455" class="LineNr">455 </span> <span class="muControl">break-unless</span> eof? -<span id="L456" class="LineNr">456 </span> buffered-out <span class="Special"><-</span> close buffered-out -<span id="L457" class="LineNr">457 </span> <span class="muControl"> return</span> -<span id="L458" class="LineNr">458 </span> <span class="Delimiter">}</span> -<span id="L459" class="LineNr">459 </span> <span class="muControl"> loop</span> -<span id="L460" class="LineNr">460 </span> <span class="Delimiter">}</span> -<span id="L461" class="LineNr">461 </span>] -<span id="L462" class="LineNr">462 </span> -<span id="L463" class="LineNr">463 </span><span class="muScenario">scenario</span> buffer-lines-blocks-until-newline [ -<span id="L464" class="LineNr">464 </span> run [ -<span id="L465" class="LineNr">465 </span> <span class="Constant">local-scope</span> -<span id="L466" class="LineNr">466 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">10/capacity</span> -<span id="L467" class="LineNr">467 </span> _, buffered-stdin:&:<a href='075channel.mu.html#L47'>sink</a>:char/buffered-stdin <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">10/capacity</span> -<span id="L468" class="LineNr">468 </span> buffered-chan:&:channel:char <span class="Special"><-</span> get *buffered-stdin, <span class="Constant">chan:offset</span> -<span id="L469" class="LineNr">469 </span> empty?:bool <span class="Special"><-</span> <a href='075channel.mu.html#L370'>channel-empty?</a> buffered-chan -<span id="L470" class="LineNr">470 </span> assert empty?, <span class="Constant">[ </span> -<span id="L471" class="LineNr">471 </span><span class="Constant">F buffer-lines-blocks-until-newline: channel should be empty after init]</span> -<span id="L472" class="LineNr">472 </span> <span class="Comment"># buffer stdin into buffered-stdin, try to read from buffered-stdin</span> -<span id="L473" class="LineNr">473 </span> buffer-routine:num <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='075channel.mu.html#L408'>buffer-lines</a>, <a href='075channel.mu.html#L43'>source</a>, buffered-stdin -<span id="L474" class="LineNr">474 </span> wait-for-routine-to-block buffer-routine -<span id="L475" class="LineNr">475 </span> empty? <span class="Special"><-</span> <a href='075channel.mu.html#L370'>channel-empty?</a> buffered-chan -<span id="L476" class="LineNr">476 </span> assert empty?:bool, <span class="Constant">[ </span> -<span id="L477" class="LineNr">477 </span><span class="Constant">F buffer-lines-blocks-until-newline: channel should be empty after <a href='075channel.mu.html#L408'>buffer-lines</a> bring-up]</span> -<span id="L478" class="LineNr">478 </span> <span class="Comment"># write 'a'</span> -<span id="L479" class="LineNr">479 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">97/a</span> -<span id="L480" class="LineNr">480 </span> restart buffer-routine -<span id="L481" class="LineNr">481 </span> wait-for-routine-to-block buffer-routine -<span id="L482" class="LineNr">482 </span> empty? <span class="Special"><-</span> <a href='075channel.mu.html#L370'>channel-empty?</a> buffered-chan -<span id="L483" class="LineNr">483 </span> assert empty?:bool, <span class="Constant">[ </span> -<span id="L484" class="LineNr">484 </span><span class="Constant">F buffer-lines-blocks-until-newline: channel should be empty after writing 'a']</span> -<span id="L485" class="LineNr">485 </span> <span class="Comment"># write 'b'</span> -<span id="L486" class="LineNr">486 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">98/b</span> -<span id="L487" class="LineNr">487 </span> restart buffer-routine -<span id="L488" class="LineNr">488 </span> wait-for-routine-to-block buffer-routine -<span id="L489" class="LineNr">489 </span> empty? <span class="Special"><-</span> <a href='075channel.mu.html#L370'>channel-empty?</a> buffered-chan -<span id="L490" class="LineNr">490 </span> assert empty?:bool, <span class="Constant">[ </span> -<span id="L491" class="LineNr">491 </span><span class="Constant">F buffer-lines-blocks-until-newline: channel should be empty after writing 'b']</span> -<span id="L492" class="LineNr">492 </span> <span class="Comment"># write newline</span> -<span id="L493" class="LineNr">493 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">10/newline</span> -<span id="L494" class="LineNr">494 </span> restart buffer-routine -<span id="L495" class="LineNr">495 </span> wait-for-routine-to-block buffer-routine -<span id="L496" class="LineNr">496 </span> empty? <span class="Special"><-</span> <a href='075channel.mu.html#L370'>channel-empty?</a> buffered-chan -<span id="L497" class="LineNr">497 </span> data-emitted?:bool <span class="Special"><-</span> not empty? -<span id="L498" class="LineNr">498 </span> assert data-emitted?, <span class="Constant">[ </span> -<span id="L499" class="LineNr">499 </span><span class="Constant">F buffer-lines-blocks-until-newline: channel should contain data after writing newline]</span> -<span id="L500" class="LineNr">500 </span> trace<span class="Constant"> 1</span>, <span class="Constant">[test]</span>, <span class="Constant">[reached end]</span> -<span id="L501" class="LineNr">501 </span> ] -<span id="L502" class="LineNr">502 </span> trace-should-contain [ -<span id="L503" class="LineNr">503 </span> test: reached end -<span id="L504" class="LineNr">504 </span> ] -<span id="L505" class="LineNr">505 </span>] -<span id="L506" class="LineNr">506 </span> -<span id="L507" class="LineNr">507 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L507'>drain</a> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char<span class="muRecipe"> -> </span>result:text, <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char [ -<span id="L508" class="LineNr">508 </span> <span class="Constant">local-scope</span> -<span id="L509" class="LineNr">509 </span> <span class="Constant">load-inputs</span> -<span id="L510" class="LineNr">510 </span> buf:&:<a href='061text.mu.html#L120'>buffer</a>:char <span class="Special"><-</span> <a href='061text.mu.html#L125'>new-buffer</a><span class="Constant"> 30</span> -<span id="L511" class="LineNr">511 </span> <span class="Delimiter">{</span> -<span id="L512" class="LineNr">512 </span> c:char, done?:bool <span class="Special"><-</span> read <a href='075channel.mu.html#L43'>source</a> -<span id="L513" class="LineNr">513 </span> <span class="muControl">break-if</span> done? -<span id="L514" class="LineNr">514 </span> buf <span class="Special"><-</span> append buf, c -<span id="L515" class="LineNr">515 </span> <span class="muControl"> loop</span> -<span id="L516" class="LineNr">516 </span> <span class="Delimiter">}</span> -<span id="L517" class="LineNr">517 </span> result <span class="Special"><-</span> <a href='061text.mu.html#L338'>buffer-to-array</a> buf -<span id="L518" class="LineNr">518 </span>] +<span id="L447" class="LineNr">447 </span> <span class="muControl">break-unless</span> eof? +<span id="L448" class="LineNr">448 </span> buffered-out <span class="Special"><-</span> close buffered-out +<span id="L449" class="LineNr">449 </span> <span class="muControl"> return</span> +<span id="L450" class="LineNr">450 </span> <span class="Delimiter">}</span> +<span id="L451" class="LineNr">451 </span> <span class="muControl"> loop</span> +<span id="L452" class="LineNr">452 </span> <span class="Delimiter">}</span> +<span id="L453" class="LineNr">453 </span>] +<span id="L454" class="LineNr">454 </span> +<span id="L455" class="LineNr">455 </span><span class="muScenario">scenario</span> buffer-lines-blocks-until-newline [ +<span id="L456" class="LineNr">456 </span> run [ +<span id="L457" class="LineNr">457 </span> <span class="Constant">local-scope</span> +<span id="L458" class="LineNr">458 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">10/capacity</span> +<span id="L459" class="LineNr">459 </span> _, buffered-stdin:&:<a href='075channel.mu.html#L40'>sink</a>:char/buffered-stdin <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">10/capacity</span> +<span id="L460" class="LineNr">460 </span> buffered-chan:&:channel:char <span class="Special"><-</span> get *buffered-stdin, <span class="Constant">chan:offset</span> +<span id="L461" class="LineNr">461 </span> empty?:bool <span class="Special"><-</span> <a href='075channel.mu.html#L362'>channel-empty?</a> buffered-chan +<span id="L462" class="LineNr">462 </span> assert empty?, <span class="Constant">[ </span> +<span id="L463" class="LineNr">463 </span><span class="Constant">F buffer-lines-blocks-until-newline: channel should be empty after init]</span> +<span id="L464" class="LineNr">464 </span> <span class="Comment"># buffer stdin into buffered-stdin, try to read from buffered-stdin</span> +<span id="L465" class="LineNr">465 </span> buffer-routine:num <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='075channel.mu.html#L400'>buffer-lines</a>, <a href='075channel.mu.html#L36'>source</a>, buffered-stdin +<span id="L466" class="LineNr">466 </span> wait-for-routine-to-block buffer-routine +<span id="L467" class="LineNr">467 </span> empty? <span class="Special"><-</span> <a href='075channel.mu.html#L362'>channel-empty?</a> buffered-chan +<span id="L468" class="LineNr">468 </span> assert empty?:bool, <span class="Constant">[ </span> +<span id="L469" class="LineNr">469 </span><span class="Constant">F buffer-lines-blocks-until-newline: channel should be empty after <a href='075channel.mu.html#L400'>buffer-lines</a> bring-up]</span> +<span id="L470" class="LineNr">470 </span> <span class="Comment"># write 'a'</span> +<span id="L471" class="LineNr">471 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">97/a</span> +<span id="L472" class="LineNr">472 </span> restart buffer-routine +<span id="L473" class="LineNr">473 </span> wait-for-routine-to-block buffer-routine +<span id="L474" class="LineNr">474 </span> empty? <span class="Special"><-</span> <a href='075channel.mu.html#L362'>channel-empty?</a> buffered-chan +<span id="L475" class="LineNr">475 </span> assert empty?:bool, <span class="Constant">[ </span> +<span id="L476" class="LineNr">476 </span><span class="Constant">F buffer-lines-blocks-until-newline: channel should be empty after writing 'a']</span> +<span id="L477" class="LineNr">477 </span> <span class="Comment"># write 'b'</span> +<span id="L478" class="LineNr">478 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">98/b</span> +<span id="L479" class="LineNr">479 </span> restart buffer-routine +<span id="L480" class="LineNr">480 </span> wait-for-routine-to-block buffer-routine +<span id="L481" class="LineNr">481 </span> empty? <span class="Special"><-</span> <a href='075channel.mu.html#L362'>channel-empty?</a> buffered-chan +<span id="L482" class="LineNr">482 </span> assert empty?:bool, <span class="Constant">[ </span> +<span id="L483" class="LineNr">483 </span><span class="Constant">F buffer-lines-blocks-until-newline: channel should be empty after writing 'b']</span> +<span id="L484" class="LineNr">484 </span> <span class="Comment"># write newline</span> +<span id="L485" class="LineNr">485 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">10/newline</span> +<span id="L486" class="LineNr">486 </span> restart buffer-routine +<span id="L487" class="LineNr">487 </span> wait-for-routine-to-block buffer-routine +<span id="L488" class="LineNr">488 </span> empty? <span class="Special"><-</span> <a href='075channel.mu.html#L362'>channel-empty?</a> buffered-chan +<span id="L489" class="LineNr">489 </span> data-emitted?:bool <span class="Special"><-</span> not empty? +<span id="L490" class="LineNr">490 </span> assert data-emitted?, <span class="Constant">[ </span> +<span id="L491" class="LineNr">491 </span><span class="Constant">F buffer-lines-blocks-until-newline: channel should contain data after writing newline]</span> +<span id="L492" class="LineNr">492 </span> trace<span class="Constant"> 1</span>, <span class="Constant">[test]</span>, <span class="Constant">[reached end]</span> +<span id="L493" class="LineNr">493 </span> ] +<span id="L494" class="LineNr">494 </span> trace-should-contain [ +<span id="L495" class="LineNr">495 </span> test: reached end +<span id="L496" class="LineNr">496 </span> ] +<span id="L497" class="LineNr">497 </span>] +<span id="L498" class="LineNr">498 </span> +<span id="L499" class="LineNr">499 </span><span class="muRecipe">def</span> <a href='075channel.mu.html#L499'>drain</a> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char<span class="muRecipe"> -> </span>result:text, <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char [ +<span id="L500" class="LineNr">500 </span> <span class="Constant">local-scope</span> +<span id="L501" class="LineNr">501 </span> <span class="Constant">load-inputs</span> +<span id="L502" class="LineNr">502 </span> buf:&:<a href='061text.mu.html#L120'>buffer</a>:char <span class="Special"><-</span> <a href='061text.mu.html#L125'>new-buffer</a><span class="Constant"> 30</span> +<span id="L503" class="LineNr">503 </span> <span class="Delimiter">{</span> +<span id="L504" class="LineNr">504 </span> c:char, done?:bool <span class="Special"><-</span> read <a href='075channel.mu.html#L36'>source</a> +<span id="L505" class="LineNr">505 </span> <span class="muControl">break-if</span> done? +<span id="L506" class="LineNr">506 </span> buf <span class="Special"><-</span> append buf, c +<span id="L507" class="LineNr">507 </span> <span class="muControl"> loop</span> +<span id="L508" class="LineNr">508 </span> <span class="Delimiter">}</span> +<span id="L509" class="LineNr">509 </span> result <span class="Special"><-</span> <a href='061text.mu.html#L338'>buffer-to-array</a> buf +<span id="L510" class="LineNr">510 </span>] </pre> </body> </html> diff --git a/html/081print.mu.html b/html/081print.mu.html index e33a35a2..889eab31 100644 --- a/html/081print.mu.html +++ b/html/081print.mu.html @@ -181,7 +181,7 @@ if ('onhashchange' in window) { <span id="L119" class="LineNr">119 </span> <span class="Comment"># (handle special cases exactly like in the real screen)</span> <span id="L120" class="LineNr">120 </span> width:num <span class="Special"><-</span> get *screen, <span class="Constant">num-columns:offset</span> <span id="L121" class="LineNr">121 </span> height:num <span class="Special"><-</span> get *screen, <span class="Constant">num-rows:offset</span> -<span id="L122" class="LineNr">122 </span> <a href='075channel.mu.html#L399'>capacity</a>:num <span class="Special"><-</span> multiply width, height +<span id="L122" class="LineNr">122 </span> <a href='075channel.mu.html#L391'>capacity</a>:num <span class="Special"><-</span> multiply width, height <span id="L123" class="LineNr">123 </span> row:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-row:offset</span> <span id="L124" class="LineNr">124 </span> column:num <span class="Special"><-</span> get *screen, <span class="Constant">cursor-column:offset</span> <span id="L125" class="LineNr">125 </span> buf:&:@:<a href='081print.mu.html#L27'>screen-cell</a> <span class="Special"><-</span> get *screen, <span class="Constant">data:offset</span> @@ -305,8 +305,8 @@ if ('onhashchange' in window) { <span id="L243" class="LineNr">243 </span> <span class="muControl"> loop</span> <span id="L244" class="LineNr">244 </span> <span class="Delimiter">}</span> <span id="L245" class="LineNr">245 </span> <span class="Comment"># top-idx now same as next-top-idx; wrap around if necessary</span> -<span id="L246" class="LineNr">246 </span> <a href='075channel.mu.html#L399'>capacity</a>:num <span class="Special"><-</span> multiply width, height -<span id="L247" class="LineNr">247 </span> _, top-idx <span class="Special"><-</span> divide-with-remainder, top-idx, <a href='075channel.mu.html#L399'>capacity</a> +<span id="L246" class="LineNr">246 </span> <a href='075channel.mu.html#L391'>capacity</a>:num <span class="Special"><-</span> multiply width, height +<span id="L247" class="LineNr">247 </span> _, top-idx <span class="Special"><-</span> divide-with-remainder, top-idx, <a href='075channel.mu.html#L391'>capacity</a> <span id="L248" class="LineNr">248 </span> *screen <span class="Special"><-</span> put *screen, <span class="Constant">top-idx:offset</span>, top-idx <span id="L249" class="LineNr">249 </span>] <span id="L250" class="LineNr">250 </span> @@ -322,8 +322,8 @@ if ('onhashchange' in window) { <span id="L260" class="LineNr">260 </span> <span class="Delimiter">}</span> <span id="L261" class="LineNr">261 </span> result <span class="Special"><-</span> multiply width, row <span id="L262" class="LineNr">262 </span> result <span class="Special"><-</span> add result, column, top-idx -<span id="L263" class="LineNr">263 </span> <a href='075channel.mu.html#L399'>capacity</a>:num <span class="Special"><-</span> multiply width, height -<span id="L264" class="LineNr">264 </span> _, result <span class="Special"><-</span> divide-with-remainder result, <a href='075channel.mu.html#L399'>capacity</a> +<span id="L263" class="LineNr">263 </span> <a href='075channel.mu.html#L391'>capacity</a>:num <span class="Special"><-</span> multiply width, height +<span id="L264" class="LineNr">264 </span> _, result <span class="Special"><-</span> divide-with-remainder result, <a href='075channel.mu.html#L391'>capacity</a> <span id="L265" class="LineNr">265 </span>] <span id="L266" class="LineNr">266 </span> <span id="L267" class="LineNr">267 </span><span class="muScenario">scenario</span> print-character-at-top-left [ diff --git a/html/084console.mu.html b/html/084console.mu.html index 2a1feec8..7928454d 100644 --- a/html/084console.mu.html +++ b/html/084console.mu.html @@ -130,7 +130,7 @@ if ('onhashchange' in window) { <span id="L70" class="LineNr"> 70 </span> <span class="muControl"> return</span> c, <span class="Constant">1/found</span>, <span class="Constant">0/quit</span> <span id="L71" class="LineNr"> 71 </span>] <span id="L72" class="LineNr"> 72 </span> -<span id="L73" class="LineNr"> 73 </span><span class="muRecipe">def</span> <a href='084console.mu.html#L73'>send-keys-to-channel</a> <a href='084console.mu.html#L23'>console</a>:&:<a href='084console.mu.html#L23'>console</a>, chan:&:<a href='075channel.mu.html#L47'>sink</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a><span class="muRecipe"> -> </span><a href='084console.mu.html#L23'>console</a>:&:<a href='084console.mu.html#L23'>console</a>, chan:&:<a href='075channel.mu.html#L47'>sink</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a> [ +<span id="L73" class="LineNr"> 73 </span><span class="muRecipe">def</span> <a href='084console.mu.html#L73'>send-keys-to-channel</a> <a href='084console.mu.html#L23'>console</a>:&:<a href='084console.mu.html#L23'>console</a>, chan:&:<a href='075channel.mu.html#L40'>sink</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a><span class="muRecipe"> -> </span><a href='084console.mu.html#L23'>console</a>:&:<a href='084console.mu.html#L23'>console</a>, chan:&:<a href='075channel.mu.html#L40'>sink</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a> [ <span id="L74" class="LineNr"> 74 </span> <span class="Constant">local-scope</span> <span id="L75" class="LineNr"> 75 </span> <span class="Constant">load-inputs</span> <span id="L76" class="LineNr"> 76 </span> <span class="Delimiter">{</span> @@ -139,7 +139,7 @@ if ('onhashchange' in window) { <span id="L79" class="LineNr"> 79 </span> <span class="muControl">break-if</span> quit? <span id="L80" class="LineNr"> 80 </span> assert c, <span class="Constant">[invalid <a href='084console.mu.html#L4'>event</a>, expected text]</span> <span id="L81" class="LineNr"> 81 </span> <a href='081print.mu.html#L16'>screen</a> <span class="Special"><-</span> print <a href='081print.mu.html#L16'>screen</a>, c -<span id="L82" class="LineNr"> 82 </span> chan <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> chan, c +<span id="L82" class="LineNr"> 82 </span> chan <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> chan, c <span id="L83" class="LineNr"> 83 </span> <span class="muControl"> loop</span> <span id="L84" class="LineNr"> 84 </span> <span class="Delimiter">}</span> <span id="L85" class="LineNr"> 85 </span> chan <span class="Special"><-</span> close chan diff --git a/html/088file.mu.html b/html/088file.mu.html index 17c78532..6f3a124d 100644 --- a/html/088file.mu.html +++ b/html/088file.mu.html @@ -78,7 +78,7 @@ if ('onhashchange' in window) { <span id="L18" class="LineNr"> 18 </span> contents:text <span id="L19" class="LineNr"> 19 </span>] <span id="L20" class="LineNr"> 20 </span> -<span id="L21" class="LineNr"> 21 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L21'>start-reading</a> <a href='088file.mu.html#L11'>resources</a>:&:<a href='088file.mu.html#L11'>resources</a>, filename:text<span class="muRecipe"> -> </span>contents:&:<a href='075channel.mu.html#L43'>source</a>:char, error?:bool [ +<span id="L21" class="LineNr"> 21 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L21'>start-reading</a> <a href='088file.mu.html#L11'>resources</a>:&:<a href='088file.mu.html#L11'>resources</a>, filename:text<span class="muRecipe"> -> </span>contents:&:<a href='075channel.mu.html#L36'>source</a>:char, error?:bool [ <span id="L22" class="LineNr"> 22 </span> <span class="Constant">local-scope</span> <span id="L23" class="LineNr"> 23 </span> <span class="Constant">load-inputs</span> <span id="L24" class="LineNr"> 24 </span> error? <span class="Special"><-</span> copy <span class="Constant">0/false</span> @@ -91,18 +91,18 @@ if ('onhashchange' in window) { <span id="L31" class="LineNr"> 31 </span> <span class="Comment"># real file system</span> <span id="L32" class="LineNr"> 32 </span> file:num <span class="Special"><-</span> $open-file-for-reading filename <span id="L33" class="LineNr"> 33 </span> <span class="muControl">return-unless</span> file, <span class="Constant">0/contents</span>, <span class="Constant">1/error?</span> -<span id="L34" class="LineNr"> 34 </span> contents:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a><span class="Constant"> 30</span> -<span id="L35" class="LineNr"> 35 </span> <span class="muControl">start-running</span> <a href='088file.mu.html#L76'>receive-from-file</a> file, <a href='075channel.mu.html#L47'>sink</a> +<span id="L34" class="LineNr"> 34 </span> contents:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a><span class="Constant"> 30</span> +<span id="L35" class="LineNr"> 35 </span> <span class="muControl">start-running</span> <a href='088file.mu.html#L76'>receive-from-file</a> file, <a href='075channel.mu.html#L40'>sink</a> <span id="L36" class="LineNr"> 36 </span>] <span id="L37" class="LineNr"> 37 </span> <span id="L38" class="LineNr"> 38 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L38'>slurp</a> <a href='088file.mu.html#L11'>resources</a>:&:<a href='088file.mu.html#L11'>resources</a>, filename:text<span class="muRecipe"> -> </span>contents:text, error?:bool [ <span id="L39" class="LineNr"> 39 </span> <span class="Constant">local-scope</span> <span id="L40" class="LineNr"> 40 </span> <span class="Constant">load-inputs</span> -<span id="L41" class="LineNr"> 41 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char, error?:bool <span class="Special"><-</span> <a href='088file.mu.html#L21'>start-reading</a> <a href='088file.mu.html#L11'>resources</a>, filename +<span id="L41" class="LineNr"> 41 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char, error?:bool <span class="Special"><-</span> <a href='088file.mu.html#L21'>start-reading</a> <a href='088file.mu.html#L11'>resources</a>, filename <span id="L42" class="LineNr"> 42 </span> <span class="muControl">return-if</span> error?, <span class="Constant">0/contents</span> <span id="L43" class="LineNr"> 43 </span> buf:&:<a href='061text.mu.html#L120'>buffer</a>:char <span class="Special"><-</span> <a href='061text.mu.html#L125'>new-buffer</a> <span class="Constant">30/capacity</span> <span id="L44" class="LineNr"> 44 </span> <span class="Delimiter">{</span> -<span id="L45" class="LineNr"> 45 </span> c:char, done?:bool, <a href='075channel.mu.html#L43'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L43'>source</a> +<span id="L45" class="LineNr"> 45 </span> c:char, done?:bool, <a href='075channel.mu.html#L36'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L36'>source</a> <span id="L46" class="LineNr"> 46 </span> <span class="muControl">break-if</span> done? <span id="L47" class="LineNr"> 47 </span> buf <span class="Special"><-</span> append buf, c <span id="L48" class="LineNr"> 48 </span> <span class="muControl"> loop</span> @@ -110,7 +110,7 @@ if ('onhashchange' in window) { <span id="L50" class="LineNr"> 50 </span> contents <span class="Special"><-</span> <a href='061text.mu.html#L338'>buffer-to-array</a> buf <span id="L51" class="LineNr"> 51 </span>] <span id="L52" class="LineNr"> 52 </span> -<span id="L53" class="LineNr"> 53 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L53'>start-reading-from-fake-resource</a> <a href='088file.mu.html#L11'>resources</a>:&:<a href='088file.mu.html#L11'>resources</a>, <a href='088file.mu.html#L16'>resource</a>:text<span class="muRecipe"> -> </span>contents:&:<a href='075channel.mu.html#L43'>source</a>:char, error?:bool [ +<span id="L53" class="LineNr"> 53 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L53'>start-reading-from-fake-resource</a> <a href='088file.mu.html#L11'>resources</a>:&:<a href='088file.mu.html#L11'>resources</a>, <a href='088file.mu.html#L16'>resource</a>:text<span class="muRecipe"> -> </span>contents:&:<a href='075channel.mu.html#L36'>source</a>:char, error?:bool [ <span id="L54" class="LineNr"> 54 </span> <span class="Constant">local-scope</span> <span id="L55" class="LineNr"> 55 </span> <span class="Constant">load-inputs</span> <span id="L56" class="LineNr"> 56 </span> error? <span class="Special"><-</span> copy <span class="Constant">0/no-error</span> @@ -125,28 +125,28 @@ if ('onhashchange' in window) { <span id="L65" class="LineNr"> 65 </span> curr-resource:text <span class="Special"><-</span> get tmp, <span class="Constant">name:offset</span> <span id="L66" class="LineNr"> 66 </span> found?:bool <span class="Special"><-</span> equal <a href='088file.mu.html#L16'>resource</a>, curr-resource <span id="L67" class="LineNr"> 67 </span> <span class="muControl">loop-unless</span> found? -<span id="L68" class="LineNr"> 68 </span> contents:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a><span class="Constant"> 30</span> +<span id="L68" class="LineNr"> 68 </span> contents:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a><span class="Constant"> 30</span> <span id="L69" class="LineNr"> 69 </span> curr-contents:text <span class="Special"><-</span> get tmp, <span class="Constant">contents:offset</span> -<span id="L70" class="LineNr"> 70 </span> <span class="muControl">start-running</span> <a href='088file.mu.html#L89'>receive-from-text</a> curr-contents, <a href='075channel.mu.html#L47'>sink</a> +<span id="L70" class="LineNr"> 70 </span> <span class="muControl">start-running</span> <a href='088file.mu.html#L89'>receive-from-text</a> curr-contents, <a href='075channel.mu.html#L40'>sink</a> <span id="L71" class="LineNr"> 71 </span> <span class="muControl"> return</span> <span id="L72" class="LineNr"> 72 </span> <span class="Delimiter">}</span> <span id="L73" class="LineNr"> 73 </span> <span class="muControl"> return</span> <span class="Constant">0/not-found</span>, <span class="Constant">1/error</span> <span id="L74" class="LineNr"> 74 </span>] <span id="L75" class="LineNr"> 75 </span> -<span id="L76" class="LineNr"> 76 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L76'>receive-from-file</a> file:num, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char<span class="muRecipe"> -> </span><a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char [ +<span id="L76" class="LineNr"> 76 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L76'>receive-from-file</a> file:num, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char<span class="muRecipe"> -> </span><a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char [ <span id="L77" class="LineNr"> 77 </span> <span class="Constant">local-scope</span> <span id="L78" class="LineNr"> 78 </span> <span class="Constant">load-inputs</span> <span id="L79" class="LineNr"> 79 </span> <span class="Delimiter">{</span> <span id="L80" class="LineNr"> 80 </span> c:char, eof?:bool <span class="Special"><-</span> $read-from-file file <span id="L81" class="LineNr"> 81 </span> <span class="muControl">break-if</span> eof? -<span id="L82" class="LineNr"> 82 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, c +<span id="L82" class="LineNr"> 82 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, c <span id="L83" class="LineNr"> 83 </span> <span class="muControl"> loop</span> <span id="L84" class="LineNr"> 84 </span> <span class="Delimiter">}</span> -<span id="L85" class="LineNr"> 85 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> close <a href='075channel.mu.html#L47'>sink</a> +<span id="L85" class="LineNr"> 85 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> close <a href='075channel.mu.html#L40'>sink</a> <span id="L86" class="LineNr"> 86 </span> file <span class="Special"><-</span> $close-file file <span id="L87" class="LineNr"> 87 </span>] <span id="L88" class="LineNr"> 88 </span> -<span id="L89" class="LineNr"> 89 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L89'>receive-from-text</a> contents:text, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char<span class="muRecipe"> -> </span><a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char [ +<span id="L89" class="LineNr"> 89 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L89'>receive-from-text</a> contents:text, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char<span class="muRecipe"> -> </span><a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char [ <span id="L90" class="LineNr"> 90 </span> <span class="Constant">local-scope</span> <span id="L91" class="LineNr"> 91 </span> <span class="Constant">load-inputs</span> <span id="L92" class="LineNr"> 92 </span> i:num <span class="Special"><-</span> copy<span class="Constant"> 0</span> @@ -155,22 +155,22 @@ if ('onhashchange' in window) { <span id="L95" class="LineNr"> 95 </span> done?:bool <span class="Special"><-</span> greater-or-equal i, len <span id="L96" class="LineNr"> 96 </span> <span class="muControl">break-if</span> done? <span id="L97" class="LineNr"> 97 </span> c:char <span class="Special"><-</span> index *contents, i -<span id="L98" class="LineNr"> 98 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, c +<span id="L98" class="LineNr"> 98 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, c <span id="L99" class="LineNr"> 99 </span> i <span class="Special"><-</span> add i,<span class="Constant"> 1</span> <span id="L100" class="LineNr">100 </span> <span class="muControl"> loop</span> <span id="L101" class="LineNr">101 </span> <span class="Delimiter">}</span> -<span id="L102" class="LineNr">102 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> close <a href='075channel.mu.html#L47'>sink</a> +<span id="L102" class="LineNr">102 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> close <a href='075channel.mu.html#L40'>sink</a> <span id="L103" class="LineNr">103 </span>] <span id="L104" class="LineNr">104 </span> -<span id="L105" class="LineNr">105 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L105'>start-writing</a> <a href='088file.mu.html#L11'>resources</a>:&:<a href='088file.mu.html#L11'>resources</a>, filename:text<span class="muRecipe"> -> </span><a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char, routine-id:num, error?:bool [ +<span id="L105" class="LineNr">105 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L105'>start-writing</a> <a href='088file.mu.html#L11'>resources</a>:&:<a href='088file.mu.html#L11'>resources</a>, filename:text<span class="muRecipe"> -> </span><a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char, routine-id:num, error?:bool [ <span id="L106" class="LineNr">106 </span> <span class="Constant">local-scope</span> <span id="L107" class="LineNr">107 </span> <span class="Constant">load-inputs</span> <span id="L108" class="LineNr">108 </span> error? <span class="Special"><-</span> copy <span class="Constant">0/false</span> -<span id="L109" class="LineNr">109 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a><span class="Constant"> 30</span> +<span id="L109" class="LineNr">109 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a><span class="Constant"> 30</span> <span id="L110" class="LineNr">110 </span> <span class="Delimiter">{</span> <span id="L111" class="LineNr">111 </span> <span class="muControl">break-unless</span> <a href='088file.mu.html#L11'>resources</a> <span id="L112" class="LineNr">112 </span> <span class="Comment"># fake file system</span> -<span id="L113" class="LineNr">113 </span> routine-id <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='088file.mu.html#L162'>transmit-to-fake-resource</a> <a href='088file.mu.html#L11'>resources</a>, filename, <a href='075channel.mu.html#L43'>source</a> +<span id="L113" class="LineNr">113 </span> routine-id <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='088file.mu.html#L162'>transmit-to-fake-resource</a> <a href='088file.mu.html#L11'>resources</a>, filename, <a href='075channel.mu.html#L36'>source</a> <span id="L114" class="LineNr">114 </span> <span class="muControl"> return</span> <span id="L115" class="LineNr">115 </span> <span class="Delimiter">}</span> <span id="L116" class="LineNr">116 </span> <span class="Comment"># real file system</span> @@ -181,7 +181,7 @@ if ('onhashchange' in window) { <span id="L121" class="LineNr">121 </span> msg:text <span class="Special"><-</span> append <span class="Constant">[no such file: ]</span> filename <span id="L122" class="LineNr">122 </span> assert file, msg <span id="L123" class="LineNr">123 </span> <span class="Delimiter">}</span> -<span id="L124" class="LineNr">124 </span> routine-id <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='088file.mu.html#L150'>transmit-to-file</a> file, <a href='075channel.mu.html#L43'>source</a> +<span id="L124" class="LineNr">124 </span> routine-id <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='088file.mu.html#L150'>transmit-to-file</a> file, <a href='075channel.mu.html#L36'>source</a> <span id="L125" class="LineNr">125 </span>] <span id="L126" class="LineNr">126 </span> <span id="L127" class="LineNr">127 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L127'>dump</a> <a href='088file.mu.html#L11'>resources</a>:&:<a href='088file.mu.html#L11'>resources</a>, filename:text, contents:text<span class="muRecipe"> -> </span><a href='088file.mu.html#L11'>resources</a>:&:<a href='088file.mu.html#L11'>resources</a>, error?:bool [ @@ -189,7 +189,7 @@ if ('onhashchange' in window) { <span id="L129" class="LineNr">129 </span> <span class="Constant">load-inputs</span> <span id="L130" class="LineNr">130 </span> <span class="Comment"># todo: really create an empty file</span> <span id="L131" class="LineNr">131 </span> <span class="muControl">return-unless</span> contents, <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">0/no-error</span> -<span id="L132" class="LineNr">132 </span> sink-file:&:<a href='075channel.mu.html#L47'>sink</a>:char, write-routine:num, error?:bool <span class="Special"><-</span> <a href='088file.mu.html#L105'>start-writing</a> <a href='088file.mu.html#L11'>resources</a>, filename +<span id="L132" class="LineNr">132 </span> sink-file:&:<a href='075channel.mu.html#L40'>sink</a>:char, write-routine:num, error?:bool <span class="Special"><-</span> <a href='088file.mu.html#L105'>start-writing</a> <a href='088file.mu.html#L11'>resources</a>, filename <span id="L133" class="LineNr">133 </span> <span class="muControl">return-if</span> error? <span id="L134" class="LineNr">134 </span> i:num <span class="Special"><-</span> copy<span class="Constant"> 0</span> <span id="L135" class="LineNr">135 </span> len:num <span class="Special"><-</span> length *contents @@ -197,7 +197,7 @@ if ('onhashchange' in window) { <span id="L137" class="LineNr">137 </span> done?:bool <span class="Special"><-</span> greater-or-equal i, len <span id="L138" class="LineNr">138 </span> <span class="muControl">break-if</span> done? <span id="L139" class="LineNr">139 </span> c:char <span class="Special"><-</span> index *contents, i -<span id="L140" class="LineNr">140 </span> sink-file <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> sink-file, c +<span id="L140" class="LineNr">140 </span> sink-file <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> sink-file, c <span id="L141" class="LineNr">141 </span> i <span class="Special"><-</span> add i,<span class="Constant"> 1</span> <span id="L142" class="LineNr">142 </span> <span class="muControl"> loop</span> <span id="L143" class="LineNr">143 </span> <span class="Delimiter">}</span> @@ -207,11 +207,11 @@ if ('onhashchange' in window) { <span id="L147" class="LineNr">147 </span> wait-for-routine write-routine <span id="L148" class="LineNr">148 </span>] <span id="L149" class="LineNr">149 </span> -<span id="L150" class="LineNr">150 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L150'>transmit-to-file</a> file:num, <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char<span class="muRecipe"> -> </span><a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char [ +<span id="L150" class="LineNr">150 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L150'>transmit-to-file</a> file:num, <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char<span class="muRecipe"> -> </span><a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char [ <span id="L151" class="LineNr">151 </span> <span class="Constant">local-scope</span> <span id="L152" class="LineNr">152 </span> <span class="Constant">load-inputs</span> <span id="L153" class="LineNr">153 </span> <span class="Delimiter">{</span> -<span id="L154" class="LineNr">154 </span> c:char, done?:bool, <a href='075channel.mu.html#L43'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L43'>source</a> +<span id="L154" class="LineNr">154 </span> c:char, done?:bool, <a href='075channel.mu.html#L36'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L36'>source</a> <span id="L155" class="LineNr">155 </span> <span class="muControl">break-if</span> done? <span id="L156" class="LineNr">156 </span> $write-to-file file, c <span id="L157" class="LineNr">157 </span> <span class="muControl"> loop</span> @@ -219,7 +219,7 @@ if ('onhashchange' in window) { <span id="L159" class="LineNr">159 </span> file <span class="Special"><-</span> $close-file file <span id="L160" class="LineNr">160 </span>] <span id="L161" class="LineNr">161 </span> -<span id="L162" class="LineNr">162 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L162'>transmit-to-fake-resource</a> <a href='088file.mu.html#L11'>resources</a>:&:<a href='088file.mu.html#L11'>resources</a>, filename:text, <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char<span class="muRecipe"> -> </span><a href='088file.mu.html#L11'>resources</a>:&:<a href='088file.mu.html#L11'>resources</a>, <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char [ +<span id="L162" class="LineNr">162 </span><span class="muRecipe">def</span> <a href='088file.mu.html#L162'>transmit-to-fake-resource</a> <a href='088file.mu.html#L11'>resources</a>:&:<a href='088file.mu.html#L11'>resources</a>, filename:text, <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char<span class="muRecipe"> -> </span><a href='088file.mu.html#L11'>resources</a>:&:<a href='088file.mu.html#L11'>resources</a>, <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char [ <span id="L163" class="LineNr">163 </span> <span class="Constant">local-scope</span> <span id="L164" class="LineNr">164 </span> <span class="Constant">load-inputs</span> <span id="L165" class="LineNr">165 </span> lock:location <span class="Special"><-</span> get-location *resources, <span class="Constant">lock:offset</span> @@ -227,7 +227,7 @@ if ('onhashchange' in window) { <span id="L167" class="LineNr">167 </span> <span class="Comment"># compute new file contents</span> <span id="L168" class="LineNr">168 </span> buf:&:<a href='061text.mu.html#L120'>buffer</a>:char <span class="Special"><-</span> <a href='061text.mu.html#L125'>new-buffer</a><span class="Constant"> 30</span> <span id="L169" class="LineNr">169 </span> <span class="Delimiter">{</span> -<span id="L170" class="LineNr">170 </span> c:char, done?:bool, <a href='075channel.mu.html#L43'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L43'>source</a> +<span id="L170" class="LineNr">170 </span> c:char, done?:bool, <a href='075channel.mu.html#L36'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L36'>source</a> <span id="L171" class="LineNr">171 </span> <span class="muControl">break-if</span> done? <span id="L172" class="LineNr">172 </span> buf <span class="Special"><-</span> append buf, c <span id="L173" class="LineNr">173 </span> <span class="muControl"> loop</span> diff --git a/html/090scenario_filesystem_test.mu.html b/html/090scenario_filesystem_test.mu.html index 847489f1..917665b1 100644 --- a/html/090scenario_filesystem_test.mu.html +++ b/html/090scenario_filesystem_test.mu.html @@ -64,7 +64,7 @@ if ('onhashchange' in window) { <span id="L7" class="LineNr"> 7 </span><span class="Constant"> |xyz|</span> <span id="L8" class="LineNr"> 8 </span> ] <span id="L9" class="LineNr"> 9 </span> ] -<span id="L10" class="LineNr">10 </span> contents:&:<a href='075channel.mu.html#L43'>source</a>:char <span class="Special"><-</span> <a href='088file.mu.html#L21'>start-reading</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[a]</span> +<span id="L10" class="LineNr">10 </span> contents:&:<a href='075channel.mu.html#L36'>source</a>:char <span class="Special"><-</span> <a href='088file.mu.html#L21'>start-reading</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[a]</span> <span id="L11" class="LineNr">11 </span> 1:char/<span class="Special">raw</span> <span class="Special"><-</span> read contents <span id="L12" class="LineNr">12 </span> 2:char/<span class="Special">raw</span> <span class="Special"><-</span> read contents <span id="L13" class="LineNr">13 </span> 3:char/<span class="Special">raw</span> <span class="Special"><-</span> read contents @@ -83,10 +83,10 @@ if ('onhashchange' in window) { <span id="L26" class="LineNr">26 </span> <span class="Constant">local-scope</span> <span id="L27" class="LineNr">27 </span> assume-resources [ <span id="L28" class="LineNr">28 </span> ] -<span id="L29" class="LineNr">29 </span> <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char, writer:num/routine <span class="Special"><-</span> <a href='088file.mu.html#L105'>start-writing</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[a]</span> -<span id="L30" class="LineNr">30 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">120/x</span> -<span id="L31" class="LineNr">31 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">121/y</span> -<span id="L32" class="LineNr">32 </span> close <a href='075channel.mu.html#L47'>sink</a> +<span id="L29" class="LineNr">29 </span> <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char, writer:num/routine <span class="Special"><-</span> <a href='088file.mu.html#L105'>start-writing</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[a]</span> +<span id="L30" class="LineNr">30 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">120/x</span> +<span id="L31" class="LineNr">31 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">121/y</span> +<span id="L32" class="LineNr">32 </span> close <a href='075channel.mu.html#L40'>sink</a> <span id="L33" class="LineNr">33 </span> wait-for-routine writer <span id="L34" class="LineNr">34 </span> contents-read-back:text <span class="Special"><-</span> <a href='088file.mu.html#L38'>slurp</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[a]</span> <span id="L35" class="LineNr">35 </span> 10:bool/<span class="Special">raw</span> <span class="Special"><-</span> equal contents-read-back, <span class="Constant">[xy]</span> @@ -102,10 +102,10 @@ if ('onhashchange' in window) { <span id="L45" class="LineNr">45 </span><span class="Constant"> |abc|</span> <span id="L46" class="LineNr">46 </span> ] <span id="L47" class="LineNr">47 </span> ] -<span id="L48" class="LineNr">48 </span> <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char, writer:num/routine <span class="Special"><-</span> <a href='088file.mu.html#L105'>start-writing</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[b]</span> -<span id="L49" class="LineNr">49 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">120/x</span> -<span id="L50" class="LineNr">50 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">121/y</span> -<span id="L51" class="LineNr">51 </span> close <a href='075channel.mu.html#L47'>sink</a> +<span id="L48" class="LineNr">48 </span> <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char, writer:num/routine <span class="Special"><-</span> <a href='088file.mu.html#L105'>start-writing</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[b]</span> +<span id="L49" class="LineNr">49 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">120/x</span> +<span id="L50" class="LineNr">50 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">121/y</span> +<span id="L51" class="LineNr">51 </span> close <a href='075channel.mu.html#L40'>sink</a> <span id="L52" class="LineNr">52 </span> wait-for-routine writer <span id="L53" class="LineNr">53 </span> contents-read-back:text <span class="Special"><-</span> <a href='088file.mu.html#L38'>slurp</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[b]</span> <span id="L54" class="LineNr">54 </span> 10:bool/<span class="Special">raw</span> <span class="Special"><-</span> equal contents-read-back, <span class="Constant">[xy]</span> @@ -119,10 +119,10 @@ if ('onhashchange' in window) { <span id="L62" class="LineNr">62 </span> assume-resources [ <span id="L63" class="LineNr">63 </span> <span class="Constant">[a]</span> <span class="Special"><-</span> <span class="Constant">[]</span> <span id="L64" class="LineNr">64 </span> ] -<span id="L65" class="LineNr">65 </span> <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char, writer:num/routine <span class="Special"><-</span> <a href='088file.mu.html#L105'>start-writing</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[a]</span> -<span id="L66" class="LineNr">66 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">120/x</span> -<span id="L67" class="LineNr">67 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">121/y</span> -<span id="L68" class="LineNr">68 </span> close <a href='075channel.mu.html#L47'>sink</a> +<span id="L65" class="LineNr">65 </span> <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char, writer:num/routine <span class="Special"><-</span> <a href='088file.mu.html#L105'>start-writing</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[a]</span> +<span id="L66" class="LineNr">66 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">120/x</span> +<span id="L67" class="LineNr">67 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">121/y</span> +<span id="L68" class="LineNr">68 </span> close <a href='075channel.mu.html#L40'>sink</a> <span id="L69" class="LineNr">69 </span> wait-for-routine writer <span id="L70" class="LineNr">70 </span> contents-read-back:text <span class="Special"><-</span> <a href='088file.mu.html#L38'>slurp</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[a]</span> <span id="L71" class="LineNr">71 </span> 10:bool/<span class="Special">raw</span> <span class="Special"><-</span> equal contents-read-back, <span class="Constant">[xy]</span> @@ -139,10 +139,10 @@ if ('onhashchange' in window) { <span id="L82" class="LineNr">82 </span><span class="Constant"> |bcd|</span> <span id="L83" class="LineNr">83 </span> ] <span id="L84" class="LineNr">84 </span> ] -<span id="L85" class="LineNr">85 </span> <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char, writer:num/routine <span class="Special"><-</span> <a href='088file.mu.html#L105'>start-writing</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[a]</span> -<span id="L86" class="LineNr">86 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">120/x</span> -<span id="L87" class="LineNr">87 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">121/y</span> -<span id="L88" class="LineNr">88 </span> close <a href='075channel.mu.html#L47'>sink</a> +<span id="L85" class="LineNr">85 </span> <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char, writer:num/routine <span class="Special"><-</span> <a href='088file.mu.html#L105'>start-writing</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[a]</span> +<span id="L86" class="LineNr">86 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">120/x</span> +<span id="L87" class="LineNr">87 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">121/y</span> +<span id="L88" class="LineNr">88 </span> close <a href='075channel.mu.html#L40'>sink</a> <span id="L89" class="LineNr">89 </span> wait-for-routine writer <span id="L90" class="LineNr">90 </span> contents-read-back:text <span class="Special"><-</span> <a href='088file.mu.html#L38'>slurp</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[a]</span> <span id="L91" class="LineNr">91 </span> 10:bool/<span class="Special">raw</span> <span class="Special"><-</span> equal contents-read-back, <span class="Constant">[xy]</span> diff --git a/html/092socket.mu.html b/html/092socket.mu.html index 427daf3d..c4f4b080 100644 --- a/html/092socket.mu.html +++ b/html/092socket.mu.html @@ -75,8 +75,8 @@ if ('onhashchange' in window) { <span id="L14" class="LineNr"> 14 </span><span class="Constant">F - example-server-test: $open-server-socket failed]</span> <span id="L15" class="LineNr"> 15 </span> handler-routine:number <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='092socket.mu.html#L55'>serve-one-request</a> socket, <a href='092socket.mu.html#L26'>example-handler</a> <span id="L16" class="LineNr"> 16 </span> ] -<span id="L17" class="LineNr"> 17 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char <span class="Special"><-</span> <a href='092socket.mu.html#L69'>start-reading-from-network</a> <span class="Constant">0/real-resources</span>, <span class="Constant">[localhost/]</span>, port -<span id="L18" class="LineNr"> 18 </span> response:text <span class="Special"><-</span> <a href='075channel.mu.html#L507'>drain</a> <a href='075channel.mu.html#L43'>source</a> +<span id="L17" class="LineNr"> 17 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char <span class="Special"><-</span> <a href='092socket.mu.html#L69'>start-reading-from-network</a> <span class="Constant">0/real-resources</span>, <span class="Constant">[localhost/]</span>, port +<span id="L18" class="LineNr"> 18 </span> response:text <span class="Special"><-</span> <a href='075channel.mu.html#L499'>drain</a> <a href='075channel.mu.html#L36'>source</a> <span id="L19" class="LineNr"> 19 </span> 10:@:char/<span class="Special">raw</span> <span class="Special"><-</span> copy *response <span id="L20" class="LineNr"> 20 </span> memory-should-contain [ <span id="L21" class="LineNr"> 21 </span> 10:array:character <span class="Special"><-</span> <span class="Constant">[abc]</span> @@ -101,9 +101,9 @@ if ('onhashchange' in window) { <span id="L40" class="LineNr"> 40 </span> ] <span id="L41" class="LineNr"> 41 </span> ] <span id="L42" class="LineNr"> 42 </span> run [ -<span id="L43" class="LineNr"> 43 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char <span class="Special"><-</span> <a href='092socket.mu.html#L69'>start-reading-from-network</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[example.com/]</span> +<span id="L43" class="LineNr"> 43 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char <span class="Special"><-</span> <a href='092socket.mu.html#L69'>start-reading-from-network</a> <a href='088file.mu.html#L11'>resources</a>, <span class="Constant">[example.com/]</span> <span id="L44" class="LineNr"> 44 </span> ] -<span id="L45" class="LineNr"> 45 </span> contents:text <span class="Special"><-</span> <a href='075channel.mu.html#L507'>drain</a> <a href='075channel.mu.html#L43'>source</a> +<span id="L45" class="LineNr"> 45 </span> contents:text <span class="Special"><-</span> <a href='075channel.mu.html#L499'>drain</a> <a href='075channel.mu.html#L36'>source</a> <span id="L46" class="LineNr"> 46 </span> 10:@:char/<span class="Special">raw</span> <span class="Special"><-</span> copy *contents <span id="L47" class="LineNr"> 47 </span> memory-should-contain [ <span id="L48" class="LineNr"> 48 </span> 10:array:character <span class="Special"><-</span> <span class="Constant">[abc</span> @@ -119,15 +119,15 @@ if ('onhashchange' in window) { <span id="L58" class="LineNr"> 58 </span> session:num <span class="Special"><-</span> $accept socket <span id="L59" class="LineNr"> 59 </span> assert session, <span class="Constant">[ </span> <span id="L60" class="LineNr"> 60 </span><span class="Constant">F - example-server-test: $accept failed]</span> -<span id="L61" class="LineNr"> 61 </span> contents:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a><span class="Constant"> 30</span> -<span id="L62" class="LineNr"> 62 </span> <span class="muControl">start-running</span> <a href='092socket.mu.html#L104'>receive-from-socket</a> session, <a href='075channel.mu.html#L47'>sink</a> -<span id="L63" class="LineNr"> 63 </span> query:text <span class="Special"><-</span> <a href='075channel.mu.html#L507'>drain</a> contents +<span id="L61" class="LineNr"> 61 </span> contents:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a><span class="Constant"> 30</span> +<span id="L62" class="LineNr"> 62 </span> <span class="muControl">start-running</span> <a href='092socket.mu.html#L104'>receive-from-socket</a> session, <a href='075channel.mu.html#L40'>sink</a> +<span id="L63" class="LineNr"> 63 </span> query:text <span class="Special"><-</span> <a href='075channel.mu.html#L499'>drain</a> contents <span id="L64" class="LineNr"> 64 </span> response:text <span class="Special"><-</span> call <a href='092socket.mu.html#L53'>request-handler</a>, query <span id="L65" class="LineNr"> 65 </span> <a href='092socket.mu.html#L132'>write-to-socket</a> session, response <span id="L66" class="LineNr"> 66 </span> session <span class="Special"><-</span> $close-socket session <span id="L67" class="LineNr"> 67 </span>] <span id="L68" class="LineNr"> 68 </span> -<span id="L69" class="LineNr"> 69 </span><span class="muRecipe">def</span> <a href='092socket.mu.html#L69'>start-reading-from-network</a> <a href='088file.mu.html#L11'>resources</a>:&:<a href='088file.mu.html#L11'>resources</a>, uri:text<span class="muRecipe"> -> </span>contents:&:<a href='075channel.mu.html#L43'>source</a>:char [ +<span id="L69" class="LineNr"> 69 </span><span class="muRecipe">def</span> <a href='092socket.mu.html#L69'>start-reading-from-network</a> <a href='088file.mu.html#L11'>resources</a>:&:<a href='088file.mu.html#L11'>resources</a>, uri:text<span class="muRecipe"> -> </span>contents:&:<a href='075channel.mu.html#L36'>source</a>:char [ <span id="L70" class="LineNr"> 70 </span> <span class="Constant">local-scope</span> <span id="L71" class="LineNr"> 71 </span> <span class="Constant">load-inputs</span> <span id="L72" class="LineNr"> 72 </span> <span class="Delimiter">{</span> @@ -147,8 +147,8 @@ if ('onhashchange' in window) { <span id="L86" class="LineNr"> 86 </span> assert socket, <span class="Constant">[contents]</span> <span id="L87" class="LineNr"> 87 </span> req:text <span class="Special"><-</span> <a href='061text.mu.html#L520'>interpolate</a> <span class="Constant">[GET _ HTTP/1.1]</span>, path <span id="L88" class="LineNr"> 88 </span> <a href='092socket.mu.html#L93'>request-socket</a> socket, req -<span id="L89" class="LineNr"> 89 </span> contents:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a><span class="Constant"> 10000</span> -<span id="L90" class="LineNr"> 90 </span> <span class="muControl">start-running</span> <a href='092socket.mu.html#L125'>receive-from-client-socket-and-close</a> socket, <a href='075channel.mu.html#L47'>sink</a> +<span id="L89" class="LineNr"> 89 </span> contents:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a><span class="Constant"> 10000</span> +<span id="L90" class="LineNr"> 90 </span> <span class="muControl">start-running</span> <a href='092socket.mu.html#L125'>receive-from-client-socket-and-close</a> socket, <a href='075channel.mu.html#L40'>sink</a> <span id="L91" class="LineNr"> 91 </span>] <span id="L92" class="LineNr"> 92 </span> <span id="L93" class="LineNr"> 93 </span><span class="muRecipe">def</span> <a href='092socket.mu.html#L93'>request-socket</a> socket:num, s:text<span class="muRecipe"> -> </span>socket:num [ @@ -162,7 +162,7 @@ if ('onhashchange' in window) { <span id="L101" class="LineNr">101 </span> $write-to-socket socket, <span class="Constant">10/lf</span> <span id="L102" class="LineNr">102 </span>] <span id="L103" class="LineNr">103 </span> -<span id="L104" class="LineNr">104 </span><span class="muRecipe">def</span> <a href='092socket.mu.html#L104'>receive-from-socket</a> socket:num, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char<span class="muRecipe"> -> </span><a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char, socket:num [ +<span id="L104" class="LineNr">104 </span><span class="muRecipe">def</span> <a href='092socket.mu.html#L104'>receive-from-socket</a> socket:num, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char<span class="muRecipe"> -> </span><a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char, socket:num [ <span id="L105" class="LineNr">105 </span> <span class="Constant">local-scope</span> <span id="L106" class="LineNr">106 </span> <span class="Constant">load-inputs</span> <span id="L107" class="LineNr">107 </span> <span class="Delimiter">{</span> @@ -172,7 +172,7 @@ if ('onhashchange' in window) { <span id="L111" class="LineNr">111 </span> <span class="muControl">break-if</span> error <span id="L112" class="LineNr">112 </span> <span class="Delimiter">{</span> <span id="L113" class="LineNr">113 </span> <span class="muControl">break-unless</span> found? -<span id="L114" class="LineNr">114 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, c +<span id="L114" class="LineNr">114 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, c <span id="L115" class="LineNr">115 </span> <span class="Delimiter">}</span> <span id="L116" class="LineNr">116 </span> <span class="Delimiter">{</span> <span id="L117" class="LineNr">117 </span> <span class="muControl">break-if</span> found? @@ -180,13 +180,13 @@ if ('onhashchange' in window) { <span id="L119" class="LineNr">119 </span> <span class="Delimiter">}</span> <span id="L120" class="LineNr">120 </span> <span class="muControl"> loop</span> <span id="L121" class="LineNr">121 </span> <span class="Delimiter">}</span> -<span id="L122" class="LineNr">122 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> close <a href='075channel.mu.html#L47'>sink</a> +<span id="L122" class="LineNr">122 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> close <a href='075channel.mu.html#L40'>sink</a> <span id="L123" class="LineNr">123 </span>] <span id="L124" class="LineNr">124 </span> -<span id="L125" class="LineNr">125 </span><span class="muRecipe">def</span> <a href='092socket.mu.html#L125'>receive-from-client-socket-and-close</a> socket:num, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char<span class="muRecipe"> -> </span><a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char, socket:num [ +<span id="L125" class="LineNr">125 </span><span class="muRecipe">def</span> <a href='092socket.mu.html#L125'>receive-from-client-socket-and-close</a> socket:num, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char<span class="muRecipe"> -> </span><a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char, socket:num [ <span id="L126" class="LineNr">126 </span> <span class="Constant">local-scope</span> <span id="L127" class="LineNr">127 </span> <span class="Constant">load-inputs</span> -<span id="L128" class="LineNr">128 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='092socket.mu.html#L104'>receive-from-socket</a> socket, <a href='075channel.mu.html#L47'>sink</a> +<span id="L128" class="LineNr">128 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='092socket.mu.html#L104'>receive-from-socket</a> socket, <a href='075channel.mu.html#L40'>sink</a> <span id="L129" class="LineNr">129 </span> socket <span class="Special"><-</span> $close-socket socket <span id="L130" class="LineNr">130 </span>] <span id="L131" class="LineNr">131 </span> diff --git a/html/channel.mu.html b/html/channel.mu.html index f69af8e5..fdb5c2dc 100644 --- a/html/channel.mu.html +++ b/html/channel.mu.html @@ -59,7 +59,7 @@ if ('onhashchange' in window) { <pre id='vimCodeElement'> <span id="L1" class="LineNr"> 1 </span><span class="Comment"># example program: communicating between routines using channels</span> <span id="L2" class="LineNr"> 2 </span> -<span id="L3" class="LineNr"> 3 </span><span class="muRecipe">def</span> <a href='channel.mu.html#L3'>producer</a> <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char<span class="muRecipe"> -> </span><a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char [ +<span id="L3" class="LineNr"> 3 </span><span class="muRecipe">def</span> <a href='channel.mu.html#L3'>producer</a> <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char<span class="muRecipe"> -> </span><a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char [ <span id="L4" class="LineNr"> 4 </span> <span class="Comment"># produce characters 1 to 5 on a channel</span> <span id="L5" class="LineNr"> 5 </span> <span class="Constant">local-scope</span> <span id="L6" class="LineNr"> 6 </span> <span class="Constant">load-inputs</span> @@ -71,20 +71,20 @@ if ('onhashchange' in window) { <span id="L12" class="LineNr">12 </span> <span class="Comment"># other threads might get between these prints</span> <span id="L13" class="LineNr">13 </span> $print <span class="Constant">[produce: ]</span>, n, <span class="Constant">[ </span> <span id="L14" class="LineNr">14 </span><span class="Constant">]</span> -<span id="L15" class="LineNr">15 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, n +<span id="L15" class="LineNr">15 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, n <span id="L16" class="LineNr">16 </span> n <span class="Special"><-</span> add n,<span class="Constant"> 1</span> <span id="L17" class="LineNr">17 </span> <span class="muControl"> loop</span> <span id="L18" class="LineNr">18 </span> <span class="Delimiter">}</span> -<span id="L19" class="LineNr">19 </span> close <a href='075channel.mu.html#L47'>sink</a> +<span id="L19" class="LineNr">19 </span> close <a href='075channel.mu.html#L40'>sink</a> <span id="L20" class="LineNr">20 </span>] <span id="L21" class="LineNr">21 </span> -<span id="L22" class="LineNr">22 </span><span class="muRecipe">def</span> <a href='channel.mu.html#L22'>consumer</a> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char<span class="muRecipe"> -> </span><a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char [ +<span id="L22" class="LineNr">22 </span><span class="muRecipe">def</span> <a href='channel.mu.html#L22'>consumer</a> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char<span class="muRecipe"> -> </span><a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char [ <span id="L23" class="LineNr">23 </span> <span class="Comment"># consume and print integers from a channel</span> <span id="L24" class="LineNr">24 </span> <span class="Constant">local-scope</span> <span id="L25" class="LineNr">25 </span> <span class="Constant">load-inputs</span> <span id="L26" class="LineNr">26 </span> <span class="Delimiter">{</span> <span id="L27" class="LineNr">27 </span> <span class="Comment"># read an integer from the channel</span> -<span id="L28" class="LineNr">28 </span> n:char, eof?:bool, <a href='075channel.mu.html#L43'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L43'>source</a> +<span id="L28" class="LineNr">28 </span> n:char, eof?:bool, <a href='075channel.mu.html#L36'>source</a> <span class="Special"><-</span> read <a href='075channel.mu.html#L36'>source</a> <span id="L29" class="LineNr">29 </span> <span class="muControl">break-if</span> eof? <span id="L30" class="LineNr">30 </span> <span class="Comment"># other threads might get between these prints</span> <span id="L31" class="LineNr">31 </span> $print <span class="Constant">[consume: ]</span>, n:char, <span class="Constant">[ </span> @@ -95,10 +95,10 @@ if ('onhashchange' in window) { <span id="L36" class="LineNr">36 </span> <span id="L37" class="LineNr">37 </span><span class="muRecipe">def</span> <a href='channel.mu.html#L37'>main</a> [ <span id="L38" class="LineNr">38 </span> <span class="Constant">local-scope</span> -<span id="L39" class="LineNr">39 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">3/capacity</span> +<span id="L39" class="LineNr">39 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">3/capacity</span> <span id="L40" class="LineNr">40 </span> <span class="Comment"># create two background 'routines' that communicate by a channel</span> -<span id="L41" class="LineNr">41 </span> routine1:num <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='channel.mu.html#L3'>producer</a>, <a href='075channel.mu.html#L47'>sink</a> -<span id="L42" class="LineNr">42 </span> routine2:num <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='channel.mu.html#L22'>consumer</a>, <a href='075channel.mu.html#L43'>source</a> +<span id="L41" class="LineNr">41 </span> routine1:num <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='channel.mu.html#L3'>producer</a>, <a href='075channel.mu.html#L40'>sink</a> +<span id="L42" class="LineNr">42 </span> routine2:num <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='channel.mu.html#L22'>consumer</a>, <a href='075channel.mu.html#L36'>source</a> <span id="L43" class="LineNr">43 </span> wait-for-routine routine1 <span id="L44" class="LineNr">44 </span> wait-for-routine routine2 <span id="L45" class="LineNr">45 </span>] diff --git a/html/chessboard.mu.html b/html/chessboard.mu.html index 1d479289..2efbb576 100644 --- a/html/chessboard.mu.html +++ b/html/chessboard.mu.html @@ -134,11 +134,11 @@ if ('onhashchange' in window) { <span id="L71" class="LineNr"> 71 </span> <span class="Constant">load-inputs</span> <span id="L72" class="LineNr"> 72 </span> <a href='chessboard.mu.html#L67'>board</a>:<a href='chessboard.mu.html#L67'>board</a> <span class="Special"><-</span> <a href='chessboard.mu.html#L190'>initial-position</a> <span id="L73" class="LineNr"> 73 </span> <span class="Comment"># hook up stdin</span> -<span id="L74" class="LineNr"> 74 </span> stdin-in:&:<a href='075channel.mu.html#L43'>source</a>:char, stdin-out:&:<a href='075channel.mu.html#L47'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">10/capacity</span> +<span id="L74" class="LineNr"> 74 </span> stdin-in:&:<a href='075channel.mu.html#L36'>source</a>:char, stdin-out:&:<a href='075channel.mu.html#L40'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">10/capacity</span> <span id="L75" class="LineNr"> 75 </span> <span class="muControl">start-running</span> <a href='084console.mu.html#L73'>send-keys-to-channel</a>, <a href='084console.mu.html#L23'>console</a>, stdin-out, <a href='081print.mu.html#L16'>screen</a> <span id="L76" class="LineNr"> 76 </span> <span class="Comment"># buffer lines in stdin</span> -<span id="L77" class="LineNr"> 77 </span> buffered-stdin-in:&:<a href='075channel.mu.html#L43'>source</a>:char, buffered-stdin-out:&:<a href='075channel.mu.html#L47'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">10/capacity</span> -<span id="L78" class="LineNr"> 78 </span> <span class="muControl">start-running</span> <a href='075channel.mu.html#L408'>buffer-lines</a>, stdin-in, buffered-stdin-out +<span id="L77" class="LineNr"> 77 </span> buffered-stdin-in:&:<a href='075channel.mu.html#L36'>source</a>:char, buffered-stdin-out:&:<a href='075channel.mu.html#L40'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">10/capacity</span> +<span id="L78" class="LineNr"> 78 </span> <span class="muControl">start-running</span> <a href='075channel.mu.html#L400'>buffer-lines</a>, stdin-in, buffered-stdin-out <span id="L79" class="LineNr"> 79 </span> <span class="Delimiter">{</span> <span id="L80" class="LineNr"> 80 </span> print <a href='081print.mu.html#L16'>screen</a>, <span class="Constant">[Stupid text-mode chessboard. White pieces in uppercase; black pieces in lowercase. No checking for legal moves.</span> <span id="L81" class="LineNr"> 81 </span><span class="Constant">]</span> @@ -155,7 +155,7 @@ if ('onhashchange' in window) { <span id="L92" class="LineNr"> 92 </span> <a href='081print.mu.html#L16'>screen</a> <span class="Special"><-</span> print <a href='081print.mu.html#L16'>screen</a>, <span class="Constant">[move: ]</span> <span id="L93" class="LineNr"> 93 </span> m:&:<a href='chessboard.mu.html#L239'>move</a>, quit:bool, error:bool <span class="Special"><-</span> <a href='chessboard.mu.html#L248'>read-move</a> buffered-stdin-in, <a href='081print.mu.html#L16'>screen</a> <span id="L94" class="LineNr"> 94 </span> <span class="muControl">break-if</span> quit, <span class="Constant">+quit</span> -<span id="L95" class="LineNr"> 95 </span> buffered-stdin-in <span class="Special"><-</span> <a href='075channel.mu.html#L312'>clear</a> buffered-stdin-in <span class="Comment"># cleanup after error. todo: test this?</span> +<span id="L95" class="LineNr"> 95 </span> buffered-stdin-in <span class="Special"><-</span> <a href='075channel.mu.html#L304'>clear</a> buffered-stdin-in <span class="Comment"># cleanup after error. todo: test this?</span> <span id="L96" class="LineNr"> 96 </span> <span class="muControl">loop-if</span> error <span id="L97" class="LineNr"> 97 </span> <span class="Delimiter">}</span> <span id="L98" class="LineNr"> 98 </span> <a href='chessboard.mu.html#L67'>board</a> <span class="Special"><-</span> <a href='chessboard.mu.html#L534'>make-move</a> <a href='chessboard.mu.html#L67'>board</a>, m @@ -308,7 +308,7 @@ if ('onhashchange' in window) { <span id="L245" class="LineNr">245 </span>] <span id="L246" class="LineNr">246 </span> <span id="L247" class="LineNr">247 </span><span class="Comment"># prints only error messages to screen</span> -<span id="L248" class="LineNr">248 </span><span class="muRecipe">def</span> <a href='chessboard.mu.html#L248'>read-move</a> stdin:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a><span class="muRecipe"> -> </span>result:&:<a href='chessboard.mu.html#L239'>move</a>, quit?:bool, error?:bool, stdin:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a> [ +<span id="L248" class="LineNr">248 </span><span class="muRecipe">def</span> <a href='chessboard.mu.html#L248'>read-move</a> stdin:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a><span class="muRecipe"> -> </span>result:&:<a href='chessboard.mu.html#L239'>move</a>, quit?:bool, error?:bool, stdin:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a> [ <span id="L249" class="LineNr">249 </span> <span class="Constant">local-scope</span> <span id="L250" class="LineNr">250 </span> <span class="Constant">load-inputs</span> <span id="L251" class="LineNr">251 </span> from-file:num, quit?:bool, error?:bool <span class="Special"><-</span> <a href='chessboard.mu.html#L276'>read-file</a> stdin, <a href='081print.mu.html#L16'>screen</a> @@ -336,7 +336,7 @@ if ('onhashchange' in window) { <span id="L273" class="LineNr">273 </span>] <span id="L274" class="LineNr">274 </span> <span id="L275" class="LineNr">275 </span><span class="Comment"># valid values for file: 0-7</span> -<span id="L276" class="LineNr">276 </span><span class="muRecipe">def</span> <a href='chessboard.mu.html#L276'>read-file</a> stdin:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a><span class="muRecipe"> -> </span>file:num, quit:bool, error:bool, stdin:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a> [ +<span id="L276" class="LineNr">276 </span><span class="muRecipe">def</span> <a href='chessboard.mu.html#L276'>read-file</a> stdin:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a><span class="muRecipe"> -> </span>file:num, quit:bool, error:bool, stdin:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a> [ <span id="L277" class="LineNr">277 </span> <span class="Constant">local-scope</span> <span id="L278" class="LineNr">278 </span> <span class="Constant">load-inputs</span> <span id="L279" class="LineNr">279 </span> c:char, eof?:bool, stdin <span class="Special"><-</span> read stdin @@ -374,7 +374,7 @@ if ('onhashchange' in window) { <span id="L311" class="LineNr">311 </span>] <span id="L312" class="LineNr">312 </span> <span id="L313" class="LineNr">313 </span><span class="Comment"># valid values for rank: 0-7</span> -<span id="L314" class="LineNr">314 </span><span class="muRecipe">def</span> <a href='chessboard.mu.html#L314'>read-rank</a> stdin:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a><span class="muRecipe"> -> </span>rank:num, quit?:bool, error?:bool, stdin:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a> [ +<span id="L314" class="LineNr">314 </span><span class="muRecipe">def</span> <a href='chessboard.mu.html#L314'>read-rank</a> stdin:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a><span class="muRecipe"> -> </span>rank:num, quit?:bool, error?:bool, stdin:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a> [ <span id="L315" class="LineNr">315 </span> <span class="Constant">local-scope</span> <span id="L316" class="LineNr">316 </span> <span class="Constant">load-inputs</span> <span id="L317" class="LineNr">317 </span> c:char, eof?:bool, stdin <span class="Special"><-</span> read stdin @@ -412,7 +412,7 @@ if ('onhashchange' in window) { <span id="L349" class="LineNr">349 </span> <span id="L350" class="LineNr">350 </span><span class="Comment"># read a character from the given channel and check that it's what we expect</span> <span id="L351" class="LineNr">351 </span><span class="Comment"># return true on error</span> -<span id="L352" class="LineNr">352 </span><span class="muRecipe">def</span> <a href='chessboard.mu.html#L352'>expect-from-channel</a> stdin:&:<a href='075channel.mu.html#L43'>source</a>:char, expected:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a><span class="muRecipe"> -> </span>result:bool, stdin:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a> [ +<span id="L352" class="LineNr">352 </span><span class="muRecipe">def</span> <a href='chessboard.mu.html#L352'>expect-from-channel</a> stdin:&:<a href='075channel.mu.html#L36'>source</a>:char, expected:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a><span class="muRecipe"> -> </span>result:bool, stdin:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='081print.mu.html#L16'>screen</a>:&:<a href='081print.mu.html#L16'>screen</a> [ <span id="L353" class="LineNr">353 </span> <span class="Constant">local-scope</span> <span id="L354" class="LineNr">354 </span> <span class="Constant">load-inputs</span> <span id="L355" class="LineNr">355 </span> c:char, eof?:bool, stdin <span class="Special"><-</span> read stdin @@ -428,8 +428,8 @@ if ('onhashchange' in window) { <span id="L365" class="LineNr">365 </span><span class="muScenario">scenario</span> read-move-blocking [ <span id="L366" class="LineNr">366 </span> <span class="Constant">local-scope</span> <span id="L367" class="LineNr">367 </span> assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> -<span id="L368" class="LineNr">368 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">2/capacity</span> -<span id="L369" class="LineNr">369 </span> read-move-routine:num/routine <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='chessboard.mu.html#L248'>read-move</a>, <a href='075channel.mu.html#L43'>source</a>, <a href='081print.mu.html#L16'>screen</a> +<span id="L368" class="LineNr">368 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">2/capacity</span> +<span id="L369" class="LineNr">369 </span> read-move-routine:num/routine <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='chessboard.mu.html#L248'>read-move</a>, <a href='075channel.mu.html#L36'>source</a>, <a href='081print.mu.html#L16'>screen</a> <span id="L370" class="LineNr">370 </span> run [ <span id="L371" class="LineNr">371 </span> <span class="Comment"># 'read-move' is waiting for keypress</span> <span id="L372" class="LineNr">372 </span> wait-for-routine-to-block read-move-routine @@ -438,7 +438,7 @@ if ('onhashchange' in window) { <span id="L375" class="LineNr">375 </span> assert waiting?, <span class="Constant">[ </span> <span id="L376" class="LineNr">376 </span><span class="Constant">F read-move-blocking: routine failed to pause after coming up (before any keys were pressed)]</span> <span id="L377" class="LineNr">377 </span> <span class="Comment"># press 'a'</span> -<span id="L378" class="LineNr">378 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">97/a</span> +<span id="L378" class="LineNr">378 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">97/a</span> <span id="L379" class="LineNr">379 </span> restart read-move-routine <span id="L380" class="LineNr">380 </span> <span class="Comment"># 'read-move' still waiting for keypress</span> <span id="L381" class="LineNr">381 </span> wait-for-routine-to-block read-move-routine @@ -447,7 +447,7 @@ if ('onhashchange' in window) { <span id="L384" class="LineNr">384 </span> assert waiting?, <span class="Constant">[ </span> <span id="L385" class="LineNr">385 </span><span class="Constant">F read-move-blocking: routine failed to pause after rank 'a']</span> <span id="L386" class="LineNr">386 </span> <span class="Comment"># press '2'</span> -<span id="L387" class="LineNr">387 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">50/'2'</span> +<span id="L387" class="LineNr">387 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">50/'2'</span> <span id="L388" class="LineNr">388 </span> restart read-move-routine <span id="L389" class="LineNr">389 </span> <span class="Comment"># 'read-move' still waiting for keypress</span> <span id="L390" class="LineNr">390 </span> wait-for-routine-to-block read-move-routine @@ -456,7 +456,7 @@ if ('onhashchange' in window) { <span id="L393" class="LineNr">393 </span> assert waiting?, <span class="Constant">[ </span> <span id="L394" class="LineNr">394 </span><span class="Constant">F read-move-blocking: routine failed to pause after file 'a2']</span> <span id="L395" class="LineNr">395 </span> <span class="Comment"># press '-'</span> -<span id="L396" class="LineNr">396 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">45/'-'</span> +<span id="L396" class="LineNr">396 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">45/'-'</span> <span id="L397" class="LineNr">397 </span> restart read-move-routine <span id="L398" class="LineNr">398 </span> <span class="Comment"># 'read-move' still waiting for keypress</span> <span id="L399" class="LineNr">399 </span> wait-for-routine-to-block read-move-routine @@ -465,7 +465,7 @@ if ('onhashchange' in window) { <span id="L402" class="LineNr">402 </span> assert waiting?, <span class="Constant">[ </span> <span id="L403" class="LineNr">403 </span><span class="Constant">F read-move-blocking: routine failed to pause after hyphen 'a2-']</span> <span id="L404" class="LineNr">404 </span> <span class="Comment"># press 'a'</span> -<span id="L405" class="LineNr">405 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">97/a</span> +<span id="L405" class="LineNr">405 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">97/a</span> <span id="L406" class="LineNr">406 </span> restart read-move-routine <span id="L407" class="LineNr">407 </span> <span class="Comment"># 'read-move' still waiting for keypress</span> <span id="L408" class="LineNr">408 </span> wait-for-routine-to-block read-move-routine @@ -474,7 +474,7 @@ if ('onhashchange' in window) { <span id="L411" class="LineNr">411 </span> assert waiting?, <span class="Constant">[ </span> <span id="L412" class="LineNr">412 </span><span class="Constant">F read-move-blocking: routine failed to pause after rank 'a2-a']</span> <span id="L413" class="LineNr">413 </span> <span class="Comment"># press '4'</span> -<span id="L414" class="LineNr">414 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">52/'4'</span> +<span id="L414" class="LineNr">414 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">52/'4'</span> <span id="L415" class="LineNr">415 </span> restart read-move-routine <span id="L416" class="LineNr">416 </span> <span class="Comment"># 'read-move' still waiting for keypress</span> <span id="L417" class="LineNr">417 </span> wait-for-routine-to-block read-move-routine @@ -483,7 +483,7 @@ if ('onhashchange' in window) { <span id="L420" class="LineNr">420 </span> assert waiting?, <span class="Constant">[ </span> <span id="L421" class="LineNr">421 </span><span class="Constant">F read-move-blocking: routine failed to pause after file 'a2-a4']</span> <span id="L422" class="LineNr">422 </span> <span class="Comment"># press 'newline'</span> -<span id="L423" class="LineNr">423 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>,<span class="Constant"> 10</span> <span class="Comment"># newline</span> +<span id="L423" class="LineNr">423 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>,<span class="Constant"> 10</span> <span class="Comment"># newline</span> <span id="L424" class="LineNr">424 </span> restart read-move-routine <span id="L425" class="LineNr">425 </span> <span class="Comment"># 'read-move' now completes</span> <span id="L426" class="LineNr">426 </span> wait-for-routine-to-block read-move-routine @@ -501,8 +501,8 @@ if ('onhashchange' in window) { <span id="L438" class="LineNr">438 </span><span class="muScenario">scenario</span> read-move-quit [ <span id="L439" class="LineNr">439 </span> <span class="Constant">local-scope</span> <span id="L440" class="LineNr">440 </span> assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> -<span id="L441" class="LineNr">441 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">2/capacity</span> -<span id="L442" class="LineNr">442 </span> read-move-routine:num <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='chessboard.mu.html#L248'>read-move</a>, <a href='075channel.mu.html#L43'>source</a>, <a href='081print.mu.html#L16'>screen</a> +<span id="L441" class="LineNr">441 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">2/capacity</span> +<span id="L442" class="LineNr">442 </span> read-move-routine:num <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='chessboard.mu.html#L248'>read-move</a>, <a href='075channel.mu.html#L36'>source</a>, <a href='081print.mu.html#L16'>screen</a> <span id="L443" class="LineNr">443 </span> run [ <span id="L444" class="LineNr">444 </span> <span class="Comment"># 'read-move' is waiting for keypress</span> <span id="L445" class="LineNr">445 </span> wait-for-routine-to-block read-move-routine @@ -511,7 +511,7 @@ if ('onhashchange' in window) { <span id="L448" class="LineNr">448 </span> assert waiting?, <span class="Constant">[ </span> <span id="L449" class="LineNr">449 </span><span class="Constant">F read-move-quit: routine failed to pause after coming up (before any keys were pressed)]</span> <span id="L450" class="LineNr">450 </span> <span class="Comment"># press 'q'</span> -<span id="L451" class="LineNr">451 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">113/q</span> +<span id="L451" class="LineNr">451 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">113/q</span> <span id="L452" class="LineNr">452 </span> restart read-move-routine <span id="L453" class="LineNr">453 </span> <span class="Comment"># 'read-move' completes</span> <span id="L454" class="LineNr">454 </span> wait-for-routine-to-block read-move-routine @@ -529,8 +529,8 @@ if ('onhashchange' in window) { <span id="L466" class="LineNr">466 </span><span class="muScenario">scenario</span> read-move-illegal-file [ <span id="L467" class="LineNr">467 </span> <span class="Constant">local-scope</span> <span id="L468" class="LineNr">468 </span> assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> -<span id="L469" class="LineNr">469 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">2/capacity</span> -<span id="L470" class="LineNr">470 </span> read-move-routine:num <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='chessboard.mu.html#L248'>read-move</a>, <a href='075channel.mu.html#L43'>source</a>, <a href='081print.mu.html#L16'>screen</a> +<span id="L469" class="LineNr">469 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">2/capacity</span> +<span id="L470" class="LineNr">470 </span> read-move-routine:num <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='chessboard.mu.html#L248'>read-move</a>, <a href='075channel.mu.html#L36'>source</a>, <a href='081print.mu.html#L16'>screen</a> <span id="L471" class="LineNr">471 </span> run [ <span id="L472" class="LineNr">472 </span> <span class="Comment"># 'read-move' is waiting for keypress</span> <span id="L473" class="LineNr">473 </span> wait-for-routine-to-block read-move-routine @@ -538,7 +538,7 @@ if ('onhashchange' in window) { <span id="L475" class="LineNr">475 </span> waiting?:bool <span class="Special"><-</span> not-equal read-move-state, <span class="Constant">2/discontinued</span> <span id="L476" class="LineNr">476 </span> assert waiting?, <span class="Constant">[ </span> <span id="L477" class="LineNr">477 </span><span class="Constant">F read-move-illegal-file: routine failed to pause after coming up (before any keys were pressed)]</span> -<span id="L478" class="LineNr">478 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">50/'2'</span> +<span id="L478" class="LineNr">478 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">50/'2'</span> <span id="L479" class="LineNr">479 </span> restart read-move-routine <span id="L480" class="LineNr">480 </span> wait-for-routine-to-block read-move-routine <span id="L481" class="LineNr">481 </span> ] @@ -551,8 +551,8 @@ if ('onhashchange' in window) { <span id="L488" class="LineNr">488 </span><span class="muScenario">scenario</span> read-move-illegal-rank [ <span id="L489" class="LineNr">489 </span> <span class="Constant">local-scope</span> <span id="L490" class="LineNr">490 </span> assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> -<span id="L491" class="LineNr">491 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">2/capacity</span> -<span id="L492" class="LineNr">492 </span> read-move-routine:num <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='chessboard.mu.html#L248'>read-move</a>, <a href='075channel.mu.html#L43'>source</a>, <a href='081print.mu.html#L16'>screen</a> +<span id="L491" class="LineNr">491 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">2/capacity</span> +<span id="L492" class="LineNr">492 </span> read-move-routine:num <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='chessboard.mu.html#L248'>read-move</a>, <a href='075channel.mu.html#L36'>source</a>, <a href='081print.mu.html#L16'>screen</a> <span id="L493" class="LineNr">493 </span> run [ <span id="L494" class="LineNr">494 </span> <span class="Comment"># 'read-move' is waiting for keypress</span> <span id="L495" class="LineNr">495 </span> wait-for-routine-to-block read-move-routine @@ -560,8 +560,8 @@ if ('onhashchange' in window) { <span id="L497" class="LineNr">497 </span> waiting?:bool <span class="Special"><-</span> not-equal read-move-state, <span class="Constant">2/discontinued</span> <span id="L498" class="LineNr">498 </span> assert waiting?, <span class="Constant">[ </span> <span id="L499" class="LineNr">499 </span><span class="Constant">F read-move-illegal-rank: routine failed to pause after coming up (before any keys were pressed)]</span> -<span id="L500" class="LineNr">500 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">97/a</span> -<span id="L501" class="LineNr">501 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">97/a</span> +<span id="L500" class="LineNr">500 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">97/a</span> +<span id="L501" class="LineNr">501 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">97/a</span> <span id="L502" class="LineNr">502 </span> restart read-move-routine <span id="L503" class="LineNr">503 </span> wait-for-routine-to-block read-move-routine <span id="L504" class="LineNr">504 </span> ] @@ -574,8 +574,8 @@ if ('onhashchange' in window) { <span id="L511" class="LineNr">511 </span><span class="muScenario">scenario</span> read-move-empty [ <span id="L512" class="LineNr">512 </span> <span class="Constant">local-scope</span> <span id="L513" class="LineNr">513 </span> assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span> -<span id="L514" class="LineNr">514 </span> <a href='075channel.mu.html#L43'>source</a>:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a> <span class="Constant">2/capacity</span> -<span id="L515" class="LineNr">515 </span> read-move-routine:num <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='chessboard.mu.html#L248'>read-move</a>, <a href='075channel.mu.html#L43'>source</a>, <a href='081print.mu.html#L16'>screen</a> +<span id="L514" class="LineNr">514 </span> <a href='075channel.mu.html#L36'>source</a>:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a> <span class="Constant">2/capacity</span> +<span id="L515" class="LineNr">515 </span> read-move-routine:num <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='chessboard.mu.html#L248'>read-move</a>, <a href='075channel.mu.html#L36'>source</a>, <a href='081print.mu.html#L16'>screen</a> <span id="L516" class="LineNr">516 </span> run [ <span id="L517" class="LineNr">517 </span> <span class="Comment"># 'read-move' is waiting for keypress</span> <span id="L518" class="LineNr">518 </span> wait-for-routine-to-block read-move-routine @@ -583,8 +583,8 @@ if ('onhashchange' in window) { <span id="L520" class="LineNr">520 </span> waiting?:bool <span class="Special"><-</span> not-equal read-move-state, <span class="Constant">2/discontinued</span> <span id="L521" class="LineNr">521 </span> assert waiting?, <span class="Constant">[ </span> <span id="L522" class="LineNr">522 </span><span class="Constant">F read-move-empty: routine failed to pause after coming up (before any keys were pressed)]</span> -<span id="L523" class="LineNr">523 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">10/newline</span> -<span id="L524" class="LineNr">524 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> <a href='075channel.mu.html#L47'>sink</a>, <span class="Constant">97/a</span> +<span id="L523" class="LineNr">523 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">10/newline</span> +<span id="L524" class="LineNr">524 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> <a href='075channel.mu.html#L40'>sink</a>, <span class="Constant">97/a</span> <span id="L525" class="LineNr">525 </span> restart read-move-routine <span id="L526" class="LineNr">526 </span> wait-for-routine-to-block read-move-routine <span id="L527" class="LineNr">527 </span> ] diff --git a/html/filesystem.mu.html b/html/filesystem.mu.html index 8a6ec191..56ea3e96 100644 --- a/html/filesystem.mu.html +++ b/html/filesystem.mu.html @@ -64,12 +64,12 @@ if ('onhashchange' in window) { <span id="L5" class="LineNr"> 5 </span> <span id="L6" class="LineNr"> 6 </span><span class="muRecipe">def</span> <a href='filesystem.mu.html#L6'>main</a> [ <span id="L7" class="LineNr"> 7 </span> <span class="Constant">local-scope</span> -<span id="L8" class="LineNr"> 8 </span> source-file:&:<a href='075channel.mu.html#L43'>source</a>:char <span class="Special"><-</span> <a href='088file.mu.html#L21'>start-reading</a> <span class="Constant">0/real-filesystem</span>, <span class="Constant">[/tmp/mu-x]</span> -<span id="L9" class="LineNr"> 9 </span> sink-file:&:<a href='075channel.mu.html#L47'>sink</a>:char, write-routine:num <span class="Special"><-</span> <a href='088file.mu.html#L105'>start-writing</a> <span class="Constant">0/real-filesystem</span>, <span class="Constant">[/tmp/mu-y]</span> +<span id="L8" class="LineNr"> 8 </span> source-file:&:<a href='075channel.mu.html#L36'>source</a>:char <span class="Special"><-</span> <a href='088file.mu.html#L21'>start-reading</a> <span class="Constant">0/real-filesystem</span>, <span class="Constant">[/tmp/mu-x]</span> +<span id="L9" class="LineNr"> 9 </span> sink-file:&:<a href='075channel.mu.html#L40'>sink</a>:char, write-routine:num <span class="Special"><-</span> <a href='088file.mu.html#L105'>start-writing</a> <span class="Constant">0/real-filesystem</span>, <span class="Constant">[/tmp/mu-y]</span> <span id="L10" class="LineNr">10 </span> <span class="Delimiter">{</span> <span id="L11" class="LineNr">11 </span> c:char, done?:bool, source-file <span class="Special"><-</span> read source-file <span id="L12" class="LineNr">12 </span> <span class="muControl">break-if</span> done? -<span id="L13" class="LineNr">13 </span> sink-file <span class="Special"><-</span> <a href='075channel.mu.html#L67'>write</a> sink-file, c +<span id="L13" class="LineNr">13 </span> sink-file <span class="Special"><-</span> <a href='075channel.mu.html#L60'>write</a> sink-file, c <span id="L14" class="LineNr">14 </span> <span class="muControl"> loop</span> <span id="L15" class="LineNr">15 </span> <span class="Delimiter">}</span> <span id="L16" class="LineNr">16 </span> close sink-file diff --git a/html/http-client.mu.html b/html/http-client.mu.html index d44e5f97..a8f5abfb 100644 --- a/html/http-client.mu.html +++ b/html/http-client.mu.html @@ -62,7 +62,7 @@ if ('onhashchange' in window) { <span id="L3" class="LineNr"> 3 </span><span class="muRecipe">def</span> <a href='http-client.mu.html#L3'>main</a> [ <span id="L4" class="LineNr"> 4 </span> <span class="Constant">local-scope</span> <span id="L5" class="LineNr"> 5 </span> $print <span class="Constant">[aaa]</span> <span class="Constant">10/newline</span> -<span id="L6" class="LineNr"> 6 </span> google:&:<a href='075channel.mu.html#L43'>source</a>:char <span class="Special"><-</span> <a href='092socket.mu.html#L69'>start-reading-from-network</a> <span class="Constant">0/real-resources</span>, <span class="Constant">[google.com/]</span> +<span id="L6" class="LineNr"> 6 </span> google:&:<a href='075channel.mu.html#L36'>source</a>:char <span class="Special"><-</span> <a href='092socket.mu.html#L69'>start-reading-from-network</a> <span class="Constant">0/real-resources</span>, <span class="Constant">[google.com/]</span> <span id="L7" class="LineNr"> 7 </span> $print <span class="Constant">[bbb]</span> <span class="Constant">10/newline</span> <span id="L8" class="LineNr"> 8 </span> n:num <span class="Special"><-</span> copy<span class="Constant"> 0</span> <span id="L9" class="LineNr"> 9 </span> buf:&:<a href='061text.mu.html#L120'>buffer</a>:char <span class="Special"><-</span> <a href='061text.mu.html#L125'>new-buffer</a><span class="Constant"> 30</span> diff --git a/html/http-server.mu.html b/html/http-server.mu.html index b8ff0d97..01243ab0 100644 --- a/html/http-server.mu.html +++ b/html/http-server.mu.html @@ -71,9 +71,9 @@ if ('onhashchange' in window) { <span id="L13" class="LineNr">13 </span> $print <span class="Constant">[Mu socket creation returned ]</span>, socket, <span class="Constant">10/newline</span> <span id="L14" class="LineNr">14 </span> <span class="muControl">return-unless</span> socket <span id="L15" class="LineNr">15 </span> session:num <span class="Special"><-</span> $accept socket -<span id="L16" class="LineNr">16 </span> contents:&:<a href='075channel.mu.html#L43'>source</a>:char, <a href='075channel.mu.html#L47'>sink</a>:&:<a href='075channel.mu.html#L47'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L51'>new-channel</a><span class="Constant"> 30</span> -<span id="L17" class="LineNr">17 </span> <a href='075channel.mu.html#L47'>sink</a> <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='092socket.mu.html#L104'>receive-from-socket</a> session, <a href='075channel.mu.html#L47'>sink</a> -<span id="L18" class="LineNr">18 </span> query:text <span class="Special"><-</span> <a href='075channel.mu.html#L507'>drain</a> contents +<span id="L16" class="LineNr">16 </span> contents:&:<a href='075channel.mu.html#L36'>source</a>:char, <a href='075channel.mu.html#L40'>sink</a>:&:<a href='075channel.mu.html#L40'>sink</a>:char <span class="Special"><-</span> <a href='075channel.mu.html#L44'>new-channel</a><span class="Constant"> 30</span> +<span id="L17" class="LineNr">17 </span> <a href='075channel.mu.html#L40'>sink</a> <span class="Special"><-</span> <span class="muControl">start-running</span> <a href='092socket.mu.html#L104'>receive-from-socket</a> session, <a href='075channel.mu.html#L40'>sink</a> +<span id="L18" class="LineNr">18 </span> query:text <span class="Special"><-</span> <a href='075channel.mu.html#L499'>drain</a> contents <span id="L19" class="LineNr">19 </span> $print <span class="Constant">[Done reading from socket.]</span>, <span class="Constant">10/newline</span> <span id="L20" class="LineNr">20 </span> <a href='092socket.mu.html#L132'>write-to-socket</a> session, <span class="Constant">[HTTP/1.0 200 OK</span> <span id="L21" class="LineNr">21 </span><span class="Constant">Content-type: text/plain</span> diff --git a/html/real-files.mu.html b/html/real-files.mu.html index c72cb608..e8d9da2d 100644 --- a/html/real-files.mu.html +++ b/html/real-files.mu.html @@ -69,7 +69,7 @@ if ('onhashchange' in window) { <span id="L12" class="LineNr">12 </span> f <span class="Special"><-</span> $close-file f <span id="L13" class="LineNr">13 </span> $print <span class="Constant">[file after closing: ]</span>, f, <span class="Constant">10/newline</span> <span id="L14" class="LineNr">14 </span> f <span class="Special"><-</span> $open-file-for-writing <span class="Constant">[/tmp/mu-y]</span> -<span id="L15" class="LineNr">15 </span> $print <span class="Constant">[file to <a href='075channel.mu.html#L67'>write</a> to: ]</span>, f, <span class="Constant">10/newline</span> +<span id="L15" class="LineNr">15 </span> $print <span class="Constant">[file to <a href='075channel.mu.html#L60'>write</a> to: ]</span>, f, <span class="Constant">10/newline</span> <span id="L16" class="LineNr">16 </span> $write-to-file f, c <span id="L17" class="LineNr">17 </span> f <span class="Special"><-</span> $close-file f <span id="L18" class="LineNr">18 </span>] diff --git a/update_html b/update_html index 651b287f..d525ee8d 100755 --- a/update_html +++ b/update_html @@ -16,7 +16,7 @@ process() { convert_html() { vim -c "set number" -c TOhtml -c write -c qall $1 - sed -i 's,<title>\~/mu/,<title>Mu - ,' $1.html + sed -i 's,<title>.*/mu/,<title>Mu - ,' $1.html sed -i 's,\.html</title>,</title>,' $1.html sed -i 's/^\* { \(.*\) }/* { font-size: 12pt; \1 }/g' $1.html sed -i 's/^body { \(.*\) }/body { font-size: 12pt; \1 }/g' $1.html |