From ffc9e66b3505990009e47b461eb03d3eb1635258 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sun, 5 Nov 2017 02:00:26 -0800 Subject: 4109 --- html/010vm.cc.html | 16 +- html/011load.cc.html | 4 +- html/014literal_string.cc.html | 12 +- html/017parse_tree.cc.html | 2 +- html/018type_abbreviations.cc.html | 2 +- html/020run.cc.html | 4 +- html/021check_instruction.cc.html | 18 +- html/022arithmetic.cc.html | 2 +- html/026call.cc.html | 6 +- html/028call_return.cc.html | 2 +- html/030container.cc.html | 16 +- html/031merge.cc.html | 4 +- html/032array.cc.html | 24 +- html/033exclusive_container.cc.html | 10 +- html/034address.cc.html | 64 +- html/035lookup.cc.html | 110 ++-- html/036refcount.cc.html | 258 ++++---- html/037abandon.cc.html | 118 ++-- html/038new_text.cc.html | 16 +- html/043space.cc.html | 947 ++++++++++++++-------------- html/044space_surround.cc.html | 8 +- html/045closure_name.cc.html | 4 +- html/046check_type_by_name.cc.html | 2 +- html/050scenario.cc.html | 22 +- html/053recipe_header.cc.html | 10 +- html/054static_dispatch.cc.html | 8 +- html/055shape_shifting_container.cc.html | 38 +- html/056shape_shifting_recipe.cc.html | 4 +- html/057immutable.cc.html | 2 +- html/062convert_ingredients_to_text.cc.html | 8 +- html/069hash.cc.html | 12 +- html/071deep_copy.cc.html | 10 +- html/072recipe.cc.html | 6 +- html/073scheduler.cc.html | 2 +- html/074wait.cc.html | 6 +- html/076continuation.cc.html | 486 ++++++++------ html/082scenario_screen.cc.html | 2 +- html/085scenario_console.cc.html | 16 +- html/089scenario_filesystem.cc.html | 18 +- html/099hardware_checks.cc.html | 6 +- html/101run_sandboxed.cc.html | 8 +- 41 files changed, 1222 insertions(+), 1091 deletions(-) diff --git a/html/010vm.cc.html b/html/010vm.cc.html index 0f2aa4a5..c37b89f9 100644 --- a/html/010vm.cc.html +++ b/html/010vm.cc.html @@ -198,8 +198,8 @@ if ('onhashchange' in window) { 134 type_ordinal number = put(Type_ordinal, "number", Next_type_ordinal++); 135 get_or_insert(Type, number).name = "number"; 136 put(Type_ordinal, "location", number); // synonym of number to indicate we only care about its size -137 type_ordinal address = put(Type_ordinal, "address", Next_type_ordinal++); -138 get_or_insert(Type, address).name = "address"; +137 type_ordinal address = put(Type_ordinal, "address", Next_type_ordinal++); +138 get_or_insert(Type, address).name = "address"; 139 type_ordinal boolean = put(Type_ordinal, "boolean", Next_type_ordinal++); 140 get_or_insert(Type, boolean).name = "boolean"; 141 type_ordinal character = put(Type_ordinal, "character", Next_type_ordinal++); @@ -498,32 +498,32 @@ if ('onhashchange' in window) { 434 CHECK(!(*b.type < *a.type)); 435 } 436 void test_compare_atom_with_non_atom() { -437 reagent a("a:address:number"), b("b:boolean"); +437 reagent a("a:address:number"), b("b:boolean"); 438 CHECK(!(*a.type < *b.type)); 439 CHECK(*b.type < *a.type); 440 } 441 void test_compare_lists_with_identical_structure() { -442 reagent a("a:address:address"), b("b:address:boolean"); +442 reagent a("a:address:address"), b("b:address:boolean"); 443 CHECK(*a.type < *b.type); 444 CHECK(!(*b.type < *a.type)); 445 } 446 void test_compare_identical_lists() { -447 reagent a("a:address:boolean"), b("b:address:boolean"); +447 reagent a("a:address:boolean"), b("b:address:boolean"); 448 CHECK(!(*a.type < *b.type)); 449 CHECK(!(*b.type < *a.type)); 450 } 451 void test_compare_list_with_extra_element() { -452 reagent a("a:address:address"), b("b:address:address:number"); +452 reagent a("a:address:address"), b("b:address:address:number"); 453 CHECK(*a.type < *b.type); 454 CHECK(!(*b.type < *a.type)); 455 } 456 void test_compare_list_with_smaller_left_but_larger_right() { -457 reagent a("a:address:number"), b("b:character:array"); +457 reagent a("a:address:number"), b("b:character:array"); 458 CHECK(*a.type < *b.type); 459 CHECK(!(*b.type < *a.type)); 460 } 461 void test_compare_list_with_smaller_left_but_larger_right_identical_types() { -462 reagent a("a:address:boolean"), b("b:boolean:address"); +462 reagent a("a:address:boolean"), b("b:boolean:address"); 463 CHECK(*a.type < *b.type); 464 CHECK(!(*b.type < *a.type)); 465 } diff --git a/html/011load.cc.html b/html/011load.cc.html index 79e5215c..9a6ec529 100644 --- a/html/011load.cc.html +++ b/html/011load.cc.html @@ -400,7 +400,7 @@ if ('onhashchange' in window) { 336 337 :(scenario parse_multiple_types) 338 def main [ -339 1:number, 2:address:number <- copy 23, 4:number +339 1:number, 2:address:number <- copy 23, 4:number 340 ] 341 +parse: instruction: copy 342 +parse: ingredient: {23: "literal"} @@ -410,7 +410,7 @@ if ('onhashchange' in window) { 346 347 :(scenario parse_properties) 348 def main [ -349 1:address:number/lookup <- copy 23 +349 1:address:number/lookup <- copy 23 350 ] 351 +parse: product: {1: ("address" "number"), "lookup": ()} 352 diff --git a/html/014literal_string.cc.html b/html/014literal_string.cc.html index 508b4862..067f1ca4 100644 --- a/html/014literal_string.cc.html +++ b/html/014literal_string.cc.html @@ -72,13 +72,13 @@ if ('onhashchange' in window) { 9 :(scenarios load) 10 :(scenario string_literal) 11 def main [ - 12 1:address:array:character <- copy [abc def] + 12 1:address:array:character <- copy [abc def] 13 ] 14 +parse: ingredient: {"abc def": "literal-string"} 15 16 :(scenario string_literal_with_colons) 17 def main [ - 18 1:address:array:character <- copy [abc:def/ghi] + 18 1:address:array:character <- copy [abc:def/ghi] 19 ] 20 +parse: ingredient: {"abc:def/ghi": "literal-string"} 21 @@ -232,26 +232,26 @@ if ('onhashchange' in window) { 169 170 :(scenario string_literal_nested) 171 def main [ -172 1:address:array:character <- copy [abc [def]] +172 1:address:array:character <- copy [abc [def]] 173 ] 174 +parse: ingredient: {"abc [def]": "literal-string"} 175 176 :(scenario string_literal_escaped) 177 def main [ -178 1:address:array:character <- copy [abc \[def] +178 1:address:array:character <- copy [abc \[def] 179 ] 180 +parse: ingredient: {"abc [def": "literal-string"} 181 182 :(scenario string_literal_escaped_twice) 183 def main [ -184 1:address:array:character <- copy [ +184 1:address:array:character <- copy [ 185 abc \\[def] 186 ] 187 +parse: ingredient: {"\nabc \[def": "literal-string"} 188 189 :(scenario string_literal_and_comment) 190 def main [ -191 1:address:array:character <- copy [abc] # comment +191 1:address:array:character <- copy [abc] # comment 192 ] 193 +parse: --- defining main 194 +parse: instruction: copy diff --git a/html/017parse_tree.cc.html b/html/017parse_tree.cc.html index 31ae7e61..cb0e91da 100644 --- a/html/017parse_tree.cc.html +++ b/html/017parse_tree.cc.html @@ -148,7 +148,7 @@ if ('onhashchange' in window) { 84 :(scenario dilated_reagent_with_type_tree) 85 % Hide_errors = true; // 'map' isn't defined yet 86 def main [ - 87 {1: (foo (address array character) (bar number))} <- copy 34 + 87 {1: (foo (address array character) (bar number))} <- copy 34 88 ] 89 # just to avoid errors 90 container foo [ diff --git a/html/018type_abbreviations.cc.html b/html/018type_abbreviations.cc.html index c7103cb5..dd6954b0 100644 --- a/html/018type_abbreviations.cc.html +++ b/html/018type_abbreviations.cc.html @@ -156,7 +156,7 @@ if ('onhashchange' in window) { 91 +error: 'type' conflict: 'foo' defined as both 'bar' and 'baz' 92 93 :(scenario type_abbreviation_for_compound) - 94 type foo = address:number + 94 type foo = address:number 95 def main [ 96 a:foo <- copy 0 97 ] diff --git a/html/020run.cc.html b/html/020run.cc.html index ad332815..9ed83089 100644 --- a/html/020run.cc.html +++ b/html/020run.cc.html @@ -362,7 +362,7 @@ if ('onhashchange' in window) { 295 int size = size_of(x); 296 for (int offset = 0; offset < size; ++offset) { 297 ¦ double val = get_or_insert(Memory, x.value+offset); -298 ¦ trace(9999, "mem") << "location " << x.value+offset << " is " << no_scientific(val) << end(); +298 ¦ trace("mem") << "location " << x.value+offset << " is " << no_scientific(val) << end(); 299 ¦ result.push_back(val); 300 } 301 return result; @@ -389,7 +389,7 @@ if ('onhashchange' in window) { 322 // End write_memory(x) Special-cases 323 for (int offset = 0; offset < SIZE(data); ++offset) { 324 ¦ assert(x.value+offset > 0); -325 ¦ trace(9999, "mem") << "storing " << no_scientific(data.at(offset)) << " in location " << x.value+offset << end(); +325 ¦ trace("mem") << "storing " << no_scientific(data.at(offset)) << " in location " << x.value+offset << end(); 326 ¦ put(Memory, x.value+offset, data.at(offset)); 327 } 328 } diff --git a/html/021check_instruction.cc.html b/html/021check_instruction.cc.html index f4f738ab..8c0e076e 100644 --- a/html/021check_instruction.cc.html +++ b/html/021check_instruction.cc.html @@ -130,14 +130,14 @@ if ('onhashchange' in window) { 67 :(scenario write_scalar_to_address_disallowed) 68 % Hide_errors = true; 69 def main [ - 70 1:address:num <- copy 34 + 70 1:address:num <- copy 34 71 ] - 72 +error: main: can't copy '34' to '1:address:num'; types don't match + 72 +error: main: can't copy '34' to '1:address:num'; types don't match 73 74 :(scenario write_address_to_number_allowed) 75 def main [ - 76 1:address:num <- copy 12/unsafe - 77 2:num <- copy 1:address:num + 76 1:address:num <- copy 12/unsafe + 77 2:num <- copy 1:address:num 78 ] 79 +mem: storing 12 in location 2 80 $error: 0 @@ -145,10 +145,10 @@ if ('onhashchange' in window) { 82 :(scenario write_address_to_character_disallowed) 83 % Hide_errors = true; 84 def main [ - 85 1:address:num <- copy 12/unsafe - 86 2:char <- copy 1:address:num + 85 1:address:num <- copy 12/unsafe + 86 2:char <- copy 1:address:num 87 ] - 88 +error: main: can't copy '1:address:num' to '2:char'; types don't match + 88 +error: main: can't copy '1:address:num' to '2:char'; types don't match 89 90 :(scenario write_boolean_to_number_allowed) 91 def main [ @@ -239,10 +239,10 @@ if ('onhashchange' in window) { 176 void test_type_abbreviations_match_raw_types() { 177 put(Type_abbreviations, "text", new_type_tree("address:array:character")); 178 // a has type (address buffer (address array character)) -179 reagent a("a:address:buffer:text"); +179 reagent a("a:address:buffer:text"); 180 expand_type_abbreviations(a.type); 181 // b has type (address buffer address array character) -182 reagent b("b:address:buffer:address:array:character"); +182 reagent b("b:address:buffer:address:array:character"); 183 CHECK(types_strictly_match(a, b)); 184 delete Type_abbreviations["text"]; 185 put(Type_abbreviations, "text", NULL); diff --git a/html/022arithmetic.cc.html b/html/022arithmetic.cc.html index e8f8eb5c..3e0d1aff 100644 --- a/html/022arithmetic.cc.html +++ b/html/022arithmetic.cc.html @@ -128,7 +128,7 @@ if ('onhashchange' in window) { 64 :(scenario add_checks_return_type) 65 % Hide_errors = true; 66 def main [ - 67 1:address:num <- add 2, 2 + 67 1:address:num <- add 2, 2 68 ] 69 +error: main: 'add' should yield a number, but got '1:address:num' 70 diff --git a/html/026call.cc.html b/html/026call.cc.html index ae15c156..096383c6 100644 --- a/html/026call.cc.html +++ b/html/026call.cc.html @@ -126,7 +126,7 @@ if ('onhashchange' in window) { 60 routine::routine(recipe_ordinal r) { 61 if (Trace_stream) { 62 ¦ ++Trace_stream->callstack_depth; - 63 ¦ trace(9999, "trace") << "new routine; incrementing callstack depth to " << Trace_stream->callstack_depth << end(); + 63 ¦ trace("trace") << "new routine; incrementing callstack depth to " << Trace_stream->callstack_depth << end(); 64 ¦ assert(Trace_stream->callstack_depth < 9000); // 9998-101 plus cushion 65 } 66 calls.push_front(call(r)); @@ -209,7 +209,7 @@ if ('onhashchange' in window) { 143 ¦ // not a primitive; look up the book of recipes 144 ¦ if (Trace_stream) { 145 ¦ ¦ ++Trace_stream->callstack_depth; -146 ¦ ¦ trace(9999, "trace") << "incrementing callstack depth to " << Trace_stream->callstack_depth << end(); +146 ¦ ¦ trace("trace") << "incrementing callstack depth to " << Trace_stream->callstack_depth << end(); 147 ¦ ¦ assert(Trace_stream->callstack_depth < 9000); // 9998-101 plus cushion 148 ¦ } 149 ¦ const call& caller_frame = current_call(); @@ -259,7 +259,7 @@ if ('onhashchange' in window) { 193 while (current_step_index() >= SIZE(Current_routine->steps())) { 194 // Falling Through End Of Recipe 195 if (Trace_stream) { -196 ¦ trace(9999, "trace") << "fall-through: exiting " << current_recipe_name() << "; decrementing callstack depth from " << Trace_stream->callstack_depth << end(); +196 ¦ trace("trace") << "fall-through: exiting " << current_recipe_name() << "; decrementing callstack depth from " << Trace_stream->callstack_depth << end(); 197 ¦ --Trace_stream->callstack_depth; 198 ¦ assert(Trace_stream->callstack_depth >= 0); 199 } diff --git a/html/028call_return.cc.html b/html/028call_return.cc.html index dfbe030e..b5a3306c 100644 --- a/html/028call_return.cc.html +++ b/html/028call_return.cc.html @@ -100,7 +100,7 @@ if ('onhashchange' in window) { 37 case RETURN: { 38 // Begin Return 39 if (Trace_stream) { - 40 ¦ trace(9999, "trace") << current_instruction().name << ": decrementing callstack depth from " << Trace_stream->callstack_depth << end(); + 40 ¦ trace("trace") << current_instruction().name << ": decrementing callstack depth from " << Trace_stream->callstack_depth << end(); 41 ¦ --Trace_stream->callstack_depth; 42 ¦ if (Trace_stream->callstack_depth < 0) { 43 ¦ ¦ Current_routine->calls.clear(); diff --git a/html/030container.cc.html b/html/030container.cc.html index 49fcfbd2..4008d4bd 100644 --- a/html/030container.cc.html +++ b/html/030container.cc.html @@ -390,7 +390,7 @@ if ('onhashchange' in window) { 323 // define a container containing an address to itself 324 run("container foo [\n" 325 ¦ ¦ " x:num\n" -326 ¦ ¦ " y:address:foo\n" +326 ¦ ¦ " y:address:foo\n" 327 ¦ ¦ "]\n"); 328 reagent r("x:foo"); 329 compute_container_sizes(r, ""); @@ -402,7 +402,7 @@ if ('onhashchange' in window) { 335 reagent container("x:point"); 336 CHECK(!contains_key(Container_metadata, container.type)); 337 // scanning an address to the container precomputes the size of the container -338 reagent r("x:address:point"); +338 reagent r("x:address:point"); 339 compute_container_sizes(r, ""); 340 CHECK(contains_key(Container_metadata, container.type)); 341 CHECK_EQ(get(Container_metadata, container.type).size, 2); @@ -542,7 +542,7 @@ if ('onhashchange' in window) { 475 12:num <- copy 34 476 13:num <- copy 35 477 14:num <- copy 36 -478 15:address:num <- get 12:point-number/raw, 1:offset +478 15:address:num <- get 12:point-number/raw, 1:offset 479 ] 480 +error: main: 'get 12:point-number/raw, 1:offset' should write to number but '15' has type (address number) 481 @@ -636,14 +636,14 @@ if ('onhashchange' in window) { 569 // Update PUT base_type in Run 570 int offset = ingredients.at(1).at(0); 571 if (offset < 0 || offset >= SIZE(get(Type, base_type->value).elements)) break; // copied from Check above -572 int address = base_address + base.metadata.offset.at(offset); -573 trace(9998, "run") << "address to copy to is " << address << end(); +572 int address = base_address + base.metadata.offset.at(offset); +573 trace(9998, "run") << "address to copy to is " << address << end(); 574 // optimization: directly write the element rather than updating 'product' 575 // and writing the entire container 576 // Write Memory in PUT in Run 577 write_products = false; 578 for (int i = 0; i < SIZE(ingredients.at(2)); ++i) { -579 ¦ trace(9999, "mem") << "storing " << no_scientific(ingredients.at(2).at(i)) << " in location " << address+i << end(); +579 ¦ trace("mem") << "storing " << no_scientific(ingredients.at(2).at(i)) << " in location " << address+i << end(); 580 ¦ put(Memory, address+i, ingredients.at(2).at(i)); 581 } 582 break; @@ -739,7 +739,7 @@ if ('onhashchange' in window) { 672 ¦ ¦ || get(Type_ordinal, name) == 0) { 673 ¦ put(Type_ordinal, name, Next_type_ordinal++); 674 } -675 trace(9999, "parse") << "type number: " << get(Type_ordinal, name) << end(); +675 trace("parse") << "type number: " << get(Type_ordinal, name) << end(); 676 skip_bracket(in, "'"+command+"' must begin with '['"); 677 type_info& info = get_or_insert(Type, get(Type_ordinal, name)); 678 if (info.Num_calls_to_transform_all_at_first_definition == -1) { @@ -938,7 +938,7 @@ if ('onhashchange' in window) { 871 872 :(scenario container_with_compound_field_type) 873 container foo [ -874 {x: (address array (address array character))} +874 {x: (address array (address array character))} 875 ] 876 $error: 0 877 diff --git a/html/031merge.cc.html b/html/031merge.cc.html index ff2a2334..dcab8062 100644 --- a/html/031merge.cc.html +++ b/html/031merge.cc.html @@ -210,7 +210,7 @@ if ('onhashchange' in window) { 145 state.data.push(merge_check_point(product, 0)); 146 while (true) { 147 ¦ assert(!state.data.empty()); -148 ¦ trace(9999, "transform") << ingredient_index << " vs " << SIZE(ingredients) << end(); +148 ¦ trace("transform") << ingredient_index << " vs " << SIZE(ingredients) << end(); 149 ¦ if (ingredient_index >= SIZE(ingredients)) { 150 ¦ ¦ raise << maybe(caller.name) << "too few ingredients in '" << to_original_string(inst) << "'\n" << end(); 151 ¦ ¦ return; @@ -226,7 +226,7 @@ if ('onhashchange' in window) { 161 ¦ ¦ ¦ if (state.data.top().container_element_index == 0 && types_coercible(container, inst.ingredients.at(ingredient_index))) 162 ¦ ¦ ¦ ¦ return; 163 ¦ ¦ ¦ const reagent& expected_ingredient = element_type(container.type, state.data.top().container_element_index); -164 ¦ ¦ ¦ trace(9999, "transform") << "checking container " << to_string(container) << " || " << to_string(expected_ingredient) << " vs ingredient " << ingredient_index << end(); +164 ¦ ¦ ¦ trace("transform") << "checking container " << to_string(container) << " || " << to_string(expected_ingredient) << " vs ingredient " << ingredient_index << end(); 165 ¦ ¦ ¦ // if the current element is the ingredient we expect, move on to the next element/ingredient 166 ¦ ¦ ¦ if (types_coercible(expected_ingredient, ingredients.at(ingredient_index))) { 167 ¦ ¦ ¦ ¦ ++ingredient_index; diff --git a/html/032array.cc.html b/html/032array.cc.html index 82126414..6e0fdf4a 100644 --- a/html/032array.cc.html +++ b/html/032array.cc.html @@ -122,7 +122,7 @@ if ('onhashchange' in window) { 57 ¦ array_length_from_type = array_length_from_type->left; 58 int array_length = to_integer(array_length_from_type->name); 59 // initialize array length, so that size_of will work - 60 trace(9999, "mem") << "storing " << array_length << " in location " << base_address << end(); + 60 trace("mem") << "storing " << array_length << " in location " << base_address << end(); 61 put(Memory, base_address, array_length); // in array elements 62 int size = size_of(product); // in locations 63 trace(9998, "run") << "creating array of size " << size << end(); @@ -289,7 +289,7 @@ if ('onhashchange' in window) { 224 reagent container("x:point"); 225 CHECK(!contains_key(Container_metadata, container.type)); 226 // scanning an address to an array of the container precomputes the size of the container -227 reagent r("x:address:array:point"); +227 reagent r("x:address:array:point"); 228 compute_container_sizes(r, ""); 229 CHECK(contains_key(Container_metadata, container.type)); 230 CHECK_EQ(get(Container_metadata, container.type).size, 2); @@ -313,7 +313,7 @@ if ('onhashchange' in window) { 248 reagent container("x:point"); 249 int old_size = SIZE(Container_metadata); 250 // scanning an address to an array of the container precomputes the size of the container -251 reagent r("x:address:array:point:10"); +251 reagent r("x:address:array:point:10"); 252 compute_container_sizes(r, ""); 253 CHECK(contains_key(Container_metadata, container.type)); 254 CHECK_EQ(get(Container_metadata, container.type).size, 2); @@ -326,7 +326,7 @@ if ('onhashchange' in window) { 261 reagent container("x:point"); 262 int old_size = SIZE(Container_metadata); 263 // scanning repeated address and array types modifying the container precomputes the size of the container -264 reagent r("x:address:array:address:array:point:10"); +264 reagent r("x:address:array:address:array:point:10"); 265 compute_container_sizes(r, ""); 266 CHECK(contains_key(Container_metadata, container.type)); 267 CHECK_EQ(get(Container_metadata, container.type).size, 2); @@ -339,7 +339,7 @@ if ('onhashchange' in window) { 274 reagent container("x:point"); 275 int old_size = SIZE(Container_metadata); 276 // scanning address to array with a typo -277 reagent r("x:address:array:adress:number"); +277 reagent r("x:address:array:adress:number"); 278 compute_container_sizes(r, ""); // should not crash 279 // no non-container types precomputed 280 CHECK_EQ(SIZE(Container_metadata), old_size); @@ -359,11 +359,11 @@ if ('onhashchange' in window) { 294 295 :(scenario index_compound_element) 296 def main [ -297 {1: (array (address number) 3)} <- create-array +297 {1: (array (address number) 3)} <- create-array 298 2:num <- copy 14 299 3:num <- copy 15 300 4:num <- copy 16 -301 5:address:num <- index {1: (array (address number) 3)}, 0 +301 5:address:num <- index {1: (array (address number) 3)}, 0 302 ] 303 +mem: storing 14 in location 5 304 @@ -416,7 +416,7 @@ if ('onhashchange' in window) { 351 reagent/*copy*/ base = current_instruction().ingredients.at(0); 352 // Update INDEX base in Run 353 int base_address = base.value; -354 trace(9998, "run") << "base address is " << base_address << end(); +354 trace(9998, "run") << "base address is " << base_address << end(); 355 if (base_address == 0) { 356 ¦ raise << maybe(current_recipe_name()) << "tried to access location 0 in '" << to_original_string(current_instruction()) << "'\n" << end(); 357 ¦ break; @@ -477,7 +477,7 @@ if ('onhashchange' in window) { 412 put(Memory, 2, 14); 413 put(Memory, 3, 15); 414 put(Memory, 4, 16); -415 reagent x("1:array:address:num"); // 3 types, but not a static array +415 reagent x("1:array:address:num"); // 3 types, but not a static array 416 populate_value(x); 417 CHECK_EQ(array_length(x), 3); 418 } @@ -618,15 +618,15 @@ if ('onhashchange' in window) { 553 ¦ raise << maybe(current_recipe_name()) << "invalid index " << no_scientific(index_val.at(0)) << " in '" << to_original_string(current_instruction()) << "'\n" << end(); 554 ¦ break; 555 } -556 int address = base_address + /*skip length*/1 + index_val.at(0)*size_of(array_element(base.type)); -557 trace(9998, "run") << "address to copy to is " << address << end(); +556 int address = base_address + /*skip length*/1 + index_val.at(0)*size_of(array_element(base.type)); +557 trace(9998, "run") << "address to copy to is " << address << end(); 558 // optimization: directly write the element rather than updating 'product' 559 // and writing the entire array 560 write_products = false; 561 vector<double> value = read_memory(current_instruction().ingredients.at(2)); 562 // Write Memory in PUT_INDEX in Run 563 for (int i = 0; i < SIZE(value); ++i) { -564 ¦ trace(9999, "mem") << "storing " << no_scientific(value.at(i)) << " in location " << address+i << end(); +564 ¦ trace("mem") << "storing " << no_scientific(value.at(i)) << " in location " << address+i << end(); 565 ¦ put(Memory, address+i, value.at(i)); 566 } 567 break; diff --git a/html/033exclusive_container.cc.html b/html/033exclusive_container.cc.html index 88d8d090..ae11dfd7 100644 --- a/html/033exclusive_container.cc.html +++ b/html/033exclusive_container.cc.html @@ -228,19 +228,19 @@ if ('onhashchange' in window) { 163 write_products = false; 164 if (tag == static_cast<int>(get_or_insert(Memory, base_address))) { 165 ¦ const reagent& variant = variant_type(base, tag); -166 ¦ trace(9999, "mem") << "storing 1 in location " << status.value << end(); +166 ¦ trace("mem") << "storing 1 in location " << status.value << end(); 167 ¦ put(Memory, status.value, 1); 168 ¦ if (!is_dummy(product)) { 169 ¦ ¦ // Write Memory in Successful MAYBE_CONVERT in Run 170 ¦ ¦ for (int i = 0; i < size_of(variant); ++i) { 171 ¦ ¦ ¦ double val = get_or_insert(Memory, base_address+/*skip tag*/1+i); -172 ¦ ¦ ¦ trace(9999, "mem") << "storing " << no_scientific(val) << " in location " << product.value+i << end(); +172 ¦ ¦ ¦ trace("mem") << "storing " << no_scientific(val) << " in location " << product.value+i << end(); 173 ¦ ¦ ¦ put(Memory, product.value+i, val); 174 ¦ ¦ } 175 ¦ } 176 } 177 else { -178 ¦ trace(9999, "mem") << "storing 0 in location " << status.value << end(); +178 ¦ trace("mem") << "storing 0 in location " << status.value << end(); 179 ¦ put(Memory, status.value, 0); 180 } 181 break; @@ -383,7 +383,7 @@ if ('onhashchange' in window) { 318 :(before "End check_merge_call Special-cases") 319 case EXCLUSIVE_CONTAINER: { 320 assert(state.data.top().container_element_index == 0); -321 trace(9999, "transform") << "checking exclusive container " << to_string(container) << " vs ingredient " << ingredient_index << end(); +321 trace("transform") << "checking exclusive container " << to_string(container) << " vs ingredient " << ingredient_index << end(); 322 // easy case: exact match 323 if (types_strictly_match(container, inst.ingredients.at(ingredient_index))) 324 ¦ return; @@ -398,7 +398,7 @@ if ('onhashchange' in window) { 333 ¦ return; 334 } 335 const reagent& variant = variant_type(container, ingredient.value); -336 trace(9999, "transform") << "tag: " << ingredient.value << end(); +336 trace("transform") << "tag: " << ingredient.value << end(); 337 // replace union with its variant 338 state.data.pop(); 339 state.data.push(merge_check_point(variant, 0)); diff --git a/html/034address.cc.html b/html/034address.cc.html index 7d5c45c8..83e47f3e 100644 --- a/html/034address.cc.html +++ b/html/034address.cc.html @@ -187,18 +187,18 @@ if ('onhashchange' in window) { 123 # call 'new' two times with identical types without modifying the results; you 124 # should get back different results 125 def main [ -126 1:address:num/raw <- new number:type -127 2:address:num/raw <- new number:type -128 3:bool/raw <- equal 1:address:num/raw, 2:address:num/raw +126 1:address:num/raw <- new number:type +127 2:address:num/raw <- new number:type +128 3:bool/raw <- equal 1:address:num/raw, 2:address:num/raw 129 ] 130 +mem: storing 0 in location 3 131 132 :(scenario new_array) 133 # call 'new' with a second ingredient to allocate an array of some type rather than a single copy 134 def main [ -135 1:address:array:num/raw <- new number:type, 5 -136 2:address:num/raw <- new number:type -137 3:num/raw <- subtract 2:address:num/raw, 1:address:array:num/raw +135 1:address:array:num/raw <- new number:type, 5 +136 2:address:num/raw <- new number:type +137 3:num/raw <- subtract 2:address:num/raw, 1:address:array:num/raw 138 ] 139 +run: {1: ("address" "array" "number"), "raw": ()} <- new {number: "type"}, {5: "literal"} 140 +mem: array length is 5 @@ -207,7 +207,7 @@ if ('onhashchange' in window) { 143 144 :(scenario dilated_reagent_with_new) 145 def main [ -146 1:address:address:num <- new {(address number): type} +146 1:address:address:num <- new {(address number): type} 147 ] 148 +new: size of '(address number)' is 1 149 @@ -298,19 +298,19 @@ if ('onhashchange' in window) { 234 :(scenario new_discerns_singleton_list_from_atom_container) 235 % Hide_errors = true; 236 def main [ -237 1:address:num/raw <- new {(num): type} # should be '{num: type}' +237 1:address:num/raw <- new {(num): type} # should be '{num: type}' 238 ] 239 +error: main: product of 'new' has incorrect type: '1:address:num/raw <- new {(num): type}' 240 241 :(scenario new_with_type_abbreviation) 242 def main [ -243 1:address:num/raw <- new num:type +243 1:address:num/raw <- new num:type 244 ] 245 $error: 0 246 247 :(scenario new_with_type_abbreviation_inside_compound) 248 def main [ -249 {1: (address address number), raw: ()} <- new {(& num): type} +249 {1: (address address number), raw: ()} <- new {(& num): type} 250 ] 251 $error: 0 252 @@ -366,7 +366,7 @@ if ('onhashchange' in window) { 302 alloc = Memory_allocated_until; 303 Memory_allocated_until += Initial_memory_per_routine; 304 alloc_max = Memory_allocated_until; -305 trace(9999, "new") << "routine allocated memory from " << alloc << " to " << alloc_max << end(); +305 trace("new") << "routine allocated memory from " << alloc << " to " << alloc_max << end(); 306 307 :(before "End Primitive Recipe Declarations") 308 ALLOCATE, @@ -378,13 +378,13 @@ if ('onhashchange' in window) { 314 int size = ingredients.at(0).at(0); 315 if (SIZE(ingredients) > 1) { 316 ¦ // array allocation -317 ¦ trace(9999, "mem") << "array length is " << ingredients.at(1).at(0) << end(); +317 ¦ trace("mem") << "array length is " << ingredients.at(1).at(0) << end(); 318 ¦ size = /*space for length*/1 + size*ingredients.at(1).at(0); 319 } 320 int result = allocate(size); 321 if (SIZE(current_instruction().ingredients) > 1) { 322 ¦ // initialize array length -323 ¦ trace(9999, "mem") << "storing " << ingredients.at(1).at(0) << " in location " << result+/*skip refcount*/1 << end(); +323 ¦ trace("mem") << "storing " << ingredients.at(1).at(0) << " in location " << result+/*skip refcount*/1 << end(); 324 ¦ put(Memory, result+/*skip refcount*/1, ingredients.at(1).at(0)); 325 } 326 products.resize(1); @@ -395,7 +395,7 @@ if ('onhashchange' in window) { 331 int allocate(int size) { 332 // include space for refcount 333 ++size; -334 trace(9999, "mem") << "allocating size " << size << end(); +334 trace("mem") << "allocating size " << size << end(); 335 //? Total_alloc += size; 336 //? ++Num_alloc; 337 // Allocate Special-cases @@ -403,11 +403,11 @@ if ('onhashchange' in window) { 339 // really crappy at the moment 340 ensure_space(size); 341 const int result = Current_routine->alloc; -342 trace(9999, "mem") << "new alloc: " << result << end(); +342 trace("mem") << "new alloc: " << result << end(); 343 // initialize allocated space -344 for (int address = result; address < result+size; ++address) { -345 ¦ trace(9999, "mem") << "storing 0 in location " << address << end(); -346 ¦ put(Memory, address, 0); +344 for (int address = result; address < result+size; ++address) { +345 ¦ trace("mem") << "storing 0 in location " << address << end(); +346 ¦ put(Memory, address, 0); 347 } 348 Current_routine->alloc += size; 349 // no support yet for reclaiming memory between routines @@ -440,7 +440,7 @@ if ('onhashchange' in window) { 376 ¦ Current_routine->alloc = Memory_allocated_until; 377 ¦ Memory_allocated_until += Initial_memory_per_routine; 378 ¦ Current_routine->alloc_max = Memory_allocated_until; -379 ¦ trace(9999, "new") << "routine allocated memory from " << Current_routine->alloc << " to " << Current_routine->alloc_max << end(); +379 ¦ trace("new") << "routine allocated memory from " << Current_routine->alloc << " to " << Current_routine->alloc_max << end(); 380 } 381 } 382 @@ -448,33 +448,33 @@ if ('onhashchange' in window) { 384 % Memory_allocated_until = 10; 385 % put(Memory, Memory_allocated_until, 1); 386 def main [ -387 1:address:num <- new number:type +387 1:address:num <- new number:type 388 ] 389 +mem: storing 0 in location 10 390 391 :(scenario new_size) 392 def main [ -393 11:address:num/raw <- new number:type -394 12:address:num/raw <- new number:type -395 13:num/raw <- subtract 12:address:num/raw, 11:address:num/raw +393 11:address:num/raw <- new number:type +394 12:address:num/raw <- new number:type +395 13:num/raw <- subtract 12:address:num/raw, 11:address:num/raw 396 ] 397 # size of number + refcount 398 +mem: storing 2 in location 13 399 400 :(scenario new_array_size) 401 def main [ -402 1:address:array:num/raw <- new number:type, 5 -403 2:address:num/raw <- new number:type -404 3:num/raw <- subtract 2:address:num/raw, 1:address:array:num/raw +402 1:address:array:num/raw <- new number:type, 5 +403 2:address:num/raw <- new number:type +404 3:num/raw <- subtract 2:address:num/raw, 1:address:array:num/raw 405 ] 406 # 5 locations for array contents + array length + refcount 407 +mem: storing 7 in location 3 408 409 :(scenario new_empty_array) 410 def main [ -411 1:address:array:num/raw <- new number:type, 0 -412 2:address:num/raw <- new number:type -413 3:num/raw <- subtract 2:address:num/raw, 1:address:array:num/raw +411 1:address:array:num/raw <- new number:type, 0 +412 2:address:num/raw <- new number:type +413 3:num/raw <- subtract 2:address:num/raw, 1:address:array:num/raw 414 ] 415 +run: {1: ("address" "array" "number"), "raw": ()} <- new {number: "type"}, {0: "literal"} 416 +mem: array length is 0 @@ -485,8 +485,8 @@ if ('onhashchange' in window) { 421 :(scenario new_overflow) 422 % Initial_memory_per_routine = 3; // barely enough room for point allocation below 423 def main [ -424 1:address:num/raw <- new number:type -425 2:address:point/raw <- new point:type # not enough room in initial page +424 1:address:num/raw <- new number:type +425 2:address:point/raw <- new point:type # not enough room in initial page 426 ] 427 +new: routine allocated memory from 1000 to 1003 428 +new: routine allocated memory from 1003 to 1006 @@ -494,7 +494,7 @@ if ('onhashchange' in window) { 430 :(scenario new_without_ingredient) 431 % Hide_errors = true; 432 def main [ -433 1:address:number <- new # missing ingredient +433 1:address:number <- new # missing ingredient 434 ] 435 +error: main: 'new' requires one or two ingredients, but got '1:address:number <- new' diff --git a/html/035lookup.cc.html b/html/035lookup.cc.html index 175b0ad5..d888828a 100644 --- a/html/035lookup.cc.html +++ b/html/035lookup.cc.html @@ -99,10 +99,10 @@ if ('onhashchange' in window) { 34 35 :(scenario copy_indirect) 36 def main [ - 37 1:address:num <- copy 10/unsafe + 37 1:address:num <- copy 10/unsafe 38 11:num <- copy 34 39 # This loads location 1 as an address and looks up *that* location. - 40 2:num <- copy 1:address:num/lookup + 40 2:num <- copy 1:address:num/lookup 41 ] 42 # 1 contains 10. Skip refcount and lookup location 11. 43 +mem: storing 34 in location 2 @@ -114,8 +114,8 @@ if ('onhashchange' in window) { 49 //: 'lookup' property 50 :(scenario store_indirect) 51 def main [ - 52 1:address:num <- copy 10/unsafe - 53 1:address:num/lookup <- copy 34 + 52 1:address:num <- copy 10/unsafe + 53 1:address:num/lookup <- copy 34 54 ] 55 +mem: storing 34 in location 11 56 @@ -126,18 +126,18 @@ if ('onhashchange' in window) { 61 :(scenario store_to_0_fails) 62 % Hide_errors = true; 63 def main [ - 64 1:address:num <- copy 0 - 65 1:address:num/lookup <- copy 34 + 64 1:address:num <- copy 0 + 65 1:address:num/lookup <- copy 34 66 ] 67 -mem: storing 34 in location 0 - 68 +error: can't write to location 0 in '1:address:num/lookup <- copy 34' + 68 +error: can't write to location 0 in '1:address:num/lookup <- copy 34' 69 70 //: attempts to /lookup address 0 always loudly fail 71 :(scenario lookup_0_fails) 72 % Hide_errors = true; 73 def main [ - 74 1:address:num <- copy 0 - 75 2:num <- copy 1:address:num/lookup + 74 1:address:num <- copy 0 + 75 2:num <- copy 1:address:num/lookup 76 ] 77 +error: main: tried to /lookup 0 in '2:num <- copy 1:address:num/lookup' 78 @@ -164,11 +164,11 @@ if ('onhashchange' in window) { 99 100 void lookup_memory_core(reagent& x, bool check_for_null) { 101 if (x.value == 0) return; -102 trace(9999, "mem") << "location " << x.value << " is " << no_scientific(get_or_insert(Memory, x.value)) << end(); +102 trace("mem") << "location " << x.value << " is " << no_scientific(get_or_insert(Memory, x.value)) << end(); 103 x.set_value(get_or_insert(Memory, x.value)); 104 drop_from_type(x, "address"); 105 if (x.value) { -106 ¦ trace(9999, "mem") << "skipping refcount at " << x.value << end(); +106 ¦ trace("mem") << "skipping refcount at " << x.value << end(); 107 ¦ x.set_value(x.value+1); // skip refcount 108 } 109 else if (check_for_null) { @@ -181,7 +181,7 @@ if ('onhashchange' in window) { 116 } 117 118 void test_lookup_address_skips_refcount() { -119 reagent x("*x:address:num"); +119 reagent x("*x:address:num"); 120 x.set_value(34); // unsafe 121 put(Memory, 34, 1000); 122 lookup_memory(x); @@ -191,7 +191,7 @@ if ('onhashchange' in window) { 126 127 void test_lookup_zero_address_does_not_skip_refcount() { 128 Hide_errors = true; -129 reagent x("*x:address:num"); +129 reagent x("*x:address:num"); 130 x.set_value(34); // unsafe 131 put(Memory, 34, 0); 132 lookup_memory(x); @@ -264,32 +264,32 @@ if ('onhashchange' in window) { 199 200 :(scenario get_indirect) 201 def main [ -202 1:address:point <- copy 10/unsafe +202 1:address:point <- copy 10/unsafe 203 # 10 reserved for refcount 204 11:num <- copy 34 205 12:num <- copy 35 -206 2:num <- get 1:address:point/lookup, 0:offset +206 2:num <- get 1:address:point/lookup, 0:offset 207 ] 208 +mem: storing 34 in location 2 209 210 :(scenario get_indirect2) 211 def main [ -212 1:address:point <- copy 10/unsafe +212 1:address:point <- copy 10/unsafe 213 # 10 reserved for refcount 214 11:num <- copy 34 215 12:num <- copy 35 -216 2:address:num <- copy 20/unsafe -217 2:address:num/lookup <- get 1:address:point/lookup, 0:offset +216 2:address:num <- copy 20/unsafe +217 2:address:num/lookup <- get 1:address:point/lookup, 0:offset 218 ] 219 +mem: storing 34 in location 21 220 221 :(scenario include_nonlookup_properties) 222 def main [ -223 1:address:point <- copy 10/unsafe +223 1:address:point <- copy 10/unsafe 224 # 10 reserved for refcount 225 11:num <- copy 34 226 12:num <- copy 35 -227 2:num <- get 1:address:point/lookup/foo, 0:offset +227 2:num <- get 1:address:point/lookup/foo, 0:offset 228 ] 229 +mem: storing 34 in location 2 230 @@ -302,11 +302,11 @@ if ('onhashchange' in window) { 237 238 :(scenario put_indirect) 239 def main [ -240 1:address:point <- copy 10/unsafe +240 1:address:point <- copy 10/unsafe 241 # 10 reserved for refcount 242 11:num <- copy 34 243 12:num <- copy 35 -244 1:address:point/lookup <- put 1:address:point/lookup, 0:offset, 36 +244 1:address:point/lookup <- put 1:address:point/lookup, 0:offset, 36 245 ] 246 +mem: storing 36 in location 11 247 @@ -320,11 +320,11 @@ if ('onhashchange' in window) { 255 :(scenario put_product_error_with_lookup) 256 % Hide_errors = true; 257 def main [ -258 1:address:point <- copy 10/unsafe +258 1:address:point <- copy 10/unsafe 259 # 10 reserved for refcount 260 11:num <- copy 34 261 12:num <- copy 35 -262 1:address:point <- put 1:address:point/lookup, x:offset, 36 +262 1:address:point <- put 1:address:point/lookup, x:offset, 36 263 ] 264 +error: main: product of 'put' must be first ingredient '1:address:point/lookup', but got '1:address:point' 265 @@ -355,8 +355,8 @@ if ('onhashchange' in window) { 290 12:num <- copy 14 291 13:num <- copy 15 292 14:num <- copy 16 -293 1:address:array:num <- copy 10/unsafe -294 2:array:num <- copy 1:address:array:num/lookup +293 1:address:array:num <- copy 10/unsafe +294 2:array:num <- copy 1:address:array:num/lookup 295 ] 296 +mem: storing 3 in location 2 297 +mem: storing 14 in location 3 @@ -366,8 +366,8 @@ if ('onhashchange' in window) { 301 :(scenario create_array_indirect) 302 def main [ 303 1000:num/raw <- copy 1 # pretend refcount -304 1:address:array:num:3 <- copy 1000/unsafe # pretend allocation -305 1:address:array:num:3/lookup <- create-array +304 1:address:array:num:3 <- copy 1000/unsafe # pretend allocation +305 1:address:array:num:3/lookup <- create-array 306 ] 307 +mem: storing 3 in location 1001 308 @@ -383,8 +383,8 @@ if ('onhashchange' in window) { 318 12:num <- copy 14 319 13:num <- copy 15 320 14:num <- copy 16 -321 1:address:array:num <- copy 10/unsafe -322 2:num <- index 1:address:array:num/lookup, 1 +321 1:address:array:num <- copy 10/unsafe +322 2:num <- index 1:address:array:num/lookup, 1 323 ] 324 +mem: storing 15 in location 2 325 @@ -407,8 +407,8 @@ if ('onhashchange' in window) { 342 12:num <- copy 14 343 13:num <- copy 15 344 14:num <- copy 16 -345 1:address:array:num <- copy 10/unsafe -346 1:address:array:num/lookup <- put-index 1:address:array:num/lookup, 1, 34 +345 1:address:array:num <- copy 10/unsafe +346 1:address:array:num/lookup <- put-index 1:address:array:num/lookup, 1, 34 347 ] 348 +mem: storing 34 in location 13 349 @@ -418,10 +418,10 @@ if ('onhashchange' in window) { 353 2:num <- copy 14 354 3:num <- copy 15 355 4:num <- copy 16 -356 5:address:num <- copy 10/unsafe +356 5:address:num <- copy 10/unsafe 357 # 10 reserved for refcount 358 11:num <- copy 1 -359 1:array:num:3 <- put-index 1:array:num:3, 5:address:num/lookup, 34 +359 1:array:num:3 <- put-index 1:array:num:3, 5:address:num/lookup, 34 360 ] 361 +mem: storing 34 in location 3 362 @@ -433,8 +433,8 @@ if ('onhashchange' in window) { 368 12:num <- copy 14 369 13:num <- copy 15 370 14:num <- copy 16 -371 1:address:array:num <- copy 10/unsafe -372 1:address:array:num <- put-index 1:address:array:num/lookup, 1, 34 +371 1:address:array:num <- copy 10/unsafe +372 1:address:array:num <- put-index 1:address:array:num/lookup, 1, 34 373 ] 374 +error: main: product of 'put-index' must be first ingredient '1:address:array:num/lookup', but got '1:address:array:num' 375 @@ -450,11 +450,11 @@ if ('onhashchange' in window) { 385 386 :(scenario dilated_reagent_in_static_array) 387 def main [ -388 {1: (array (address number) 3)} <- create-array -389 5:address:num <- new number:type -390 {1: (array (address number) 3)} <- put-index {1: (array (address number) 3)}, 0, 5:address:num -391 *5:address:num <- copy 34 -392 6:num <- copy *5:address:num +388 {1: (array (address number) 3)} <- create-array +389 5:address:num <- new number:type +390 {1: (array (address number) 3)} <- put-index {1: (array (address number) 3)}, 0, 5:address:num +391 *5:address:num <- copy 34 +392 6:num <- copy *5:address:num 393 ] 394 +run: creating array of size 4 395 +mem: storing 34 in location 6 @@ -478,8 +478,8 @@ if ('onhashchange' in window) { 413 12:num <- copy 14 414 13:num <- copy 15 415 14:num <- copy 16 -416 1:address:array:num <- copy 10/unsafe -417 2:num <- length 1:address:array:num/lookup +416 1:address:array:num <- copy 10/unsafe +417 2:num <- length 1:address:array:num/lookup 418 ] 419 +mem: storing 3 in location 2 420 @@ -492,8 +492,8 @@ if ('onhashchange' in window) { 427 def main [ 428 # 10 reserved for refcount 429 11:number-or-point <- merge 0/number, 34 -430 1:address:number-or-point <- copy 10/unsafe -431 2:num, 3:bool <- maybe-convert 1:address:number-or-point/lookup, i:variant +430 1:address:number-or-point <- copy 10/unsafe +431 2:num, 3:bool <- maybe-convert 1:address:number-or-point/lookup, i:variant 432 ] 433 +mem: storing 1 in location 3 434 +mem: storing 34 in location 2 @@ -502,9 +502,9 @@ if ('onhashchange' in window) { 437 def main [ 438 # 10 reserved for refcount 439 11:number-or-point <- merge 0/number, 34 -440 1:address:number-or-point <- copy 10/unsafe -441 2:address:num <- copy 20/unsafe -442 2:address:num/lookup, 3:bool <- maybe-convert 1:address:number-or-point/lookup, i:variant +440 1:address:number-or-point <- copy 10/unsafe +441 2:address:num <- copy 20/unsafe +442 2:address:num/lookup, 3:bool <- maybe-convert 1:address:number-or-point/lookup, i:variant 443 ] 444 +mem: storing 1 in location 3 445 +mem: storing 34 in location 21 @@ -513,9 +513,9 @@ if ('onhashchange' in window) { 448 def main [ 449 # 10 reserved for refcount 450 11:number-or-point <- merge 0/number, 34 -451 1:address:number-or-point <- copy 10/unsafe -452 2:address:bool <- copy 20/unsafe -453 3:num, 2:address:bool/lookup <- maybe-convert 1:address:number-or-point/lookup, i:variant +451 1:address:number-or-point <- copy 10/unsafe +452 2:address:bool <- copy 20/unsafe +453 3:num, 2:address:bool/lookup <- maybe-convert 1:address:number-or-point/lookup, i:variant 454 ] 455 +mem: storing 1 in location 21 456 +mem: storing 34 in location 3 @@ -536,8 +536,8 @@ if ('onhashchange' in window) { 471 472 :(scenario merge_exclusive_container_indirect) 473 def main [ -474 1:address:number-or-point <- copy 10/unsafe -475 1:address:number-or-point/lookup <- merge 0/number, 34 +474 1:address:number-or-point <- copy 10/unsafe +475 1:address:number-or-point/lookup <- merge 0/number, 34 476 ] 477 # skip 10 for refcount 478 +mem: storing 0 in location 11 @@ -550,10 +550,10 @@ if ('onhashchange' in window) { 485 486 :(scenario lookup_abbreviation) 487 def main [ -488 1:address:number <- copy 10/unsafe +488 1:address:number <- copy 10/unsafe 489 # 10 reserved for refcount 490 11:number <- copy 34 -491 3:number <- copy *1:address:number +491 3:number <- copy *1:address:number 492 ] 493 +parse: ingredient: {1: ("address" "number"), "lookup": ()} 494 +mem: storing 34 in location 3 diff --git a/html/036refcount.cc.html b/html/036refcount.cc.html index f7dc5df7..d8667152 100644 --- a/html/036refcount.cc.html +++ b/html/036refcount.cc.html @@ -68,10 +68,10 @@ if ('onhashchange' in window) { 3 4 :(scenario refcounts) 5 def main [ - 6 1:address:num <- copy 1000/unsafe - 7 2:address:num <- copy 1:address:num - 8 1:address:num <- copy 0 - 9 2:address:num <- copy 0 + 6 1:address:num <- copy 1000/unsafe + 7 2:address:num <- copy 1:address:num + 8 1:address:num <- copy 0 + 9 2:address:num <- copy 0 10 ] 11 +run: {1: ("address" "number")} <- copy {1000: "literal", "unsafe": ()} 12 +mem: incrementing refcount of 1000: 0 -> 1 @@ -117,7 +117,7 @@ if ('onhashchange' in window) { 52 if (new_address == 0) return; 53 ++Total_refcount_updates; 54 int new_refcount = get_or_insert(Memory, new_address); - 55 trace(9999, "mem") << "incrementing refcount of " << new_address << ": " << new_refcount << " -> " << new_refcount+1 << end(); + 55 trace("mem") << "incrementing refcount of " << new_address << ": " << new_refcount << " -> " << new_refcount+1 << end(); 56 put(Memory, new_address, new_refcount+1); 57 } 58 @@ -135,7 +135,7 @@ if ('onhashchange' in window) { 70 if (old_address == 0) return; 71 ++Total_refcount_updates; 72 int old_refcount = get_or_insert(Memory, old_address); - 73 trace(9999, "mem") << "decrementing refcount of " << old_address << ": " << old_refcount << " -> " << old_refcount-1 << end(); + 73 trace("mem") << "decrementing refcount of " << old_address << ": " << old_refcount << " -> " << old_refcount-1 << end(); 74 --old_refcount; 75 put(Memory, old_address, old_refcount); 76 if (old_refcount < 0) { @@ -159,9 +159,9 @@ if ('onhashchange' in window) { 94 95 :(scenario refcounts_reflexive) 96 def main [ - 97 1:address:num <- new number:type + 97 1:address:num <- new number:type 98 # idempotent copies leave refcount unchanged - 99 1:address:num <- copy 1:address:num + 99 1:address:num <- copy 1:address:num 100 ] 101 +run: {1: ("address" "number")} <- new {number: "type"} 102 +mem: incrementing refcount of 1000: 0 -> 1 @@ -171,14 +171,14 @@ if ('onhashchange' in window) { 106 107 :(scenario refcounts_call) 108 def main [ - 109 1:address:num <- new number:type + 109 1:address:num <- new number:type 110 # passing in addresses to recipes increments refcount - 111 foo 1:address:num + 111 foo 1:address:num 112 # return does NOT yet decrement refcount; memory must be explicitly managed - 113 1:address:num <- new number:type + 113 1:address:num <- new number:type 114 ] 115 def foo [ - 116 2:address:num <- next-ingredient + 116 2:address:num <- next-ingredient 117 ] 118 +run: {1: ("address" "number")} <- new {number: "type"} 119 +mem: incrementing refcount of 1000: 0 -> 1 @@ -193,12 +193,12 @@ if ('onhashchange' in window) { 128 129 :(scenario refcounts_put) 130 container foo [ - 131 x:address:num + 131 x:address:num 132 ] 133 def main [ - 134 1:address:num <- new number:type - 135 2:address:foo <- new foo:type - 136 *2:address:foo <- put *2:address:foo, x:offset, 1:address:num + 134 1:address:num <- new number:type + 135 2:address:foo <- new foo:type + 136 *2:address:foo <- put *2:address:foo, x:offset, 1:address:num 137 ] 138 +run: {1: ("address" "number")} <- new {number: "type"} 139 +mem: incrementing refcount of 1000: 0 -> 1 @@ -211,14 +211,14 @@ if ('onhashchange' in window) { 146 :(after "Write Memory in PUT in Run") 147 reagent/*copy*/ element = element_type(base.type, offset); 148 assert(!has_property(element, "lookup")); - 149 element.set_value(address); + 149 element.set_value(address); 150 update_any_refcounts(element, ingredients.at(2)); 151 152 :(scenario refcounts_put_index) 153 def main [ - 154 1:address:num <- new number:type - 155 2:address:array:address:num <- new {(address number): type}, 3 - 156 *2:address:array:address:num <- put-index *2:address:array:address:num, 0, 1:address:num + 154 1:address:num <- new number:type + 155 2:address:array:address:num <- new {(address number): type}, 3 + 156 *2:address:array:address:num <- put-index *2:address:array:address:num, 0, 1:address:num 157 ] 158 +run: {1: ("address" "number")} <- new {number: "type"} 159 +mem: incrementing refcount of 1000: 0 -> 1 @@ -230,19 +230,19 @@ if ('onhashchange' in window) { 165 166 :(after "Write Memory in PUT_INDEX in Run") 167 reagent/*local*/ element; - 168 element.set_value(address); + 168 element.set_value(address); 169 element.type = copy_array_element(base.type); 170 update_any_refcounts(element, value); 171 172 :(scenario refcounts_maybe_convert) 173 exclusive-container foo [ 174 x:num - 175 p:address:num + 175 p:address:num 176 ] 177 def main [ - 178 1:address:num <- new number:type - 179 2:foo <- merge 1/p, 1:address:num - 180 4:address:num, 5:bool <- maybe-convert 2:foo, 1:variant/p + 178 1:address:num <- new number:type + 179 2:foo <- merge 1/p, 1:address:num + 180 4:address:num, 5:bool <- maybe-convert 2:foo, 1:variant/p 181 ] 182 +run: {1: ("address" "number")} <- new {number: "type"} 183 +mem: incrementing refcount of 1000: 0 -> 1 @@ -264,17 +264,17 @@ if ('onhashchange' in window) { 199 200 :(scenario refcounts_copy_nested) 201 container foo [ - 202 x:address:num # address inside container + 202 x:address:num # address inside container 203 ] 204 def main [ - 205 1:address:num <- new number:type - 206 2:address:foo <- new foo:type - 207 *2:address:foo <- put *2:address:foo, x:offset, 1:address:num - 208 3:foo <- copy *2:address:foo + 205 1:address:num <- new number:type + 206 2:address:foo <- new foo:type + 207 *2:address:foo <- put *2:address:foo, x:offset, 1:address:num + 208 3:foo <- copy *2:address:foo 209 ] - 210 +transform: compute address offsets for container foo + 210 +transform: compute address offsets for container foo 211 +transform: checking container foo, element 0 - 212 +transform: address at offset 0 + 212 +transform: address at offset 0 213 +run: {1: ("address" "number")} <- new {number: "type"} 214 +mem: incrementing refcount of 1000: 0 -> 1 215 +run: {2: ("address" "foo"), "lookup": ()} <- put {2: ("address" "foo"), "lookup": ()}, {x: "offset"}, {1: ("address" "number")} @@ -339,7 +339,7 @@ if ('onhashchange' in window) { 274 // IF offset o1 has tag t2 AND offset o2 has tag t2 AND .., THEN 275 // for all address_element_infos: 276 // you need to update refcounts for the address at offset pointing to a payload of type payload_type (just in case we need to abandon something in the process) - 277 map<set<tag_condition_info>, set<address_element_info> > address; + 277 map<set<tag_condition_info>, set<address_element_info> > address; 278 :(code) 279 bool operator<(const set<tag_condition_info>& a, const set<tag_condition_info>& b) { 280 if (a.size() != b.size()) return a.size() < b.size(); @@ -374,10 +374,10 @@ if ('onhashchange' in window) { 309 :(code) 310 void compute_container_address_offsets(const recipe_ordinal r) { 311 recipe& caller = get(Recipe, r); - 312 trace(9992, "transform") << "--- compute address offsets for " << caller.name << end(); + 312 trace(9992, "transform") << "--- compute address offsets for " << caller.name << end(); 313 for (int i = 0; i < SIZE(caller.steps); ++i) { 314 ¦ instruction& inst = caller.steps.at(i); - 315 ¦ trace(9993, "transform") << "- compute address offsets for " << to_string(inst) << end(); + 315 ¦ trace(9993, "transform") << "- compute address offsets for " << to_string(inst) << end(); 316 ¦ for (int i = 0; i < SIZE(inst.ingredients); ++i) 317 ¦ ¦ compute_container_address_offsets(inst.ingredients.at(i), " in '"+inst.original_string+"'"); 318 ¦ for (int i = 0; i < SIZE(inst.products); ++i) @@ -421,18 +421,18 @@ if ('onhashchange' in window) { 356 357 void compute_container_address_offsets(const type_info& container_info, const type_tree* full_type, const string& location_for_error_messages) { 358 container_metadata& metadata = get(Container_metadata, full_type); - 359 if (!metadata.address.empty()) return; - 360 trace(9994, "transform") << "compute address offsets for container " << container_info.name << end(); - 361 append_addresses(0, full_type, metadata.address, set<tag_condition_info>(), location_for_error_messages); + 359 if (!metadata.address.empty()) return; + 360 trace(9994, "transform") << "compute address offsets for container " << container_info.name << end(); + 361 append_addresses(0, full_type, metadata.address, set<tag_condition_info>(), location_for_error_messages); 362 } 363 364 void compute_exclusive_container_address_offsets(const type_info& exclusive_container_info, const type_tree* full_type, const string& location_for_error_messages) { 365 container_metadata& metadata = get(Container_metadata, full_type); - 366 trace(9994, "transform") << "compute address offsets for exclusive container " << exclusive_container_info.name << end(); + 366 trace(9994, "transform") << "compute address offsets for exclusive container " << exclusive_container_info.name << end(); 367 for (int tag = 0; tag < SIZE(exclusive_container_info.elements); ++tag) { 368 ¦ set<tag_condition_info> key; 369 ¦ key.insert(tag_condition_info(/*tag is at offset*/0, tag)); - 370 ¦ append_addresses(/*skip tag offset*/1, variant_type(full_type, tag).type, metadata.address, key, location_for_error_messages); + 370 ¦ append_addresses(/*skip tag offset*/1, variant_type(full_type, tag).type, metadata.address, key, location_for_error_messages); 371 } 372 } 373 @@ -509,10 +509,10 @@ if ('onhashchange' in window) { 444 // no entries for non-container types or other junk 445 CHECK_EQ(SIZE(Container_metadata)-old_size, 1); 446 // the reagent we scanned knows it has no addresses - 447 CHECK(r.metadata.address.empty()); + 447 CHECK(r.metadata.address.empty()); 448 // the global table contains an identical entry 449 CHECK(contains_key(Container_metadata, r.type)); - 450 CHECK(get(Container_metadata, r.type).address.empty()); + 450 CHECK(get(Container_metadata, r.type).address.empty()); 451 // compute_container_address_offsets creates no new entries 452 CHECK_EQ(SIZE(Container_metadata)-old_size, 1); 453 } @@ -521,7 +521,7 @@ if ('onhashchange' in window) { 456 int old_size = SIZE(Container_metadata); 457 // define a container with an address at offset 0 that we have the size for 458 run("container foo [\n" - 459 ¦ ¦ " x:address:num\n" + 459 ¦ ¦ " x:address:num\n" 460 ¦ ¦ "]\n"); 461 reagent r("x:foo"); 462 compute_container_sizes(r, ""); // need to first pre-populate the metadata @@ -531,16 +531,16 @@ if ('onhashchange' in window) { 466 // no entries for non-container types or other junk 467 CHECK_EQ(SIZE(Container_metadata)-old_size, 1); 468 // the reagent we scanned knows it has an address at offset 0 - 469 CHECK_EQ(SIZE(r.metadata.address), 1); - 470 CHECK(contains_key(r.metadata.address, set<tag_condition_info>())); - 471 const set<address_element_info>& address_offsets = get(r.metadata.address, set<tag_condition_info>()); // unconditional for containers + 469 CHECK_EQ(SIZE(r.metadata.address), 1); + 470 CHECK(contains_key(r.metadata.address, set<tag_condition_info>())); + 471 const set<address_element_info>& address_offsets = get(r.metadata.address, set<tag_condition_info>()); // unconditional for containers 472 CHECK_EQ(SIZE(address_offsets), 1); 473 CHECK_EQ(address_offsets.begin()->offset, 0); 474 CHECK(address_offsets.begin()->payload_type->atom); 475 CHECK_EQ(address_offsets.begin()->payload_type->name, "number"); 476 // the global table contains an identical entry 477 CHECK(contains_key(Container_metadata, r.type)); - 478 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, r.type).address, set<tag_condition_info>()); + 478 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, r.type).address, set<tag_condition_info>()); 479 CHECK_EQ(SIZE(address_offsets2), 1); 480 CHECK_EQ(address_offsets2.begin()->offset, 0); 481 CHECK(address_offsets2.begin()->payload_type->atom); @@ -554,7 +554,7 @@ if ('onhashchange' in window) { 489 // define a container with an address at offset 1 that we have the size for 490 run("container foo [\n" 491 ¦ ¦ " x:num\n" - 492 ¦ ¦ " y:address:num\n" + 492 ¦ ¦ " y:address:num\n" 493 ¦ ¦ "]\n"); 494 reagent r("x:foo"); 495 compute_container_sizes(r, ""); // need to first pre-populate the metadata @@ -566,16 +566,16 @@ if ('onhashchange' in window) { 501 // compute_container_address_offsets creates no new entries 502 CHECK_EQ(SIZE(Container_metadata)-old_size, 1); 503 // the reagent we scanned knows it has an address at offset 1 - 504 CHECK_EQ(SIZE(r.metadata.address), 1); - 505 CHECK(contains_key(r.metadata.address, set<tag_condition_info>())); - 506 const set<address_element_info>& address_offsets = get(r.metadata.address, set<tag_condition_info>()); + 504 CHECK_EQ(SIZE(r.metadata.address), 1); + 505 CHECK(contains_key(r.metadata.address, set<tag_condition_info>())); + 506 const set<address_element_info>& address_offsets = get(r.metadata.address, set<tag_condition_info>()); 507 CHECK_EQ(SIZE(address_offsets), 1); 508 CHECK_EQ(address_offsets.begin()->offset, 1); // 509 CHECK(address_offsets.begin()->payload_type->atom); 510 CHECK_EQ(address_offsets.begin()->payload_type->name, "number"); 511 // the global table contains an identical entry 512 CHECK(contains_key(Container_metadata, r.type)); - 513 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, r.type).address, set<tag_condition_info>()); + 513 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, r.type).address, set<tag_condition_info>()); 514 CHECK_EQ(SIZE(address_offsets2), 1); 515 CHECK_EQ(address_offsets2.begin()->offset, 1); // 516 CHECK(address_offsets2.begin()->payload_type->atom); @@ -586,7 +586,7 @@ if ('onhashchange' in window) { 521 int old_size = SIZE(Container_metadata); 522 // define a container with a nested container containing an address 523 run("container foo [\n" - 524 ¦ ¦ " x:address:num\n" + 524 ¦ ¦ " x:address:num\n" 525 ¦ ¦ " y:num\n" 526 ¦ ¦ "]\n" 527 ¦ ¦ "container bar [\n" @@ -601,16 +601,16 @@ if ('onhashchange' in window) { 536 // scan 537 compute_container_address_offsets(r, ""); 538 // the reagent we scanned knows it has an address at offset 2 - 539 CHECK_EQ(SIZE(r.metadata.address), 1); - 540 CHECK(contains_key(r.metadata.address, set<tag_condition_info>())); - 541 const set<address_element_info>& address_offsets = get(r.metadata.address, set<tag_condition_info>()); + 539 CHECK_EQ(SIZE(r.metadata.address), 1); + 540 CHECK(contains_key(r.metadata.address, set<tag_condition_info>())); + 541 const set<address_element_info>& address_offsets = get(r.metadata.address, set<tag_condition_info>()); 542 CHECK_EQ(SIZE(address_offsets), 1); 543 CHECK_EQ(address_offsets.begin()->offset, 2); // 544 CHECK(address_offsets.begin()->payload_type->atom); 545 CHECK_EQ(address_offsets.begin()->payload_type->name, "number"); 546 // the global table also knows its address offset 547 CHECK(contains_key(Container_metadata, r.type)); - 548 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, r.type).address, set<tag_condition_info>()); + 548 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, r.type).address, set<tag_condition_info>()); 549 CHECK_EQ(SIZE(address_offsets2), 1); 550 CHECK_EQ(address_offsets2.begin()->offset, 2); // 551 CHECK(address_offsets2.begin()->payload_type->atom); @@ -623,9 +623,9 @@ if ('onhashchange' in window) { 558 int old_size = SIZE(Container_metadata); 559 // define a container with an address at offset 0 560 run("container foo [\n" - 561 ¦ ¦ " x:address:num\n" + 561 ¦ ¦ " x:address:num\n" 562 ¦ ¦ "]\n"); - 563 reagent r("x:address:foo"); + 563 reagent r("x:address:foo"); 564 compute_container_sizes(r, ""); // need to first pre-populate the metadata 565 // global metadata contains just the entry for foo 566 // no entries for non-container types or other junk @@ -637,7 +637,7 @@ if ('onhashchange' in window) { 572 // scanning precomputed metadata for the container 573 reagent container("x:foo"); 574 CHECK(contains_key(Container_metadata, container.type)); - 575 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); + 575 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); 576 CHECK_EQ(SIZE(address_offsets2), 1); 577 CHECK_EQ(address_offsets2.begin()->offset, 0); 578 CHECK(address_offsets2.begin()->payload_type->atom); @@ -648,7 +648,7 @@ if ('onhashchange' in window) { 583 int old_size = SIZE(Container_metadata); 584 // define a container with an address at offset 0 585 run("container foo [\n" - 586 ¦ ¦ " x:address:num\n" + 586 ¦ ¦ " x:address:num\n" 587 ¦ ¦ "]\n"); 588 reagent r("x:array:foo"); 589 compute_container_sizes(r, ""); // need to first pre-populate the metadata @@ -662,7 +662,7 @@ if ('onhashchange' in window) { 597 // scanning precomputed metadata for the container 598 reagent container("x:foo"); 599 CHECK(contains_key(Container_metadata, container.type)); - 600 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); + 600 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); 601 CHECK_EQ(SIZE(address_offsets2), 1); 602 CHECK_EQ(address_offsets2.begin()->offset, 0); 603 CHECK(address_offsets2.begin()->payload_type->atom); @@ -673,9 +673,9 @@ if ('onhashchange' in window) { 608 int old_size = SIZE(Container_metadata); 609 // define a container with an address at offset 0 610 run("container foo [\n" - 611 ¦ ¦ " x:address:num\n" + 611 ¦ ¦ " x:address:num\n" 612 ¦ ¦ "]\n"); - 613 reagent r("x:address:array:foo"); + 613 reagent r("x:address:array:foo"); 614 compute_container_sizes(r, ""); // need to first pre-populate the metadata 615 // global metadata contains just the entry for foo 616 // no entries for non-container types or other junk @@ -687,7 +687,7 @@ if ('onhashchange' in window) { 622 // scanning precomputed metadata for the container 623 reagent container("x:foo"); 624 CHECK(contains_key(Container_metadata, container.type)); - 625 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); + 625 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); 626 CHECK_EQ(SIZE(address_offsets2), 1); 627 CHECK_EQ(address_offsets2.begin()->offset, 0); 628 CHECK(address_offsets2.begin()->payload_type->atom); @@ -698,7 +698,7 @@ if ('onhashchange' in window) { 633 int old_size = SIZE(Container_metadata); 634 // define a container with an address at offset 0 635 run("container foo [\n" - 636 ¦ ¦ " x:address:num\n" + 636 ¦ ¦ " x:address:num\n" 637 ¦ ¦ "]\n"); 638 reagent r("x:array:foo:10"); 639 compute_container_sizes(r, ""); // need to first pre-populate the metadata @@ -712,7 +712,7 @@ if ('onhashchange' in window) { 647 // scanning precomputed metadata for the container 648 reagent container("x:foo"); 649 CHECK(contains_key(Container_metadata, container.type)); - 650 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); + 650 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); 651 CHECK_EQ(SIZE(address_offsets2), 1); 652 CHECK_EQ(address_offsets2.begin()->offset, 0); 653 CHECK(address_offsets2.begin()->payload_type->atom); @@ -723,9 +723,9 @@ if ('onhashchange' in window) { 658 int old_size = SIZE(Container_metadata); 659 // define a container with an address at offset 0 660 run("container foo [\n" - 661 ¦ ¦ " x:address:num\n" + 661 ¦ ¦ " x:address:num\n" 662 ¦ ¦ "]\n"); - 663 reagent r("x:address:array:foo:10"); + 663 reagent r("x:address:array:foo:10"); 664 compute_container_sizes(r, ""); // need to first pre-populate the metadata 665 // global metadata contains just the entry for foo 666 // no entries for non-container types or other junk @@ -737,7 +737,7 @@ if ('onhashchange' in window) { 672 // scanning precomputed metadata for the container 673 reagent container("x:foo"); 674 CHECK(contains_key(Container_metadata, container.type)); - 675 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); + 675 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); 676 CHECK_EQ(SIZE(address_offsets2), 1); 677 CHECK_EQ(address_offsets2.begin()->offset, 0); 678 CHECK(address_offsets2.begin()->payload_type->atom); @@ -748,10 +748,10 @@ if ('onhashchange' in window) { 683 int old_size = SIZE(Container_metadata); 684 // define a container with an address at offset 0 685 run("container foo [\n" - 686 ¦ ¦ " x:address:num\n" + 686 ¦ ¦ " x:address:num\n" 687 ¦ ¦ "]\n"); 688 // scan a deep nest of 'address' and 'array' types modifying a container - 689 reagent r("x:address:array:address:address:array:foo:10"); + 689 reagent r("x:address:array:address:address:array:foo:10"); 690 compute_container_sizes(r, ""); // need to first pre-populate the metadata 691 // global metadata contains just the entry for foo 692 // no entries for non-container types or other junk @@ -762,7 +762,7 @@ if ('onhashchange' in window) { 697 // scanning precomputed metadata for the container 698 reagent container("x:foo"); 699 CHECK(contains_key(Container_metadata, container.type)); - 700 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); + 700 const set<address_element_info>& address_offsets2 = get(get(Container_metadata, container.type).address, set<tag_condition_info>()); 701 CHECK_EQ(SIZE(address_offsets2), 1); 702 CHECK_EQ(address_offsets2.begin()->offset, 0); 703 CHECK(address_offsets2.begin()->payload_type->atom); @@ -775,7 +775,7 @@ if ('onhashchange' in window) { 710 :(before "End Increment Refcounts(canonized_x)") 711 if (is_mu_container(canonized_x) || is_mu_exclusive_container(canonized_x)) { 712 const container_metadata& metadata = get(Container_metadata, canonized_x.type); - 713 for (map<set<tag_condition_info>, set<address_element_info> >::const_iterator p = metadata.address.begin(); p != metadata.address.end(); ++p) { + 713 for (map<set<tag_condition_info>, set<address_element_info> >::const_iterator p = metadata.address.begin(); p != metadata.address.end(); ++p) { 714 ¦ if (!all_match(data, p->first)) continue; 715 ¦ for (set<address_element_info>::const_iterator info = p->second.begin(); info != p->second.end(); ++info) 716 ¦ ¦ increment_refcount(data.at(info->offset)); @@ -784,14 +784,14 @@ if ('onhashchange' in window) { 719 720 :(before "End Decrement Refcounts(canonized_x)") 721 if (is_mu_container(canonized_x) || is_mu_exclusive_container(canonized_x)) { - 722 trace(9999, "mem") << "need to read old value of '" << to_string(canonized_x) << "' to figure out what refcounts to decrement" << end(); + 722 trace("mem") << "need to read old value of '" << to_string(canonized_x) << "' to figure out what refcounts to decrement" << end(); 723 // read from canonized_x but without canonizing again 724 reagent/*copy*/ tmp = canonized_x; 725 tmp.properties.push_back(pair<string, string_tree*>("raw", NULL)); 726 vector<double> data = read_memory(tmp); - 727 trace(9999, "mem") << "done reading old value of '" << to_string(canonized_x) << "'" << end(); + 727 trace("mem") << "done reading old value of '" << to_string(canonized_x) << "'" << end(); 728 const container_metadata& metadata = get(Container_metadata, canonized_x.type); - 729 for (map<set<tag_condition_info>, set<address_element_info> >::const_iterator p = metadata.address.begin(); p != metadata.address.end(); ++p) { + 729 for (map<set<tag_condition_info>, set<address_element_info> >::const_iterator p = metadata.address.begin(); p != metadata.address.end(); ++p) { 730 ¦ if (!all_match(data, p->first)) continue; 731 ¦ for (set<address_element_info>::const_iterator info = p->second.begin(); info != p->second.end(); ++info) { 732 ¦ ¦ int element_address = get_or_insert(Memory, canonized_x.value + info->offset); @@ -817,13 +817,13 @@ if ('onhashchange' in window) { 752 a:bar # contains an address 753 ] 754 container bar [ - 755 x:address:num + 755 x:address:num 756 ] 757 def main [ - 758 1:address:num <- new number:type - 759 2:bar <- merge 1:address:num - 760 3:address:foo <- new foo:type - 761 *3:address:foo <- put *3:address:foo, a:offset, 2:bar + 758 1:address:num <- new number:type + 759 2:bar <- merge 1:address:num + 760 3:address:foo <- new foo:type + 761 *3:address:foo <- put *3:address:foo, a:offset, 2:bar 762 ] 763 +run: {1: ("address" "number")} <- new {number: "type"} 764 +mem: incrementing refcount of 1000: 0 -> 1 @@ -835,13 +835,13 @@ if ('onhashchange' in window) { 770 771 :(scenario refcounts_put_index_array) 772 container bar [ - 773 x:address:num + 773 x:address:num 774 ] 775 def main [ - 776 1:address:num <- new number:type - 777 2:bar <- merge 1:address:num - 778 3:address:array:bar <- new bar:type, 3 - 779 *3:address:array:bar <- put-index *3:address:array:bar, 0, 2:bar + 776 1:address:num <- new number:type + 777 2:bar <- merge 1:address:num + 778 3:address:array:bar <- new bar:type, 3 + 779 *3:address:array:bar <- put-index *3:address:array:bar, 0, 2:bar 780 ] 781 +run: {1: ("address" "number")} <- new {number: "type"} 782 +mem: incrementing refcount of 1000: 0 -> 1 @@ -857,11 +857,11 @@ if ('onhashchange' in window) { 792 b:bar # contains an address 793 ] 794 container bar [ - 795 x:address:num + 795 x:address:num 796 ] 797 def main [ - 798 1:address:num <- new number:type - 799 2:bar <- merge 1:address:num + 798 1:address:num <- new number:type + 799 2:bar <- merge 1:address:num 800 3:foo <- merge 1/b, 2:bar 801 5:bar, 6:bool <- maybe-convert 3:foo, 1:variant/b 802 ] @@ -885,19 +885,19 @@ if ('onhashchange' in window) { 820 ] 821 container curr [ 822 x:num - 823 y:address:num # address inside container inside container + 823 y:address:num # address inside container inside container 824 ] 825 def main [ - 826 1:address:num <- new number:type - 827 2:address:curr <- new curr:type - 828 *2:address:curr <- put *2:address:curr, 1:offset/y, 1:address:num - 829 3:address:foo <- new foo:type - 830 *3:address:foo <- put *3:address:foo, 1:offset/b, *2:address:curr - 831 4:foo <- copy *3:address:foo + 826 1:address:num <- new number:type + 827 2:address:curr <- new curr:type + 828 *2:address:curr <- put *2:address:curr, 1:offset/y, 1:address:num + 829 3:address:foo <- new foo:type + 830 *3:address:foo <- put *3:address:foo, 1:offset/b, *2:address:curr + 831 4:foo <- copy *3:address:foo 832 ] - 833 +transform: compute address offsets for container foo + 833 +transform: compute address offsets for container foo 834 +transform: checking container foo, element 1 - 835 +transform: address at offset 3 + 835 +transform: address at offset 3 836 +run: {1: ("address" "number")} <- new {number: "type"} 837 +mem: incrementing refcount of 1000: 0 -> 1 838 # storing an address in a container updates its refcount @@ -918,15 +918,15 @@ if ('onhashchange' in window) { 853 exclusive-container bar [ 854 x:num 855 y:num - 856 z:address:num + 856 z:address:num 857 ] 858 def main [ - 859 1:address:num <- new number:type + 859 1:address:num <- new number:type 860 2:bar <- merge 0/x, 34 861 3:foo <- merge 12, 2:bar 862 5:bar <- merge 1/y, 35 863 6:foo <- merge 13, 5:bar - 864 8:bar <- merge 2/z, 1:address:num + 864 8:bar <- merge 2/z, 1:address:num 865 9:foo <- merge 14, 8:bar 866 11:foo <- copy 9:foo 867 ] @@ -948,13 +948,13 @@ if ('onhashchange' in window) { 883 container bar [ 884 x:num 885 y:num - 886 z:address:num + 886 z:address:num 887 ] 888 def main [ - 889 1:address:num <- new number:type + 889 1:address:num <- new number:type 890 2:foo <- merge 0/a, 34 891 6:foo <- merge 0/a, 35 - 892 10:bar <- merge 2/x, 15/y, 1:address:num + 892 10:bar <- merge 2/x, 15/y, 1:address:num 893 13:foo <- merge 1/b, 10:bar 894 17:foo <- copy 13:foo 895 ] @@ -975,11 +975,11 @@ if ('onhashchange' in window) { 910 ] 911 exclusive-container bar [ 912 x:num - 913 y:address:num + 913 y:address:num 914 ] 915 def main [ - 916 1:address:num <- new number:type - 917 10:foo <- merge 1/b, 1/y, 1:address:num + 916 1:address:num <- new number:type + 917 10:foo <- merge 1/b, 1/y, 1:address:num 918 20:foo <- copy 10:foo 919 ] 920 +run: {1: ("address" "number")} <- new {number: "type"} @@ -992,13 +992,13 @@ if ('onhashchange' in window) { 927 928 :(scenario refcounts_copy_array_within_container) 929 container foo [ - 930 x:address:array:num + 930 x:address:array:num 931 ] 932 def main [ - 933 1:address:array:num <- new number:type, 3 - 934 2:foo <- merge 1:address:array:num - 935 3:address:array:num <- new number:type, 5 - 936 2:foo <- merge 3:address:array:num + 933 1:address:array:num <- new number:type, 3 + 934 2:foo <- merge 1:address:array:num + 935 3:address:array:num <- new number:type, 5 + 936 2:foo <- merge 3:address:array:num 937 ] 938 +run: {1: ("address" "array" "number")} <- new {number: "type"}, {3: "literal"} 939 +mem: incrementing refcount of 1000: 0 -> 1 @@ -1010,22 +1010,22 @@ if ('onhashchange' in window) { 945 :(scenario refcounts_copy_address_within_static_array_within_container) 946 container foo [ 947 a:array:bar:3 - 948 b:address:num + 948 b:address:num 949 ] 950 container bar [ 951 y:num - 952 z:address:num + 952 z:address:num 953 ] 954 def main [ - 955 1:address:num <- new number:type - 956 2:bar <- merge 34, 1:address:num + 955 1:address:num <- new number:type + 956 2:bar <- merge 34, 1:address:num 957 10:array:bar:3 <- create-array 958 put-index 10:array:bar:3, 1, 2:bar - 959 20:foo <- merge 10:array:bar:3, 1:address:num - 960 1:address:num <- copy 0 - 961 2:bar <- merge 34, 1:address:num + 959 20:foo <- merge 10:array:bar:3, 1:address:num + 960 1:address:num <- copy 0 + 961 2:bar <- merge 34, 1:address:num 962 put-index 10:array:bar:3, 1, 2:bar - 963 20:foo <- merge 10:array:bar:3, 1:address:num + 963 20:foo <- merge 10:array:bar:3, 1:address:num 964 ] 965 +run: {1: ("address" "number")} <- new {number: "type"} 966 +mem: incrementing refcount of 1000: 0 -> 1 @@ -1048,24 +1048,24 @@ if ('onhashchange' in window) { 983 984 :(scenario refcounts_handle_exclusive_containers_with_different_tags) 985 container foo1 [ - 986 x:address:num + 986 x:address:num 987 y:num 988 ] 989 container foo2 [ 990 x:num - 991 y:address:num + 991 y:address:num 992 ] 993 exclusive-container bar [ 994 a:foo1 995 b:foo2 996 ] 997 def main [ - 998 1:address:num <- copy 12000/unsafe # pretend allocation - 999 *1:address:num <- copy 34 -1000 2:bar <- merge 0/foo1, 1:address:num, 97 -1001 5:address:num <- copy 13000/unsafe # pretend allocation -1002 *5:address:num <- copy 35 -1003 6:bar <- merge 1/foo2, 98, 5:address:num + 998 1:address:num <- copy 12000/unsafe # pretend allocation + 999 *1:address:num <- copy 34 +1000 2:bar <- merge 0/foo1, 1:address:num, 97 +1001 5:address:num <- copy 13000/unsafe # pretend allocation +1002 *5:address:num <- copy 35 +1003 6:bar <- merge 1/foo2, 98, 5:address:num 1004 2:bar <- copy 6:bar 1005 ] 1006 +run: {2: "bar"} <- merge {0: "literal", "foo1": ()}, {1: ("address" "number")}, {97: "literal"} diff --git a/html/037abandon.cc.html b/html/037abandon.cc.html index 7af0b622..848bbc41 100644 --- a/html/037abandon.cc.html +++ b/html/037abandon.cc.html @@ -68,11 +68,11 @@ if ('onhashchange' in window) { 3 4 :(scenario new_reclaim) 5 def main [ - 6 1:address:num <- new number:type - 7 2:num <- copy 1:address:num # because 1 will get reset during abandon below - 8 1:address:num <- copy 0 # abandon - 9 3:address:num <- new number:type # must be same size as abandoned memory to reuse - 10 4:num <- copy 3:address:num + 6 1:address:num <- new number:type + 7 2:num <- copy 1:address:num # because 1 will get reset during abandon below + 8 1:address:num <- copy 0 # abandon + 9 3:address:num <- new number:type # must be same size as abandoned memory to reuse + 10 4:num <- copy 3:address:num 11 5:bool <- equal 2:num, 4:num 12 ] 13 # both allocations should have returned the same address @@ -80,7 +80,7 @@ if ('onhashchange' in window) { 15 16 :(before "End Decrement Refcount(old_address, payload_type, payload_size)") 17 if (old_refcount == 0) { - 18 trace(9999, "mem") << "automatically abandoning " << old_address << end(); + 18 trace("mem") << "automatically abandoning " << old_address << end(); 19 abandon(old_address, payload_type, payload_size); 20 } 21 @@ -90,8 +90,8 @@ if ('onhashchange' in window) { 25 map<int, int> free_list; 26 27 :(code) - 28 void abandon(int address, const type_tree* payload_type, int payload_size) { - 29 trace(9999, "abandon") << "updating refcounts inside " << address << ": " << to_string(payload_type) << end(); + 28 void abandon(int address, const type_tree* payload_type, int payload_size) { + 29 trace("abandon") << "updating refcounts inside " << address << ": " << to_string(payload_type) << end(); 30 //? Total_free += size; 31 //? ++Num_free; 32 //? cerr << "abandon: " << size << '\n'; @@ -103,30 +103,30 @@ if ('onhashchange' in window) { 38 ¦ assert(element.type->name != "array"); 39 ¦ int element_size = size_of(element); 40 ¦ for (int i = 0; i < array_length; ++i) { - 41 ¦ ¦ element.set_value(address + /*skip refcount and length*/2 + i*element_size); + 41 ¦ ¦ element.set_value(address + /*skip refcount and length*/2 + i*element_size); 42 ¦ ¦ decrement_any_refcounts(element); 43 ¦ } 44 } 45 else if (is_mu_container(payload_type) || is_mu_exclusive_container(payload_type)) { 46 ¦ reagent tmp; 47 ¦ tmp.type = new type_tree(*payload_type); - 48 ¦ tmp.set_value(address + /*skip refcount*/1); + 48 ¦ tmp.set_value(address + /*skip refcount*/1); 49 ¦ decrement_any_refcounts(tmp); 50 } 51 // clear memory - 52 for (int curr = address; curr < address+payload_size; ++curr) + 52 for (int curr = address; curr < address+payload_size; ++curr) 53 ¦ put(Memory, curr, 0); 54 // append existing free list to address - 55 trace(9999, "abandon") << "saving " << address << " in free-list of size " << payload_size << end(); - 56 put(Memory, address, get_or_insert(Current_routine->free_list, payload_size)); - 57 put(Current_routine->free_list, payload_size, address); + 55 trace("abandon") << "saving " << address << " in free-list of size " << payload_size << end(); + 56 put(Memory, address, get_or_insert(Current_routine->free_list, payload_size)); + 57 put(Current_routine->free_list, payload_size, address); 58 } 59 60 :(after "Allocate Special-cases") 61 if (get_or_insert(Current_routine->free_list, size)) { - 62 trace(9999, "abandon") << "picking up space from free-list of size " << size << end(); + 62 trace("abandon") << "picking up space from free-list of size " << size << end(); 63 int result = get_or_insert(Current_routine->free_list, size); - 64 trace(9999, "mem") << "new alloc from free list: " << result << end(); + 64 trace("mem") << "new alloc from free list: " << result << end(); 65 put(Current_routine->free_list, size, get_or_insert(Memory, result)); 66 put(Memory, result, 0); 67 for (int curr = result; curr < result+size; ++curr) { @@ -140,11 +140,11 @@ if ('onhashchange' in window) { 75 76 :(scenario new_differing_size_no_reclaim) 77 def main [ - 78 1:address:num <- new number:type - 79 2:num <- copy 1:address:num - 80 1:address:num <- copy 0 # abandon - 81 3:address:array:num <- new number:type, 2 # different size - 82 4:num <- copy 3:address:array:num + 78 1:address:num <- new number:type + 79 2:num <- copy 1:address:num + 80 1:address:num <- copy 0 # abandon + 81 3:address:array:num <- new number:type, 2 # different size + 82 4:num <- copy 3:address:array:num 83 5:bool <- equal 2:num, 4:num 84 ] 85 # no reuse @@ -152,11 +152,11 @@ if ('onhashchange' in window) { 87 88 :(scenario new_reclaim_array) 89 def main [ - 90 1:address:array:num <- new number:type, 2 - 91 2:num <- copy 1:address:array:num - 92 1:address:array:num <- copy 0 # abandon - 93 3:address:array:num <- new number:type, 2 # same size - 94 4:num <- copy 3:address:array:num + 90 1:address:array:num <- new number:type, 2 + 91 2:num <- copy 1:address:array:num + 92 1:address:array:num <- copy 0 # abandon + 93 3:address:array:num <- new number:type, 2 # same size + 94 4:num <- copy 3:address:array:num 95 5:bool <- equal 2:num, 4:num 96 ] 97 # both calls to new returned identical addresses @@ -164,10 +164,10 @@ if ('onhashchange' in window) { 99 100 :(scenario abandon_on_overwrite) 101 def main [ -102 1:address:num <- new number:type +102 1:address:num <- new number:type 103 # over-writing one allocation with another -104 1:address:num <- new number:type -105 1:address:num <- copy 0 +104 1:address:num <- new number:type +105 1:address:num <- copy 0 106 ] 107 +run: {1: ("address" "number")} <- new {number: "type"} 108 +mem: incrementing refcount of 1000: 0 -> 1 @@ -176,15 +176,15 @@ if ('onhashchange' in window) { 111 112 :(scenario abandon_after_call) 113 def main [ -114 1:address:num <- new number:type +114 1:address:num <- new number:type 115 # passing in addresses to recipes increments refcount -116 foo 1:address:num -117 1:address:num <- copy 0 +116 foo 1:address:num +117 1:address:num <- copy 0 118 ] 119 def foo [ -120 2:address:num <- next-ingredient +120 2:address:num <- next-ingredient 121 # return does NOT yet decrement refcount; memory must be explicitly managed -122 2:address:num <- copy 0 +122 2:address:num <- copy 0 123 ] 124 +run: {1: ("address" "number")} <- new {number: "type"} 125 +mem: incrementing refcount of 1000: 0 -> 1 @@ -201,10 +201,10 @@ if ('onhashchange' in window) { 136 def main [ 137 1:num <- copy 30 138 # allocate an array -139 10:address:array:num <- new number:type, 20 -140 11:num <- copy 10:address:array:num # doesn't increment refcount +139 10:address:array:num <- new number:type, 20 +140 11:num <- copy 10:address:array:num # doesn't increment refcount 141 # allocate another array in its place, implicitly freeing the previous allocation -142 10:address:array:num <- new number:type, 25 +142 10:address:array:num <- new number:type, 25 143 ] 144 +run: {10: ("address" "array" "number")} <- new {number: "type"}, {25: "literal"} 145 # abandoned array is of old size (20, not 25) @@ -213,14 +213,14 @@ if ('onhashchange' in window) { 148 :(scenario refcounts_abandon_address_in_container) 149 # container containing an address 150 container foo [ -151 x:address:num +151 x:address:num 152 ] 153 def main [ -154 1:address:num <- new number:type -155 2:address:foo <- new foo:type -156 *2:address:foo <- put *2:address:foo, x:offset, 1:address:num -157 1:address:num <- copy 0 -158 2:address:foo <- copy 0 +154 1:address:num <- new number:type +155 2:address:foo <- new foo:type +156 *2:address:foo <- put *2:address:foo, x:offset, 1:address:num +157 1:address:num <- copy 0 +158 2:address:foo <- copy 0 159 ] 160 +run: {1: ("address" "number")} <- new {number: "type"} 161 +mem: incrementing refcount of 1000: 0 -> 1 @@ -242,11 +242,11 @@ if ('onhashchange' in window) { 177 # todo: move past dilated reagent 178 :(scenario refcounts_abandon_address_in_array) 179 def main [ -180 1:address:num <- new number:type -181 2:address:array:address:num <- new {(address number): type}, 3 -182 *2:address:array:address:num <- put-index *2:address:array:address:num, 1, 1:address:num -183 1:address:num <- copy 0 -184 2:address:array:address:num <- copy 0 +180 1:address:num <- new number:type +181 2:address:array:address:num <- new {(address number): type}, 3 +182 *2:address:array:address:num <- put-index *2:address:array:address:num, 1, 1:address:num +183 1:address:num <- copy 0 +184 2:address:array:address:num <- copy 0 185 ] 186 +run: {1: ("address" "number")} <- new {number: "type"} 187 +mem: incrementing refcount of 1000: 0 -> 1 @@ -262,16 +262,16 @@ if ('onhashchange' in window) { 197 :(scenario refcounts_abandon_address_in_container_in_array) 198 # container containing an address 199 container foo [ -200 x:address:num +200 x:address:num 201 ] 202 def main [ -203 1:address:num <- new number:type -204 2:address:array:foo <- new foo:type, 3 -205 3:foo <- merge 1:address:num -206 *2:address:array:foo <- put-index *2:address:array:foo, 1, 3:foo -207 1:address:num <- copy 0 +203 1:address:num <- new number:type +204 2:address:array:foo <- new foo:type, 3 +205 3:foo <- merge 1:address:num +206 *2:address:array:foo <- put-index *2:address:array:foo, 1, 3:foo +207 1:address:num <- copy 0 208 3:foo <- merge 0 -209 2:address:array:foo <- copy 0 +209 2:address:array:foo <- copy 0 210 ] 211 +run: {1: ("address" "number")} <- new {number: "type"} 212 +mem: incrementing refcount of 1000: 0 -> 1 @@ -290,12 +290,12 @@ if ('onhashchange' in window) { 225 226 :(scenario refcounts_abandon_array_within_container) 227 container foo [ -228 x:address:array:num +228 x:address:array:num 229 ] 230 def main [ -231 1:address:array:num <- new number:type, 3 -232 2:foo <- merge 1:address:array:num -233 1:address:array:num <- copy 0 +231 1:address:array:num <- new number:type, 3 +232 2:foo <- merge 1:address:array:num +233 1:address:array:num <- copy 0 234 2:foo <- copy 0 235 ] 236 +run: {1: ("address" "array" "number")} <- new {number: "type"}, {3: "literal"} diff --git a/html/038new_text.cc.html b/html/038new_text.cc.html index 7dab898f..6b422c40 100644 --- a/html/038new_text.cc.html +++ b/html/038new_text.cc.html @@ -95,7 +95,7 @@ if ('onhashchange' in window) { 30 if (is_literal_text(current_instruction().ingredients.at(0))) { 31 ¦ products.resize(1); 32 ¦ products.at(0).push_back(new_mu_text(current_instruction().ingredients.at(0).name)); - 33 ¦ trace(9999, "mem") << "new string alloc: " << products.at(0).at(0) << end(); + 33 ¦ trace("mem") << "new string alloc: " << products.at(0).at(0) << end(); 34 ¦ break; 35 } 36 @@ -106,10 +106,10 @@ if ('onhashchange' in window) { 41 //? Total_alloc += string_length+1; 42 //? ++Num_alloc; 43 int result = allocate(string_length+/*array length*/1); - 44 trace(9999, "mem") << "storing string refcount 0 in location " << result << end(); + 44 trace("mem") << "storing string refcount 0 in location " << result << end(); 45 put(Memory, result, 0); 46 int curr_address = result+/*skip refcount*/1; - 47 trace(9999, "mem") << "storing string length " << string_length << " in location " << curr_address << end(); + 47 trace("mem") << "storing string length " << string_length << " in location " << curr_address << end(); 48 put(Memory, curr_address, string_length); 49 ++curr_address; // skip length 50 int curr = 0; @@ -118,7 +118,7 @@ if ('onhashchange' in window) { 53 ¦ uint32_t curr_character; 54 ¦ assert(curr < SIZE(contents)); 55 ¦ tb_utf8_char_to_unicode(&curr_character, &raw_contents[curr]); - 56 ¦ trace(9999, "mem") << "storing string character " << curr_character << " in location " << curr_address << end(); + 56 ¦ trace("mem") << "storing string character " << curr_character << " in location " << curr_address << end(); 57 ¦ put(Memory, curr_address, curr_character); 58 ¦ curr += tb_utf8_char_length(raw_contents[curr]); 59 ¦ ++curr_address; @@ -185,7 +185,7 @@ if ('onhashchange' in window) { 120 :(scenario new_string_overflow) 121 % Initial_memory_per_routine = 3; 122 def main [ -123 1:address:num/raw <- new number:type +123 1:address:num/raw <- new number:type 124 2:text/raw <- new [a] # not enough room in initial page, if you take the refcount and array length into account 125 ] 126 +new: routine allocated memory from 1000 to 1003 @@ -205,10 +205,10 @@ if ('onhashchange' in window) { 140 return result; 141 } 142 -143 string read_mu_text(int address) { -144 if (address == 0) return ""; +143 string read_mu_text(int address) { +144 if (address == 0) return ""; 145 ++address; // skip refcount -146 int length = get_or_insert(Memory, address); +146 int length = get_or_insert(Memory, address); 147 if (length == 0) return ""; 148 return read_mu_characters(address+1, length); 149 } diff --git a/html/043space.cc.html b/html/043space.cc.html index 66900af8..ac9c1f97 100644 --- a/html/043space.cc.html +++ b/html/043space.cc.html @@ -71,480 +71,479 @@ if ('onhashchange' in window) { 5 //: Spaces are often called 'scopes' in other languages. Stack frames are a 6 //: limited form of space that can't outlive callers. 7 //: - 8 //: Warning: messing with 'default-space' can corrupt memory. Don't do things - 9 //: like initialize default-space with some other function's default-space. - 10 //: Later we'll see how to chain spaces safely. - 11 - 12 //: Under the hood, a space is an array of locations in memory. - 13 :(before "End Mu Types Initialization") - 14 put(Type_abbreviations, "space", new_type_tree("address:array:location")); - 15 - 16 :(scenario set_default_space) - 17 # if default-space is 10, and if an array of 5 locals lies from location 12 to 16 (inclusive), - 18 # then local 0 is really location 12, local 1 is really location 13, and so on. - 19 def main [ - 20 # pretend address:array:location; in practice we'll use 'new' - 21 10:num <- copy 0 # refcount - 22 11:num <- copy 5 # length - 23 default-space:space <- copy 10/unsafe - 24 1:num <- copy 23 - 25 ] - 26 +mem: storing 23 in location 13 - 27 - 28 :(scenario lookup_sidesteps_default_space) - 29 def main [ - 30 # pretend pointer from outside (2000 reserved for refcount) - 31 2001:num <- copy 34 - 32 # pretend address:array:location; in practice we'll use 'new' - 33 1000:num <- copy 0 # refcount - 34 1001:num <- copy 5 # length - 35 # actual start of this recipe - 36 default-space:space <- copy 1000/unsafe - 37 1:&:num <- copy 2000/unsafe # even local variables always contain raw addresses - 38 8:num/raw <- copy *1:&:num - 39 ] - 40 +mem: storing 34 in location 8 - 41 - 42 //: precondition: disable name conversion for 'default-space' - 43 - 44 :(scenario convert_names_passes_default_space) - 45 % Hide_errors = true; - 46 def main [ - 47 default-space:num, x:num <- copy 0, 1 - 48 ] - 49 +name: assign x 1 - 50 -name: assign default-space 1 - 51 - 52 :(before "End is_disqualified Special-cases") - 53 if (x.name == "default-space") - 54 x.initialized = true; - 55 :(before "End is_special_name Special-cases") - 56 if (s == "default-space") return true; - 57 - 58 //: core implementation - 59 - 60 :(before "End call Fields") - 61 int default_space; - 62 :(before "End call Constructor") - 63 default_space = 0; - 64 - 65 :(before "Begin canonize(x) Lookups") - 66 absolutize(x); - 67 :(code) - 68 void absolutize(reagent& x) { - 69 if (is_raw(x) || is_dummy(x)) return; - 70 if (x.name == "default-space") return; - 71 if (!x.initialized) - 72 ¦ raise << to_original_string(current_instruction()) << ": reagent not initialized: '" << x.original_string << "'\n" << end(); - 73 x.set_value(address(x.value, space_base(x))); - 74 x.properties.push_back(pair<string, string_tree*>("raw", NULL)); - 75 assert(is_raw(x)); - 76 } - 77 - 78 //: hook replaced in a later layer - 79 int space_base(const reagent& x) { - 80 return current_call().default_space ? (current_call().default_space+/*skip refcount*/1) : 0; - 81 } - 82 - 83 int address(int offset, int base) { - 84 assert(offset >= 0); - 85 if (base == 0) return offset; // raw - 86 int size = get_or_insert(Memory, base); - 87 if (offset >= size) { - 88 ¦ // todo: test - 89 ¦ raise << current_recipe_name() << ": location " << offset << " is out of bounds " << size << " at " << base << '\n' << end(); - 90 ¦ DUMP(""); - 91 ¦ exit(1); - 92 ¦ return 0; - 93 } - 94 return base + /*skip length*/1 + offset; - 95 } - 96 - 97 //: reads and writes to the 'default-space' variable have special behavior - 98 - 99 :(after "Begin Preprocess write_memory(x, data)") -100 if (x.name == "default-space") { -101 if (!scalar(data) || !is_mu_space(x)) -102 ¦ raise << maybe(current_recipe_name()) << "'default-space' should be of type address:array:location, but is " << to_string(x.type) << '\n' << end(); -103 current_call().default_space = data.at(0); -104 return; -105 } -106 :(code) -107 bool is_mu_space(reagent/*copy*/ x) { -108 canonize_type(x); -109 if (!is_compound_type_starting_with(x.type, "address")) return false; -110 drop_from_type(x, "address"); -111 if (!is_compound_type_starting_with(x.type, "array")) return false; -112 drop_from_type(x, "array"); -113 return x.type && x.type->atom && x.type->name == "location"; -114 } -115 -116 :(scenario get_default_space) -117 def main [ -118 default-space:space <- copy 10/unsafe -119 1:space/raw <- copy default-space:space -120 ] -121 +mem: storing 10 in location 1 -122 -123 :(after "Begin Preprocess read_memory(x)") -124 if (x.name == "default-space") { -125 vector<double> result; -126 result.push_back(current_call().default_space); -127 return result; -128 } -129 -130 //:: fix 'get' -131 -132 :(scenario lookup_sidesteps_default_space_in_get) -133 def main [ -134 # pretend pointer to container from outside (2000 reserved for refcount) -135 2001:num <- copy 34 -136 2002:num <- copy 35 -137 # pretend address:array:location; in practice we'll use 'new' -138 1000:num <- copy 0 # refcount -139 1001:num <- copy 5 # length -140 # actual start of this recipe -141 default-space:space <- copy 1000/unsafe -142 1:&:point <- copy 2000/unsafe -143 9:num/raw <- get *1:&:point, 1:offset -144 ] -145 +mem: storing 35 in location 9 -146 -147 :(before "Read element" following "case GET:") -148 element.properties.push_back(pair<string, string_tree*>("raw", NULL)); -149 -150 //:: fix 'index' -151 -152 :(scenario lookup_sidesteps_default_space_in_index) -153 def main [ -154 # pretend pointer to array from outside (2000 reserved for refcount) -155 2001:num <- copy 2 # length -156 2002:num <- copy 34 -157 2003:num <- copy 35 -158 # pretend address:array:location; in practice we'll use 'new' -159 1000:num <- copy 0 # refcount -160 1001:num <- copy 5 # length -161 # actual start of this recipe -162 default-space:space <- copy 1000/unsafe -163 1:&:@:num <- copy 2000/unsafe -164 9:num/raw <- index *1:&:@:num, 1 -165 ] -166 +mem: storing 35 in location 9 -167 -168 :(before "Read element" following "case INDEX:") -169 element.properties.push_back(pair<string, string_tree*>("raw", NULL)); -170 -171 //:: 'local-scope' is a convenience operation to automatically deduce -172 //:: the amount of space to allocate in a default space with names -173 -174 :(scenario local_scope) -175 def main [ -176 local-scope -177 x:num <- copy 0 -178 y:num <- copy 3 -179 ] -180 # allocate space for x and y, as well as the chaining slot at 0 -181 +mem: array length is 3 -182 -183 :(before "End is_disqualified Special-cases") -184 if (x.name == "number-of-locals") -185 x.initialized = true; -186 :(before "End is_special_name Special-cases") -187 if (s == "number-of-locals") return true; -188 -189 :(before "End Rewrite Instruction(curr, recipe result)") -190 // rewrite 'local-scope' to -191 // ``` -192 // default-space:space <- new location:type, number-of-locals:literal -193 // ``` -194 // where number-of-locals is Name[recipe][""] -195 if (curr.name == "local-scope") { -196 rewrite_default_space_instruction(curr); -197 } -198 :(code) -199 void rewrite_default_space_instruction(instruction& curr) { -200 if (!curr.ingredients.empty()) -201 ¦ raise << "'" << to_original_string(curr) << "' can't take any ingredients\n" << end(); -202 curr.name = "new"; -203 curr.ingredients.push_back(reagent("location:type")); -204 curr.ingredients.push_back(reagent("number-of-locals:literal")); -205 if (!curr.products.empty()) -206 ¦ raise << "new-default-space can't take any results\n" << end(); -207 curr.products.push_back(reagent("default-space:space")); -208 } -209 :(after "Begin Preprocess read_memory(x)") -210 if (x.name == "number-of-locals") { -211 vector<double> result; -212 result.push_back(Name[get(Recipe_ordinal, current_recipe_name())][""]); -213 if (result.back() == 0) -214 ¦ raise << "no space allocated for default-space in recipe " << current_recipe_name() << "; are you using names?\n" << end(); -215 return result; -216 } -217 :(after "Begin Preprocess write_memory(x, data)") -218 if (x.name == "number-of-locals") { -219 raise << maybe(current_recipe_name()) << "can't write to special name 'number-of-locals'\n" << end(); -220 return; -221 } -222 -223 //:: try to reclaim the default-space when a recipe returns -224 -225 :(scenario local_scope_reclaimed_on_return) -226 def main [ -227 1:num <- foo -228 2:num <- foo -229 3:bool <- equal 1:num, 2:num -230 ] -231 def foo [ -232 local-scope -233 result:num <- copy default-space:space -234 return result:num -235 ] -236 # both calls to foo should have received the same default-space -237 +mem: storing 1 in location 3 -238 -239 //: todo: do this in a transform, rather than magically in the 'return' instruction -240 :(after "Falling Through End Of Recipe") -241 reclaim_default_space(); -242 :(after "Begin Return") -243 reclaim_default_space(); -244 :(code) -245 void reclaim_default_space() { -246 if (!Reclaim_memory) return; -247 reagent default_space("default-space:address:array:location"); -248 decrement_any_refcounts(default_space); -249 } -250 :(after "Begin Decrement Refcounts(canonized_x)") -251 if (is_mu_space(canonized_x)) { -252 int space_address = (canonized_x.name == "default-space") ? current_call().default_space : get_or_insert(Memory, canonized_x.value); -253 if (space_address == 0) return; -254 // this branch relies on global state -255 string recipe_name; -256 if (has_property(canonized_x, "names")) { -257 ¦ assert(property(canonized_x, "names")->atom); -258 ¦ recipe_name = property(canonized_x, "names")->value; -259 } -260 else { -261 ¦ if (canonized_x.name != "default-space") -262 ¦ ¦ cerr << current_recipe_name() << ": " << to_string(canonized_x) << '\n'; -263 ¦ assert(canonized_x.name == "default-space"); -264 ¦ recipe_name = current_recipe_name(); -265 } -266 const recipe_ordinal space_recipe_ordinal = get(Recipe_ordinal, recipe_name); -267 const recipe& space_recipe = get(Recipe, space_recipe_ordinal); -268 if (canonized_x.name == "default-space" && !has_property(canonized_x, "names") && !starts_by_setting_default_space(space_recipe)) return; -269 // Reclaim Space(space_address, space_recipe_ordinal, space_recipe) -270 decrement_refcount(space_address, canonized_x.type->right, -271 ¦ ¦ /*refcount*/1 + /*array length*/1 + /*number-of-locals*/Name[space_recipe_ordinal][""]); -272 return; -273 } -274 :(code) -275 bool starts_by_setting_default_space(const recipe& r) { -276 return !r.steps.empty() -277 ¦ ¦ && !r.steps.at(0).products.empty() -278 ¦ ¦ && r.steps.at(0).products.at(0).name == "default-space"; -279 } -280 -281 //: -282 -283 :(scenario local_scope_reclaims_locals) -284 def main [ -285 local-scope -286 x:text <- new [abc] -287 ] -288 # x -289 +mem: automatically abandoning 1004 -290 # local-scope -291 +mem: automatically abandoning 1000 -292 -293 :(before "Reclaim Space(space_address, space_recipe_ordinal, space_recipe)") -294 if (get_or_insert(Memory, space_address) <= 1) { -295 set<string> reclaimed_locals; -296 trace(9999, "mem") << "trying to reclaim locals" << end(); -297 // update any refcounts for variables in the space -- in the context of the space -298 call_stack calls_stash = save_call_stack(space_address, space_recipe_ordinal); -299 Current_routine->calls.swap(calls_stash); -300 // no early returns until we restore 'calls' below -301 for (int i = /*leave default space for last*/1; i < SIZE(space_recipe.steps); ++i) { -302 ¦ const instruction& inst = space_recipe.steps.at(i); -303 ¦ for (int i = 0; i < SIZE(inst.products); ++i) { -304 ¦ ¦ reagent/*copy*/ product = inst.products.at(i); -305 ¦ ¦ if (reclaimed_locals.find(product.name) != reclaimed_locals.end()) continue; -306 ¦ ¦ reclaimed_locals.insert(product.name); -307 ¦ ¦ // local variables only -308 ¦ ¦ if (has_property(product, "lookup")) continue; -309 ¦ ¦ if (has_property(product, "raw")) continue; // tests often want to check such locations after they run -310 ¦ ¦ // End Checks For Reclaiming Locals -311 ¦ ¦ trace(9999, "mem") << "trying to reclaim local " << product.original_string << end(); -312 ¦ ¦ canonize(product); -313 ¦ ¦ decrement_any_refcounts(product); -314 ¦ } -315 } -316 Current_routine->calls.swap(calls_stash); // restore -317 } -318 :(code) -319 call_stack save_call_stack(int space_address, recipe_ordinal space_recipe_ordinal) { -320 call dummy_call(space_recipe_ordinal); -321 dummy_call.default_space = space_address; -322 call_stack result; -323 result.push_front(dummy_call); -324 return result; -325 } -326 -327 :(scenario local_variables_can_outlive_call) -328 def main [ -329 local-scope -330 x:&:num <- new num:type -331 y:space <- copy default-space:space -332 ] -333 -mem: automatically abandoning 1005 -334 -335 //: -336 -337 :(scenario local_scope_does_not_reclaim_escaping_locals) -338 def main [ -339 1:text <- foo -340 ] -341 def foo [ -342 local-scope -343 x:text <- new [abc] -344 return x:text -345 ] -346 # local-scope -347 +mem: automatically abandoning 1000 -348 # x -349 -mem: automatically abandoning 1004 -350 -351 :(after "Begin Return") // before reclaiming default-space -352 increment_refcounts_of_return_ingredients(ingredients); -353 :(code) -354 void increment_refcounts_of_return_ingredients(const vector<vector<double> >& ingredients) { -355 assert(current_instruction().operation == RETURN); -356 if (SIZE(Current_routine->calls) == 1) // no caller to receive result -357 ¦ return; -358 const instruction& caller_instruction = to_instruction(*++Current_routine->calls.begin()); -359 for (int i = 0; i < min(SIZE(current_instruction().ingredients), SIZE(caller_instruction.products)); ++i) { -360 ¦ if (!is_dummy(caller_instruction.products.at(i))) { -361 ¦ ¦ // no need to canonize ingredient because we ignore its value -362 ¦ ¦ increment_any_refcounts(current_instruction().ingredients.at(i), ingredients.at(i)); -363 ¦ } -364 } -365 } -366 -367 //: -368 -369 :(scenario local_scope_frees_up_addresses_inside_containers) -370 container foo [ -371 x:num -372 y:&:num -373 ] -374 def main [ -375 local-scope -376 x:&:num <- new number:type -377 y:foo <- merge 34, x:&:num -378 # x and y are both cleared when main returns -379 ] -380 +mem: automatically abandoning 1006 -381 -382 :(scenario local_scope_returns_addresses_inside_containers) -383 container foo [ -384 x:num -385 y:&:num -386 ] -387 def f [ -388 local-scope -389 x:&:num <- new number:type -390 *x:&:num <- copy 12 -391 y:foo <- merge 34, x:&:num -392 # since y is 'escaping' f, it should not be cleared -393 return y:foo -394 ] -395 def main [ -396 1:foo <- f -397 3:num <- get 1:foo, x:offset -398 4:&:num <- get 1:foo, y:offset -399 5:num <- copy *4:&:num -400 1:foo <- put 1:foo, y:offset, 0 -401 4:&:num <- copy 0 -402 ] -403 +mem: storing 34 in location 1 -404 +mem: storing 1006 in location 2 -405 +mem: storing 34 in location 3 -406 # refcount of 1:foo shouldn't include any stray ones from f -407 +run: {4: ("address" "number")} <- get {1: "foo"}, {y: "offset"} -408 +mem: incrementing refcount of 1006: 1 -> 2 -409 # 1:foo wasn't abandoned/cleared -410 +run: {5: "number"} <- copy {4: ("address" "number"), "lookup": ()} -411 +mem: storing 12 in location 5 -412 +run: {1: "foo"} <- put {1: "foo"}, {y: "offset"}, {0: "literal"} -413 +mem: decrementing refcount of 1006: 2 -> 1 -414 +run: {4: ("address" "number")} <- copy {0: "literal"} -415 +mem: decrementing refcount of 1006: 1 -> 0 -416 +mem: automatically abandoning 1006 -417 -418 :(scenario local_scope_claims_return_values_when_not_saved) -419 def f [ -420 local-scope -421 x:&:num <- new number:type -422 return x:&:num -423 ] -424 def main [ -425 f # doesn't save result -426 ] -427 # x reclaimed -428 +mem: automatically abandoning 1004 -429 # f's local scope reclaimed -430 +mem: automatically abandoning 1000 -431 -432 //:: all recipes must set default-space one way or another -433 -434 :(before "End Globals") -435 bool Hide_missing_default_space_errors = true; -436 :(before "End Checks") -437 Transform.push_back(check_default_space); // idempotent -438 :(code) -439 void check_default_space(const recipe_ordinal r) { -440 if (Hide_missing_default_space_errors) return; // skip previous core tests; this is only for Mu code -441 const recipe& caller = get(Recipe, r); -442 // End check_default_space Special-cases -443 // assume recipes with only numeric addresses know what they're doing (usually tests) -444 if (!contains_non_special_name(r)) return; -445 trace(9991, "transform") << "--- check that recipe " << caller.name << " sets default-space" << end(); -446 if (caller.steps.empty()) return; -447 if (!starts_by_setting_default_space(caller)) -448 ¦ raise << caller.name << " does not seem to start with 'local-scope' or 'default-space'\n" << end(); -449 } -450 :(after "Load Mu Prelude") -451 Hide_missing_default_space_errors = false; -452 :(after "Test Runs") -453 Hide_missing_default_space_errors = true; -454 :(after "Running Main") -455 Hide_missing_default_space_errors = false; -456 -457 :(code) -458 bool contains_non_special_name(const recipe_ordinal r) { -459 for (map<string, int>::iterator p = Name[r].begin(); p != Name[r].end(); ++p) { -460 ¦ if (p->first.empty()) continue; -461 ¦ if (p->first.find("stash_") == 0) continue; // generated by rewrite_stashes_to_text (cross-layer) -462 ¦ if (!is_special_name(p->first)) -463 ¦ ¦ return true; -464 } -465 return false; -466 } -467 -468 // reagent comparison -- only between reagents in a single recipe -469 bool operator==(const reagent& a, const reagent& b) { -470 if (a.name != b.name) return false; -471 if (property(a, "space") != property(b, "space")) return false; -472 return true; -473 } -474 -475 bool operator<(const reagent& a, const reagent& b) { -476 int aspace = 0, bspace = 0; -477 if (has_property(a, "space")) aspace = to_integer(property(a, "space")->value); -478 if (has_property(b, "space")) bspace = to_integer(property(b, "space")->value); -479 if (aspace != bspace) return aspace < bspace; -480 return a.name < b.name; -481 } + 8 //: Warning: messing with 'default-space' can corrupt memory. Don't share + 9 //: default-space between recipes. Later we'll see how to chain spaces safely. + 10 + 11 //: Under the hood, a space is an array of locations in memory. + 12 :(before "End Mu Types Initialization") + 13 put(Type_abbreviations, "space", new_type_tree("address:array:location")); + 14 + 15 :(scenario set_default_space) + 16 # if default-space is 10, and if an array of 5 locals lies from location 12 to 16 (inclusive), + 17 # then local 0 is really location 12, local 1 is really location 13, and so on. + 18 def main [ + 19 # pretend address:array:location; in practice we'll use 'new' + 20 10:num <- copy 0 # refcount + 21 11:num <- copy 5 # length + 22 default-space:space <- copy 10/unsafe + 23 1:num <- copy 23 + 24 ] + 25 +mem: storing 23 in location 13 + 26 + 27 :(scenario lookup_sidesteps_default_space) + 28 def main [ + 29 # pretend pointer from outside (2000 reserved for refcount) + 30 2001:num <- copy 34 + 31 # pretend address:array:location; in practice we'll use 'new' + 32 1000:num <- copy 0 # refcount + 33 1001:num <- copy 5 # length + 34 # actual start of this recipe + 35 default-space:space <- copy 1000/unsafe + 36 1:&:num <- copy 2000/unsafe # even local variables always contain raw addresses + 37 8:num/raw <- copy *1:&:num + 38 ] + 39 +mem: storing 34 in location 8 + 40 + 41 //: precondition: disable name conversion for 'default-space' + 42 + 43 :(scenario convert_names_passes_default_space) + 44 % Hide_errors = true; + 45 def main [ + 46 default-space:num, x:num <- copy 0, 1 + 47 ] + 48 +name: assign x 1 + 49 -name: assign default-space 1 + 50 + 51 :(before "End is_disqualified Special-cases") + 52 if (x.name == "default-space") + 53 x.initialized = true; + 54 :(before "End is_special_name Special-cases") + 55 if (s == "default-space") return true; + 56 + 57 //: core implementation + 58 + 59 :(before "End call Fields") + 60 int default_space; + 61 :(before "End call Constructor") + 62 default_space = 0; + 63 + 64 :(before "Begin canonize(x) Lookups") + 65 absolutize(x); + 66 :(code) + 67 void absolutize(reagent& x) { + 68 if (is_raw(x) || is_dummy(x)) return; + 69 if (x.name == "default-space") return; + 70 if (!x.initialized) + 71 ¦ raise << to_original_string(current_instruction()) << ": reagent not initialized: '" << x.original_string << "'\n" << end(); + 72 x.set_value(address(x.value, space_base(x))); + 73 x.properties.push_back(pair<string, string_tree*>("raw", NULL)); + 74 assert(is_raw(x)); + 75 } + 76 + 77 //: hook replaced in a later layer + 78 int space_base(const reagent& x) { + 79 return current_call().default_space ? (current_call().default_space+/*skip refcount*/1) : 0; + 80 } + 81 + 82 int address(int offset, int base) { + 83 assert(offset >= 0); + 84 if (base == 0) return offset; // raw + 85 int size = get_or_insert(Memory, base); + 86 if (offset >= size) { + 87 ¦ // todo: test + 88 ¦ raise << current_recipe_name() << ": location " << offset << " is out of bounds " << size << " at " << base << '\n' << end(); + 89 ¦ DUMP(""); + 90 ¦ exit(1); + 91 ¦ return 0; + 92 } + 93 return base + /*skip length*/1 + offset; + 94 } + 95 + 96 //: reads and writes to the 'default-space' variable have special behavior + 97 + 98 :(after "Begin Preprocess write_memory(x, data)") + 99 if (x.name == "default-space") { +100 if (!scalar(data) || !is_mu_space(x)) +101 ¦ raise << maybe(current_recipe_name()) << "'default-space' should be of type address:array:location, but is " << to_string(x.type) << '\n' << end(); +102 current_call().default_space = data.at(0); +103 return; +104 } +105 :(code) +106 bool is_mu_space(reagent/*copy*/ x) { +107 canonize_type(x); +108 if (!is_compound_type_starting_with(x.type, "address")) return false; +109 drop_from_type(x, "address"); +110 if (!is_compound_type_starting_with(x.type, "array")) return false; +111 drop_from_type(x, "array"); +112 return x.type && x.type->atom && x.type->name == "location"; +113 } +114 +115 :(scenario get_default_space) +116 def main [ +117 default-space:space <- copy 10/unsafe +118 1:space/raw <- copy default-space:space +119 ] +120 +mem: storing 10 in location 1 +121 +122 :(after "Begin Preprocess read_memory(x)") +123 if (x.name == "default-space") { +124 vector<double> result; +125 result.push_back(current_call().default_space); +126 return result; +127 } +128 +129 //:: fix 'get' +130 +131 :(scenario lookup_sidesteps_default_space_in_get) +132 def main [ +133 # pretend pointer to container from outside (2000 reserved for refcount) +134 2001:num <- copy 34 +135 2002:num <- copy 35 +136 # pretend address:array:location; in practice we'll use 'new' +137 1000:num <- copy 0 # refcount +138 1001:num <- copy 5 # length +139 # actual start of this recipe +140 default-space:space <- copy 1000/unsafe +141 1:&:point <- copy 2000/unsafe +142 9:num/raw <- get *1:&:point, 1:offset +143 ] +144 +mem: storing 35 in location 9 +145 +146 :(before "Read element" following "case GET:") +147 element.properties.push_back(pair<string, string_tree*>("raw", NULL)); +148 +149 //:: fix 'index' +150 +151 :(scenario lookup_sidesteps_default_space_in_index) +152 def main [ +153 # pretend pointer to array from outside (2000 reserved for refcount) +154 2001:num <- copy 2 # length +155 2002:num <- copy 34 +156 2003:num <- copy 35 +157 # pretend address:array:location; in practice we'll use 'new' +158 1000:num <- copy 0 # refcount +159 1001:num <- copy 5 # length +160 # actual start of this recipe +161 default-space:space <- copy 1000/unsafe +162 1:&:@:num <- copy 2000/unsafe +163 9:num/raw <- index *1:&:@:num, 1 +164 ] +165 +mem: storing 35 in location 9 +166 +167 :(before "Read element" following "case INDEX:") +168 element.properties.push_back(pair<string, string_tree*>("raw", NULL)); +169 +170 //:: 'local-scope' is a convenience operation to automatically deduce +171 //:: the amount of space to allocate in a default space with names +172 +173 :(scenario local_scope) +174 def main [ +175 local-scope +176 x:num <- copy 0 +177 y:num <- copy 3 +178 ] +179 # allocate space for x and y, as well as the chaining slot at 0 +180 +mem: array length is 3 +181 +182 :(before "End is_disqualified Special-cases") +183 if (x.name == "number-of-locals") +184 x.initialized = true; +185 :(before "End is_special_name Special-cases") +186 if (s == "number-of-locals") return true; +187 +188 :(before "End Rewrite Instruction(curr, recipe result)") +189 // rewrite 'local-scope' to +190 // ``` +191 // default-space:space <- new location:type, number-of-locals:literal +192 // ``` +193 // where number-of-locals is Name[recipe][""] +194 if (curr.name == "local-scope") { +195 rewrite_default_space_instruction(curr); +196 } +197 :(code) +198 void rewrite_default_space_instruction(instruction& curr) { +199 if (!curr.ingredients.empty()) +200 ¦ raise << "'" << to_original_string(curr) << "' can't take any ingredients\n" << end(); +201 curr.name = "new"; +202 curr.ingredients.push_back(reagent("location:type")); +203 curr.ingredients.push_back(reagent("number-of-locals:literal")); +204 if (!curr.products.empty()) +205 ¦ raise << "new-default-space can't take any results\n" << end(); +206 curr.products.push_back(reagent("default-space:space")); +207 } +208 :(after "Begin Preprocess read_memory(x)") +209 if (x.name == "number-of-locals") { +210 vector<double> result; +211 result.push_back(Name[get(Recipe_ordinal, current_recipe_name())][""]); +212 if (result.back() == 0) +213 ¦ raise << "no space allocated for default-space in recipe " << current_recipe_name() << "; are you using names?\n" << end(); +214 return result; +215 } +216 :(after "Begin Preprocess write_memory(x, data)") +217 if (x.name == "number-of-locals") { +218 raise << maybe(current_recipe_name()) << "can't write to special name 'number-of-locals'\n" << end(); +219 return; +220 } +221 +222 //:: try to reclaim the default-space when a recipe returns +223 +224 :(scenario local_scope_reclaimed_on_return) +225 def main [ +226 1:num <- foo +227 2:num <- foo +228 3:bool <- equal 1:num, 2:num +229 ] +230 def foo [ +231 local-scope +232 result:num <- copy default-space:space +233 return result:num +234 ] +235 # both calls to foo should have received the same default-space +236 +mem: storing 1 in location 3 +237 +238 //: todo: do this in a transform, rather than magically in the 'return' instruction +239 :(after "Falling Through End Of Recipe") +240 reclaim_default_space(); +241 :(after "Begin Return") +242 reclaim_default_space(); +243 :(code) +244 void reclaim_default_space() { +245 if (!Reclaim_memory) return; +246 reagent default_space("default-space:address:array:location"); +247 decrement_any_refcounts(default_space); +248 } +249 :(after "Begin Decrement Refcounts(canonized_x)") +250 if (is_mu_space(canonized_x)) { +251 int space_address = (canonized_x.name == "default-space") ? current_call().default_space : get_or_insert(Memory, canonized_x.value); +252 if (space_address == 0) return; +253 // this branch relies on global state +254 string recipe_name; +255 if (has_property(canonized_x, "names")) { +256 ¦ assert(property(canonized_x, "names")->atom); +257 ¦ recipe_name = property(canonized_x, "names")->value; +258 } +259 else { +260 ¦ if (canonized_x.name != "default-space") +261 ¦ ¦ cerr << current_recipe_name() << ": " << to_string(canonized_x) << '\n'; +262 ¦ assert(canonized_x.name == "default-space"); +263 ¦ recipe_name = current_recipe_name(); +264 } +265 const recipe_ordinal space_recipe_ordinal = get(Recipe_ordinal, recipe_name); +266 const recipe& space_recipe = get(Recipe, space_recipe_ordinal); +267 if (canonized_x.name == "default-space" && !has_property(canonized_x, "names") && !starts_by_setting_default_space(space_recipe)) return; +268 // Reclaim Space(space_address, space_recipe_ordinal, space_recipe) +269 decrement_refcount(space_address, canonized_x.type->right, +270 ¦ ¦ /*refcount*/1 + /*array length*/1 + /*number-of-locals*/Name[space_recipe_ordinal][""]); +271 return; +272 } +273 :(code) +274 bool starts_by_setting_default_space(const recipe& r) { +275 return !r.steps.empty() +276 ¦ ¦ && !r.steps.at(0).products.empty() +277 ¦ ¦ && r.steps.at(0).products.at(0).name == "default-space"; +278 } +279 +280 //: +281 +282 :(scenario local_scope_reclaims_locals) +283 def main [ +284 local-scope +285 x:text <- new [abc] +286 ] +287 # x +288 +mem: automatically abandoning 1004 +289 # local-scope +290 +mem: automatically abandoning 1000 +291 +292 :(before "Reclaim Space(space_address, space_recipe_ordinal, space_recipe)") +293 if (get_or_insert(Memory, space_address) <= 1) { +294 set<string> reclaimed_locals; +295 trace("mem") << "trying to reclaim locals" << end(); +296 // update any refcounts for variables in the space -- in the context of the space +297 call_stack calls_stash = save_call_stack(space_address, space_recipe_ordinal); +298 Current_routine->calls.swap(calls_stash); +299 // no early returns until we restore 'calls' below +300 for (int i = /*leave default space for last*/1; i < SIZE(space_recipe.steps); ++i) { +301 ¦ const instruction& inst = space_recipe.steps.at(i); +302 ¦ for (int i = 0; i < SIZE(inst.products); ++i) { +303 ¦ ¦ reagent/*copy*/ product = inst.products.at(i); +304 ¦ ¦ if (reclaimed_locals.find(product.name) != reclaimed_locals.end()) continue; +305 ¦ ¦ reclaimed_locals.insert(product.name); +306 ¦ ¦ // local variables only +307 ¦ ¦ if (has_property(product, "lookup")) continue; +308 ¦ ¦ if (has_property(product, "raw")) continue; // tests often want to check such locations after they run +309 ¦ ¦ // End Checks For Reclaiming Locals +310 ¦ ¦ trace("mem") << "trying to reclaim local " << product.original_string << end(); +311 ¦ ¦ canonize(product); +312 ¦ ¦ decrement_any_refcounts(product); +313 ¦ } +314 } +315 Current_routine->calls.swap(calls_stash); // restore +316 } +317 :(code) +318 call_stack save_call_stack(int space_address, recipe_ordinal space_recipe_ordinal) { +319 call dummy_call(space_recipe_ordinal); +320 dummy_call.default_space = space_address; +321 call_stack result; +322 result.push_front(dummy_call); +323 return result; +324 } +325 +326 :(scenario local_variables_can_outlive_call) +327 def main [ +328 local-scope +329 x:&:num <- new num:type +330 y:space <- copy default-space:space +331 ] +332 -mem: automatically abandoning 1005 +333 +334 //: +335 +336 :(scenario local_scope_does_not_reclaim_escaping_locals) +337 def main [ +338 1:text <- foo +339 ] +340 def foo [ +341 local-scope +342 x:text <- new [abc] +343 return x:text +344 ] +345 # local-scope +346 +mem: automatically abandoning 1000 +347 # x +348 -mem: automatically abandoning 1004 +349 +350 :(after "Begin Return") // before reclaiming default-space +351 increment_refcounts_of_return_ingredients(ingredients); +352 :(code) +353 void increment_refcounts_of_return_ingredients(const vector<vector<double> >& ingredients) { +354 assert(current_instruction().operation == RETURN); +355 if (SIZE(Current_routine->calls) == 1) // no caller to receive result +356 ¦ return; +357 const instruction& caller_instruction = to_instruction(*++Current_routine->calls.begin()); +358 for (int i = 0; i < min(SIZE(current_instruction().ingredients), SIZE(caller_instruction.products)); ++i) { +359 ¦ if (!is_dummy(caller_instruction.products.at(i))) { +360 ¦ ¦ // no need to canonize ingredient because we ignore its value +361 ¦ ¦ increment_any_refcounts(current_instruction().ingredients.at(i), ingredients.at(i)); +362 ¦ } +363 } +364 } +365 +366 //: +367 +368 :(scenario local_scope_frees_up_addresses_inside_containers) +369 container foo [ +370 x:num +371 y:&:num +372 ] +373 def main [ +374 local-scope +375 x:&:num <- new number:type +376 y:foo <- merge 34, x:&:num +377 # x and y are both cleared when main returns +378 ] +379 +mem: automatically abandoning 1006 +380 +381 :(scenario local_scope_returns_addresses_inside_containers) +382 container foo [ +383 x:num +384 y:&:num +385 ] +386 def f [ +387 local-scope +388 x:&:num <- new number:type +389 *x:&:num <- copy 12 +390 y:foo <- merge 34, x:&:num +391 # since y is 'escaping' f, it should not be cleared +392 return y:foo +393 ] +394 def main [ +395 1:foo <- f +396 3:num <- get 1:foo, x:offset +397 4:&:num <- get 1:foo, y:offset +398 5:num <- copy *4:&:num +399 1:foo <- put 1:foo, y:offset, 0 +400 4:&:num <- copy 0 +401 ] +402 +mem: storing 34 in location 1 +403 +mem: storing 1006 in location 2 +404 +mem: storing 34 in location 3 +405 # refcount of 1:foo shouldn't include any stray ones from f +406 +run: {4: ("address" "number")} <- get {1: "foo"}, {y: "offset"} +407 +mem: incrementing refcount of 1006: 1 -> 2 +408 # 1:foo wasn't abandoned/cleared +409 +run: {5: "number"} <- copy {4: ("address" "number"), "lookup": ()} +410 +mem: storing 12 in location 5 +411 +run: {1: "foo"} <- put {1: "foo"}, {y: "offset"}, {0: "literal"} +412 +mem: decrementing refcount of 1006: 2 -> 1 +413 +run: {4: ("address" "number")} <- copy {0: "literal"} +414 +mem: decrementing refcount of 1006: 1 -> 0 +415 +mem: automatically abandoning 1006 +416 +417 :(scenario local_scope_claims_return_values_when_not_saved) +418 def f [ +419 local-scope +420 x:&:num <- new number:type +421 return x:&:num +422 ] +423 def main [ +424 f # doesn't save result +425 ] +426 # x reclaimed +427 +mem: automatically abandoning 1004 +428 # f's local scope reclaimed +429 +mem: automatically abandoning 1000 +430 +431 //:: all recipes must set default-space one way or another +432 +433 :(before "End Globals") +434 bool Hide_missing_default_space_errors = true; +435 :(before "End Checks") +436 Transform.push_back(check_default_space); // idempotent +437 :(code) +438 void check_default_space(const recipe_ordinal r) { +439 if (Hide_missing_default_space_errors) return; // skip previous core tests; this is only for Mu code +440 const recipe& caller = get(Recipe, r); +441 // End check_default_space Special-cases +442 // assume recipes with only numeric addresses know what they're doing (usually tests) +443 if (!contains_non_special_name(r)) return; +444 trace(9991, "transform") << "--- check that recipe " << caller.name << " sets default-space" << end(); +445 if (caller.steps.empty()) return; +446 if (!starts_by_setting_default_space(caller)) +447 ¦ raise << caller.name << " does not seem to start with 'local-scope' or 'default-space'\n" << end(); +448 } +449 :(after "Load Mu Prelude") +450 Hide_missing_default_space_errors = false; +451 :(after "Test Runs") +452 Hide_missing_default_space_errors = true; +453 :(after "Running Main") +454 Hide_missing_default_space_errors = false; +455 +456 :(code) +457 bool contains_non_special_name(const recipe_ordinal r) { +458 for (map<string, int>::iterator p = Name[r].begin(); p != Name[r].end(); ++p) { +459 ¦ if (p->first.empty()) continue; +460 ¦ if (p->first.find("stash_") == 0) continue; // generated by rewrite_stashes_to_text (cross-layer) +461 ¦ if (!is_special_name(p->first)) +462 ¦ ¦ return true; +463 } +464 return false; +465 } +466 +467 // reagent comparison -- only between reagents in a single recipe +468 bool operator==(const reagent& a, const reagent& b) { +469 if (a.name != b.name) return false; +470 if (property(a, "space") != property(b, "space")) return false; +471 return true; +472 } +473 +474 bool operator<(const reagent& a, const reagent& b) { +475 int aspace = 0, bspace = 0; +476 if (has_property(a, "space")) aspace = to_integer(property(a, "space")->value); +477 if (has_property(b, "space")) bspace = to_integer(property(b, "space")->value); +478 if (aspace != bspace) return aspace < bspace; +479 return a.name < b.name; +480 } diff --git a/html/044space_surround.cc.html b/html/044space_surround.cc.html index f1f007b9..c6291f2e 100644 --- a/html/044space_surround.cc.html +++ b/html/044space_surround.cc.html @@ -100,15 +100,15 @@ if ('onhashchange' in window) { 37 //: one. 38 39 :(replace{} "int space_base(const reagent& x)") -40 int space_base(const reagent& x) { +40 int space_base(const reagent& x) { 41 int base = current_call().default_space ? (current_call().default_space+/*skip refcount*/1) : 0; -42 return space_base(x, space_index(x), base); +42 return space_base(x, space_index(x), base); 43 } 44 -45 int space_base(const reagent& x, int space_index, int base) { +45 int space_base(const reagent& x, int space_index, int base) { 46 if (space_index == 0) 47 ¦ return base; -48 int result = space_base(x, space_index-1, get_or_insert(Memory, base+/*skip length*/1))+/*skip refcount*/1; +48 int result = space_base(x, space_index-1, get_or_insert(Memory, base+/*skip length*/1))+/*skip refcount*/1; 49 return result; 50 } 51 diff --git a/html/045closure_name.cc.html b/html/045closure_name.cc.html index ad68b75f..1740cdf2 100644 --- a/html/045closure_name.cc.html +++ b/html/045closure_name.cc.html @@ -66,7 +66,7 @@ if ('onhashchange' in window) { 3 //: the variable in the chained/surrounding space. /space:2 looks up the 4 //: surrounding space of the surrounding space, etc. 5 //: - 6 //: todo: warn on default-space abuse. default-space for one function should + 6 //: todo: warn on default-space abuse. default-space for one recipe should 7 //: never come from another, otherwise memory will be corrupted. 8 9 :(scenario closure) @@ -111,7 +111,7 @@ if ('onhashchange' in window) { 48 ¦ ¦ if (is_literal(inst.products.at(j))) continue; 49 ¦ ¦ if (inst.products.at(j).name != "0") continue; 50 ¦ ¦ if (!is_mu_space(inst.products.at(j))) { - 51 ¦ ¦ ¦ raise << "slot 0 should always have type address:array:location, but is '" << to_string(inst.products.at(j)) << "'\n" << end(); + 51 ¦ ¦ ¦ raise << "slot 0 should always have type address:array:location, but is '" << to_string(inst.products.at(j)) << "'\n" << end(); 52 ¦ ¦ ¦ continue; 53 ¦ ¦ } 54 ¦ ¦ string_tree* s = property(inst.products.at(j), "names"); diff --git a/html/046check_type_by_name.cc.html b/html/046check_type_by_name.cc.html index 2003837b..332f1843 100644 --- a/html/046check_type_by_name.cc.html +++ b/html/046check_type_by_name.cc.html @@ -110,7 +110,7 @@ if ('onhashchange' in window) { 46 x.type = new type_tree(*exemplar.type); 47 trace(9992, "transform") << x.name << " <= " << names_to_string(x.type) << end(); 48 // spaces are special; their type includes their /names property - 49 if (is_mu_space(x) && !has_property(x, "names")) { + 49 if (is_mu_space(x) && !has_property(x, "names")) { 50 ¦ if (!has_property(exemplar, "names")) { 51 ¦ ¦ raise << maybe(caller.name) << "missing /names property for space variable '" << exemplar.name << "'\n" << end(); 52 ¦ ¦ return; diff --git a/html/050scenario.cc.html b/html/050scenario.cc.html index 698ac6c8..e47925c1 100644 --- a/html/050scenario.cc.html +++ b/html/050scenario.cc.html @@ -479,7 +479,7 @@ if ('onhashchange' in window) { 412 ¦ ¦ check_type(lhs, in); 413 ¦ ¦ continue; 414 ¦ } -415 ¦ int address = to_integer(lhs); +415 ¦ int address = to_integer(lhs); 416 ¦ skip_whitespace_and_comments(in); 417 ¦ string _assign; in >> _assign; assert(_assign == "<-"); 418 ¦ skip_whitespace_and_comments(in); @@ -496,16 +496,16 @@ if ('onhashchange' in window) { 429 ¦ ¦ return; 430 ¦ } 431 ¦ double value = to_double(rhs); -432 ¦ if (contains_key(locations_checked, address)) +432 ¦ if (contains_key(locations_checked, address)) 433 ¦ ¦ raise << maybe(current_recipe_name()) << "duplicate expectation for location '" << address << "'\n" << end(); -434 ¦ trace(9999, "run") << "checking location " << address << end(); -435 ¦ if (get_or_insert(Memory, address) != value) { +434 ¦ trace("run") << "checking location " << address << end(); +435 ¦ if (get_or_insert(Memory, address) != value) { 436 ¦ ¦ if (!Hide_errors) cerr << '\n'; -437 ¦ ¦ raise << "F - " << maybe(current_recipe_name()) << "expected location '" << address << "' to contain " << no_scientific(value) << " but saw " << no_scientific(get_or_insert(Memory, address)) << '\n' << end(); +437 ¦ ¦ raise << "F - " << maybe(current_recipe_name()) << "expected location '" << address << "' to contain " << no_scientific(value) << " but saw " << no_scientific(get_or_insert(Memory, address)) << '\n' << end(); 438 ¦ ¦ if (!Scenario_testing_scenario) Passed = false; 439 ¦ ¦ return; 440 ¦ } -441 ¦ locations_checked.insert(address); +441 ¦ locations_checked.insert(address); 442 } 443 } 444 @@ -528,7 +528,7 @@ if ('onhashchange' in window) { 461 ¦ ¦ raise << maybe(current_recipe_name()) << "incomplete 'memory-should-contain' block at end of file (3)\n" << end(); 462 ¦ ¦ return; 463 ¦ } -464 ¦ int address = x.value; +464 ¦ int address = x.value; 465 ¦ // exclude quoting brackets 466 ¦ if (*literal.begin() != '[') { 467 ¦ ¦ raise << maybe(current_recipe_name()) << "array:character types inside 'memory-should-contain' can only be compared with text literals surrounded by [], not '" << literal << "'\n" << end(); @@ -536,7 +536,7 @@ if ('onhashchange' in window) { 469 ¦ } 470 ¦ literal.erase(literal.begin()); 471 ¦ assert(*--literal.end() == ']'); literal.erase(--literal.end()); -472 ¦ check_mu_text(address, literal); +472 ¦ check_mu_text(address, literal); 473 ¦ return; 474 } 475 // End Scenario Type Special-cases @@ -544,7 +544,7 @@ if ('onhashchange' in window) { 477 } 478 479 void check_mu_text(int start, const string& literal) { -480 trace(9999, "run") << "checking text length at " << start << end(); +480 trace("run") << "checking text length at " << start << end(); 481 int array_length = static_cast<int>(get_or_insert(Memory, start)); 482 if (array_length != SIZE(literal)) { 483 ¦ if (!Hide_errors) cerr << '\n'; @@ -554,7 +554,7 @@ if ('onhashchange' in window) { 487 } 488 int curr = start+1; // now skip length 489 for (int i = 0; i < SIZE(literal); ++i) { -490 ¦ trace(9999, "run") << "checking location " << curr+i << end(); +490 ¦ trace("run") << "checking location " << curr+i << end(); 491 ¦ if (get_or_insert(Memory, curr+i) != literal.at(i)) { 492 ¦ ¦ if (!Hide_errors) cerr << '\n'; 493 ¦ ¦ raise << "F - " << maybe(current_recipe_name()) << "expected location " << (curr+i) << " to contain " << literal.at(i) << " but saw " << no_scientific(get_or_insert(Memory, curr+i)) << '\n' << end(); @@ -944,7 +944,7 @@ if ('onhashchange' in window) { 877 :(after "case _SYSTEM:") 878 if (Current_scenario) break; 879 -880 //:: Warn if people use '_' manually in function names. They're reserved for internal use. +880 //:: Warn if people use '_' manually in recipe names. They're reserved for internal use. 881 882 :(scenario recipe_name_with_underscore) 883 % Hide_errors = true; diff --git a/html/053recipe_header.cc.html b/html/053recipe_header.cc.html index 6591374c..3d30ac4c 100644 --- a/html/053recipe_header.cc.html +++ b/html/053recipe_header.cc.html @@ -90,7 +90,7 @@ if ('onhashchange' in window) { 24 25 :(before "End Recipe Refinements") 26 if (in.peek() != '[') { - 27 trace(9999, "parse") << "recipe has a header; parsing" << end(); + 27 trace("parse") << "recipe has a header; parsing" << end(); 28 load_recipe_header(in, result); 29 } 30 @@ -108,7 +108,7 @@ if ('onhashchange' in window) { 42 ¦ ¦ raise << "recipe " << result.name << " should say '->' and not '<-'\n" << end(); 43 ¦ if (s == "->") break; 44 ¦ result.ingredients.push_back(reagent(s)); - 45 ¦ trace(9999, "parse") << "header ingredient: " << result.ingredients.back().original_string << end(); + 45 ¦ trace("parse") << "header ingredient: " << result.ingredients.back().original_string << end(); 46 ¦ skip_whitespace_but_not_newline(in); 47 } 48 while (has_data(in) && in.peek() != '[' && in.peek() != '\n') { @@ -119,7 +119,7 @@ if ('onhashchange' in window) { 53 ¦ ¦ return; 54 ¦ } 55 ¦ result.products.push_back(reagent(s)); - 56 ¦ trace(9999, "parse") << "header product: " << result.products.back().original_string << end(); + 56 ¦ trace("parse") << "header product: " << result.products.back().original_string << end(); 57 ¦ skip_whitespace_but_not_newline(in); 58 } 59 // End Load Recipe Header(result) @@ -215,7 +215,7 @@ if ('onhashchange' in window) { 149 } 150 } 151 if (result.has_header) { -152 trace(9999, "parse") << "recipe " << result.name << " has a header" << end(); +152 trace("parse") << "recipe " << result.name << " has a header" << end(); 153 } 154 155 //: Support type abbreviations in headers. @@ -692,7 +692,7 @@ if ('onhashchange' in window) { 626 if (caller.name != "main") return; 627 trace(9992, "transform") << "check recipe header constraints for recipe " << caller.name << end(); 628 if (!caller.has_header) return; -629 reagent/*local*/ expected_ingredient("x:address:array:character"); +629 reagent/*local*/ expected_ingredient("x:address:array:character"); 630 for (int i = 0; i < SIZE(caller.ingredients); ++i) { 631 ¦ if (!types_strictly_match(expected_ingredient, caller.ingredients.at(i))) { 632 ¦ ¦ raise << "ingredients of recipe 'main' must all be text (address:array:character)\n" << end(); diff --git a/html/054static_dispatch.cc.html b/html/054static_dispatch.cc.html index 12306ed6..5d3cac06 100644 --- a/html/054static_dispatch.cc.html +++ b/html/054static_dispatch.cc.html @@ -107,7 +107,7 @@ if ('onhashchange' in window) { 41 ¦ ¦ put(Recipe_ordinal, new_name, Next_recipe_ordinal++); 42 ¦ ¦ get_or_insert(Recipe_variants, result.name).push_back(get(Recipe_ordinal, new_name)); 43 ¦ } - 44 ¦ trace(9999, "load") << "switching " << result.name << " to " << new_name << end(); + 44 ¦ trace("load") << "switching " << result.name << " to " << new_name << end(); 45 ¦ result.name = new_name; 46 ¦ result.is_autogenerated = true; 47 } @@ -408,10 +408,10 @@ if ('onhashchange' in window) { 342 int min_index = 0; 343 for (int i = 0; i < SIZE(candidates); ++i) { 344 ¦ const recipe& candidate = get(Recipe, candidates.at(i)); -345 ¦ // prefer functions without extra or missing ingredients or products +345 ¦ // prefer variants without extra or missing ingredients or products 346 ¦ int score = abs(SIZE(candidate.products)-SIZE(inst.products)) 347 ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ + abs(SIZE(candidate.ingredients)-SIZE(inst.ingredients)); -348 ¦ // prefer functions with non-address ingredients or products +348 ¦ // prefer variants with non-address ingredients or products 349 ¦ for (int j = 0; j < SIZE(candidate.ingredients); ++j) { 350 ¦ ¦ if (is_mu_address(candidate.ingredients.at(j))) 351 ¦ ¦ ¦ ++score; @@ -711,7 +711,7 @@ if ('onhashchange' in window) { 645 s:text <- new [abc] 646 1:num/raw <- foo s 647 ] -648 def foo a:address:array:character -> result:number [ +648 def foo a:address:array:character -> result:number [ 649 return 34 650 ] 651 # identical to previous variant once you take type abbreviations into account diff --git a/html/055shape_shifting_container.cc.html b/html/055shape_shifting_container.cc.html index 8953e839..b7a86272 100644 --- a/html/055shape_shifting_container.cc.html +++ b/html/055shape_shifting_container.cc.html @@ -145,7 +145,7 @@ if ('onhashchange' in window) { 79 def main [ 80 1:text <- new [abc] 81 # compound types for type ingredients - 82 {2: (foo number (address array character))} <- merge 34/x, 1:text/y + 82 {2: (foo number (address array character))} <- merge 34/x, 1:text/y 83 ] 84 $error: 0 85 @@ -156,7 +156,7 @@ if ('onhashchange' in window) { 90 ] 91 container bar:_a:_b [ 92 # dilated element - 93 {data: (foo _a (address _b))} + 93 {data: (foo _a (address _b))} 94 ] 95 def main [ 96 1:text <- new [abc] @@ -210,7 +210,7 @@ if ('onhashchange' in window) { 144 145 :(before "End container Name Refinements") 146 if (name.find(':') != string::npos) { -147 trace(9999, "parse") << "container has type ingredients; parsing" << end(); +147 trace("parse") << "container has type ingredients; parsing" << end(); 148 if (!read_type_ingredients(name, command)) { 149 ¦ // error; skip rest of the container definition and continue 150 ¦ slurp_balanced_bracket(in); @@ -374,8 +374,8 @@ if ('onhashchange' in window) { 308 ] 309 def main [ 310 1:text <- new [abc] -311 {2: (foo number (address array character))} <- merge 34/x, 1:text/y -312 3:text <- get {2: (foo number (address array character))}, y:offset +311 {2: (foo number (address array character))} <- merge 34/x, 1:text/y +312 3:text <- get {2: (foo number (address array character))}, y:offset 313 4:bool <- equal 1:text, 3:text 314 ] 315 +mem: storing 1 in location 4 @@ -516,9 +516,9 @@ if ('onhashchange' in window) { 450 ¦ ¦ "container bar:_elem [\n" 451 ¦ ¦ " x:foo:_elem\n" 452 ¦ ¦ "]\n"); -453 reagent callsite("x:bar:address:array:character"); +453 reagent callsite("x:bar:address:array:character"); 454 reagent element = element_type(callsite.type, 0); -455 CHECK_EQ(to_string(element), "{x: (\"foo\" \"address\" \"array\" \"character\")}"); +455 CHECK_EQ(to_string(element), "{x: (\"foo\" \"address\" \"array\" \"character\")}"); 456 } 457 458 void test_replace_type_ingredients_head_middle() { @@ -530,7 +530,7 @@ if ('onhashchange' in window) { 464 ¦ ¦ "]\n"); 465 reagent callsite("x:bar:address"); 466 reagent element = element_type(callsite.type, 0); -467 CHECK_EQ(to_string(element), "{x: (\"foo\" \"address\" \"number\")}"); +467 CHECK_EQ(to_string(element), "{x: (\"foo\" \"address\" \"number\")}"); 468 } 469 470 void test_replace_last_type_ingredient_with_multiple() { @@ -542,7 +542,7 @@ if ('onhashchange' in window) { 476 reagent element1 = element_type(callsite.type, 0); 477 CHECK_EQ(to_string(element1), "{x: \"number\"}"); 478 reagent element2 = element_type(callsite.type, 1); -479 CHECK_EQ(to_string(element2), "{y: (\"address\" \"array\" \"character\")}"); +479 CHECK_EQ(to_string(element2), "{y: (\"address\" \"array\" \"character\")}"); 480 } 481 482 void test_replace_last_type_ingredient_inside_compound() { @@ -564,7 +564,7 @@ if ('onhashchange' in window) { 498 reagent element1 = element_type(callsite.type, 0); 499 CHECK_EQ(to_string(element1), "{x: \"number\"}"); 500 reagent element2 = element_type(callsite.type, 1); -501 CHECK_EQ(to_string(element2), "{y: (\"address\" \"array\" \"character\")}"); +501 CHECK_EQ(to_string(element2), "{y: (\"address\" \"array\" \"character\")}"); 502 reagent element3 = element_type(callsite.type, 2); 503 CHECK_EQ(to_string(element3), "{z: \"boolean\"}"); 504 } @@ -576,7 +576,7 @@ if ('onhashchange' in window) { 510 ¦ ¦ "]\n"); 511 reagent callsite("{f: (foo (address array character) number)}"); 512 reagent element = element_type(callsite.type, 0); -513 CHECK_EQ(to_string(element), "{key: (\"address\" \"array\" \"character\")}"); +513 CHECK_EQ(to_string(element), "{key: (\"address\" \"array\" \"character\")}"); 514 } 515 516 void test_replace_middle_type_ingredient_with_multiple3() { @@ -590,7 +590,7 @@ if ('onhashchange' in window) { 524 ¦ ¦ "]\n"); 525 reagent callsite("{f: (foo_table (address array character) number)}"); 526 reagent element = element_type(callsite.type, 0); -527 CHECK_EQ(to_string(element), "{data: (\"address\" \"array\" \"foo_table_row\" (\"address\" \"array\" \"character\") \"number\")}"); +527 CHECK_EQ(to_string(element), "{data: (\"address\" \"array\" \"foo_table_row\" (\"address\" \"array\" \"character\") \"number\")}"); 528 } 529 530 :(code) @@ -703,9 +703,9 @@ if ('onhashchange' in window) { 637 reagent r("x:foo:&:num"); 638 compute_container_sizes(r, ""); 639 compute_container_address_offsets(r, ""); -640 CHECK_EQ(SIZE(r.metadata.address), 1); -641 CHECK(contains_key(r.metadata.address, set<tag_condition_info>())); -642 set<address_element_info>& offset_info = get(r.metadata.address, set<tag_condition_info>()); +640 CHECK_EQ(SIZE(r.metadata.address), 1); +641 CHECK(contains_key(r.metadata.address, set<tag_condition_info>())); +642 set<address_element_info>& offset_info = get(r.metadata.address, set<tag_condition_info>()); 643 CHECK_EQ(SIZE(offset_info), 1); 644 CHECK_EQ(offset_info.begin()->offset, 1); // 645 CHECK(offset_info.begin()->payload_type->atom); @@ -725,9 +725,9 @@ if ('onhashchange' in window) { 659 CLEAR_TRACE; 660 compute_container_sizes(r, ""); 661 compute_container_address_offsets(r, ""); -662 CHECK_EQ(SIZE(r.metadata.address), 1); -663 CHECK(contains_key(r.metadata.address, set<tag_condition_info>())); -664 set<address_element_info>& offset_info = get(r.metadata.address, set<tag_condition_info>()); +662 CHECK_EQ(SIZE(r.metadata.address), 1); +663 CHECK(contains_key(r.metadata.address, set<tag_condition_info>())); +664 set<address_element_info>& offset_info = get(r.metadata.address, set<tag_condition_info>()); 665 CHECK_EQ(SIZE(offset_info), 2); 666 CHECK_EQ(offset_info.begin()->offset, 0); // 667 CHECK(offset_info.begin()->payload_type->atom); @@ -744,7 +744,7 @@ if ('onhashchange' in window) { 678 ] 679 def main [ 680 local-scope -681 x:address:foo:num <- new {(foo num): type} +681 x:address:foo:num <- new {(foo num): type} 682 ] 683 # no crash 684 diff --git a/html/056shape_shifting_recipe.cc.html b/html/056shape_shifting_recipe.cc.html index 6166e4b8..b1de6ae2 100644 --- a/html/056shape_shifting_recipe.cc.html +++ b/html/056shape_shifting_recipe.cc.html @@ -649,7 +649,7 @@ if ('onhashchange' in window) { 582 ] 583 def main [ 584 s:text <- new [abc] - 585 {x: (c (address array character) number)} <- merge s, 34 + 585 {x: (c (address array character) number)} <- merge s, 34 586 foo x 587 ] 588 def foo x:c:_bar:_baz [ @@ -788,7 +788,7 @@ if ('onhashchange' in window) { 721 result <- get *x, value:offset 722 ] 723 def main [ - 724 1:&:foo:&:point <- new {(foo address point): type} + 724 1:&:foo:&:point <- new {(foo address point): type} 725 2:&:point <- bar 1:&:foo:&:point 726 ] 727 # no errors; call to 'bar' successfully specialized diff --git a/html/057immutable.cc.html b/html/057immutable.cc.html index 5058f120..5b28aafb 100644 --- a/html/057immutable.cc.html +++ b/html/057immutable.cc.html @@ -298,7 +298,7 @@ if ('onhashchange' in window) { 234 def foo a:&:@:&:num [ 235 local-scope 236 load-ingredients -237 b:&:@:&:num <- new {(address number): type}, 3 +237 b:&:@:&:num <- new {(address number): type}, 3 238 # modify b, completely unrelated to immutable ingredient a 239 x:&:num <- index *b, 0 240 *x <- copy 34 diff --git a/html/062convert_ingredients_to_text.cc.html b/html/062convert_ingredients_to_text.cc.html index 091d01fa..eda38d88 100644 --- a/html/062convert_ingredients_to_text.cc.html +++ b/html/062convert_ingredients_to_text.cc.html @@ -61,7 +61,7 @@ if ('onhashchange' in window) {
-  1 //: make some functions more friendly by trying to auto-convert their ingredients to text
+  1 //: make some recipes more friendly by trying to auto-convert their ingredients to text
   2 
   3 :(scenarios transform)
   4 :(scenario rewrite_stashes_to_text)
@@ -137,7 +137,7 @@ if ('onhashchange' in window) {
  74   ¦ ¦ for (int j = 0;  j < SIZE(inst.ingredients);  ++j) {
  75   ¦ ¦ ¦ if (is_literal_text(inst.ingredients.at(j))) continue;
  76   ¦ ¦ ¦ ostringstream ingredient_name;
- 77   ¦ ¦ ¦ ingredient_name << "stash_" << i << '_' << j << ":address:array:character";
+ 77   ¦ ¦ ¦ ingredient_name << "stash_" << i << '_' << j << ":address:array:character";
  78   ¦ ¦ ¦ convert_ingredient_to_text(inst.ingredients.at(j), new_instructions, ingredient_name.str());
  79   ¦ ¦ }
  80   ¦ }
@@ -145,7 +145,7 @@ if ('onhashchange' in window) {
  82   ¦ ¦ for (int j = /*skip*/2;  j < SIZE(inst.ingredients);  ++j) {
  83   ¦ ¦ ¦ if (is_literal_text(inst.ingredients.at(j))) continue;
  84   ¦ ¦ ¦ ostringstream ingredient_name;
- 85   ¦ ¦ ¦ ingredient_name << "trace_" << i << '_' << j << ":address:array:character";
+ 85   ¦ ¦ ¦ ingredient_name << "trace_" << i << '_' << j << ":address:array:character";
  86   ¦ ¦ ¦ convert_ingredient_to_text(inst.ingredients.at(j), new_instructions, ingredient_name.str());
  87   ¦ ¦ }
  88   ¦ }
@@ -158,7 +158,7 @@ if ('onhashchange' in window) {
  95   ¦ ¦ if (is_literal_text(inst.ingredients.at(0)) || is_mu_text(inst.ingredients.at(0))) {
  96   ¦ ¦ ¦ for (int j = /*skip base*/1;  j < SIZE(inst.ingredients);  ++j) {
  97   ¦ ¦ ¦ ¦ ostringstream ingredient_name;
- 98   ¦ ¦ ¦ ¦ ingredient_name << "append_" << i << '_' << j << ":address:array:character";
+ 98   ¦ ¦ ¦ ¦ ingredient_name << "append_" << i << '_' << j << ":address:array:character";
  99   ¦ ¦ ¦ ¦ convert_ingredient_to_text(inst.ingredients.at(j), new_instructions, ingredient_name.str());
 100   ¦ ¦ ¦ }
 101   ¦ ¦ }
diff --git a/html/069hash.cc.html b/html/069hash.cc.html
index 9521a756..00d88349 100644
--- a/html/069hash.cc.html
+++ b/html/069hash.cc.html
@@ -63,7 +63,7 @@ if ('onhashchange' in window) {
 
 
 
-  1 // A universal hash function that can handle objects of any type.
+  1 // Compute a hash for objects of any type.
   2 //
   3 // The way it's currently implemented, two objects will have the same hash if
   4 // all their non-address fields (all the way down) expand to the same sequence
@@ -120,10 +120,10 @@ if ('onhashchange' in window) {
  55 
  56 size_t hash_mu_address(size_t h, reagent& r) {
  57   if (r.value == 0) return 0;
- 58   trace(9999, "mem") << "location " << r.value << " is " << no_scientific(get_or_insert(Memory, r.value)) << end();
+ 58   trace("mem") << "location " << r.value << " is " << no_scientific(get_or_insert(Memory, r.value)) << end();
  59   r.set_value(get_or_insert(Memory, r.value));
  60   if (r.value != 0) {
- 61   ¦ trace(9999, "mem") << "skipping refcount at " << r.value << end();
+ 61   ¦ trace("mem") << "skipping refcount at " << r.value << end();
  62   ¦ r.set_value(r.value+1);  // skip refcount
  63   }
  64   drop_from_type(r, "address");
@@ -144,9 +144,9 @@ if ('onhashchange' in window) {
  79   reagent/*copy*/ elem = r;
  80   delete elem.type;
  81   elem.type = copy_array_element(r.type);
- 82   for (int i=0, address = r.value+1;  i < size;  ++i, address += size_of(elem)) {
+ 82   for (int i=0, address = r.value+1;  i < size;  ++i, address += size_of(elem)) {
  83   ¦ reagent/*copy*/ tmp = elem;
- 84   ¦ tmp.set_value(address);
+ 84   ¦ tmp.set_value(address);
  85   ¦ h = hash(h, tmp);
  86 //?     cerr << i << " (" << address << "): " << h << '\n';
  87   }
@@ -155,7 +155,7 @@ if ('onhashchange' in window) {
  90 
  91 size_t hash_mu_container(size_t h, const reagent& r) {
  92   type_info& info = get(Type, get_base_type(r.type)->value);
- 93   int address = r.value;
+ 93   int address = r.value;
  94   int offset = 0;
  95   for (int i = 0;  i < SIZE(info.elements);  ++i) {
  96   ¦ reagent/*copy*/ element = element_type(r.type, i);
diff --git a/html/071deep_copy.cc.html b/html/071deep_copy.cc.html
index 90700e7f..641d493b 100644
--- a/html/071deep_copy.cc.html
+++ b/html/071deep_copy.cc.html
@@ -292,7 +292,7 @@ if ('onhashchange' in window) {
 228 vector<double> deep_copy(const reagent& in) {
 229   // allocate a tiny bit of temporary space for deep_copy()
 230   trace(9991, "run") << "deep-copy: allocating space for temporary" << end();
-231   reagent tmp("tmp:address:number");
+231   reagent tmp("tmp:address:number");
 232   tmp.set_value(allocate(1));
 233   map<int, int> addresses_copied;
 234   vector<double> result = deep_copy(in, addresses_copied, tmp);
@@ -323,7 +323,7 @@ if ('onhashchange' in window) {
 259 int deep_copy_address(const reagent& canonized_in, map<int, int>& addresses_copied, const reagent& tmp) {
 260   if (address_value(canonized_in) == 0) return 0;
 261   int in_address = payload_address(canonized_in);
-262   trace(9991, "run") << "deep-copy: copying address " << in_address << end();
+262   trace(9991, "run") << "deep-copy: copying address " << in_address << end();
 263   if (contains_key(addresses_copied, in_address)) {
 264   ¦ int out = get(addresses_copied, in_address);
 265   ¦ trace(9991, "run") << "deep-copy: copy already exists: " << out << end();
@@ -332,7 +332,7 @@ if ('onhashchange' in window) {
 268   ¦ return out;
 269   }
 270   int out = allocate(payload_size(canonized_in));
-271   trace(9991, "run") << "deep-copy: new address is " << out << end();
+271   trace(9991, "run") << "deep-copy: new address is " << out << end();
 272   put(addresses_copied, in_address, out);
 273   reagent/*copy*/ payload = canonized_in;
 274   payload.properties.push_back(pair<string, string_tree*>("lookup", NULL));
@@ -359,7 +359,7 @@ if ('onhashchange' in window) {
 295   if (!contains_key(Container_metadata, canonized_in.type)) return;
 296   trace(9991, "run") << "deep-copy: scanning for addresses in " << to_string(data) << end();
 297   const container_metadata& metadata = get(Container_metadata, canonized_in.type);
-298   for (map<set<tag_condition_info>, set<address_element_info> >::const_iterator p = metadata.address.begin();  p != metadata.address.end();  ++p) {
+298   for (map<set<tag_condition_info>, set<address_element_info> >::const_iterator p = metadata.address.begin();  p != metadata.address.end();  ++p) {
 299   ¦ if (!all_match(data, p->first)) continue;
 300   ¦ for (set<address_element_info>::const_iterator info = p->second.begin();  info != p->second.end();  ++info) {
 301   ¦ ¦ // hack: skip primitive containers that do their own locking; they're designed to be shared between routines
@@ -376,7 +376,7 @@ if ('onhashchange' in window) {
 312   ¦ ¦ ¦ curr.type = new type_tree(new type_tree("address"), new type_tree(*info->payload_type));
 313   ¦ ¦ curr.set_value(canonized_in.value + info->offset);
 314   ¦ ¦ curr.properties.push_back(pair<string, string_tree*>("raw", NULL));
-315   ¦ ¦ trace(9991, "run") << "deep-copy: copying address " << curr.value << end();
+315   ¦ ¦ trace(9991, "run") << "deep-copy: copying address " << curr.value << end();
 316   ¦ ¦ out.at(info->offset) = deep_copy_address(curr, addresses_copied, tmp);
 317   ¦ }
 318   }
diff --git a/html/072recipe.cc.html b/html/072recipe.cc.html
index 0da90663..32f77078 100644
--- a/html/072recipe.cc.html
+++ b/html/072recipe.cc.html
@@ -394,9 +394,9 @@ if ('onhashchange' in window) {
 330 
 331 :(scenario call_variable_compound_ingredient)
 332 def main [
-333   {1: (recipe (address number) -> number)} <- copy f
+333   {1: (recipe (address number) -> number)} <- copy f
 334   2:&:num <- copy 0
-335   3:num <- call {1: (recipe (address number) -> number)}, 2:&:num
+335   3:num <- call {1: (recipe (address number) -> number)}, 2:&:num
 336 ]
 337 def f x:&:num -> y:num [
 338   local-scope
@@ -405,7 +405,7 @@ if ('onhashchange' in window) {
 341 ]
 342 $error: 0
 343 
-344 //: make sure we don't accidentally break on a function literal
+344 //: make sure we don't accidentally break on a recipe literal
 345 :(scenario jump_forbidden_on_recipe_literals)
 346 % Hide_errors = true;
 347 def foo [
diff --git a/html/073scheduler.cc.html b/html/073scheduler.cc.html
index a9745289..094a8a8b 100644
--- a/html/073scheduler.cc.html
+++ b/html/073scheduler.cc.html
@@ -600,7 +600,7 @@ if ('onhashchange' in window) {
 535 :(before "End Scheduler State Transitions")
 536 if (Current_routine->limit >= 0) {
 537   if (Current_routine->limit <= Scheduling_interval) {
-538   ¦ trace(9999, "schedule") << "discontinuing routine " << Current_routine->id << end();
+538   ¦ trace("schedule") << "discontinuing routine " << Current_routine->id << end();
 539   ¦ Current_routine->state = DISCONTINUED;
 540   ¦ Current_routine->limit = 0;
 541   }
diff --git a/html/074wait.cc.html b/html/074wait.cc.html
index 934f2f29..661da8b1 100644
--- a/html/074wait.cc.html
+++ b/html/074wait.cc.html
@@ -197,7 +197,7 @@ if ('onhashchange' in window) {
 132   if (Routines.at(i)->state != WAITING) continue;
 133   int loc = Routines.at(i)->waiting_on_location;
 134   if (loc && get_or_insert(Memory, loc) == 0) {
-135   ¦ trace(9999, "schedule") << "waking up routine " << Routines.at(i)->id << end();
+135   ¦ trace("schedule") << "waking up routine " << Routines.at(i)->id << end();
 136   ¦ put(Memory, loc, 1);
 137   ¦ Routines.at(i)->state = RUNNING;
 138   ¦ Routines.at(i)->waiting_on_location = 0;
@@ -425,7 +425,7 @@ if ('onhashchange' in window) {
 360   ¦ const routine* waitee = Routines.at(j);
 361   ¦ if (waitee->id == id && waitee->state != RUNNING && waitee->state != WAITING) {
 362   ¦ ¦ // routine is COMPLETED or DISCONTINUED
-363   ¦ ¦ trace(9999, "schedule") << "waking up routine " << waiter->id << end();
+363   ¦ ¦ trace("schedule") << "waking up routine " << waiter->id << end();
 364   ¦ ¦ waiter->state = RUNNING;
 365   ¦ ¦ waiter->waiting_on_routine = 0;
 366   ¦ }
@@ -585,7 +585,7 @@ if ('onhashchange' in window) {
 520   ¦ const routine* waitee = Routines.at(j);
 521   ¦ if (waitee->id != id) continue;
 522   ¦ if (waitee->state != RUNNING || waitee->blocked) {
-523   ¦ ¦ trace(9999, "schedule") << "waking up routine " << waiter->id << " because routine " << waitee->id << " is blocked" << end();
+523   ¦ ¦ trace("schedule") << "waking up routine " << waiter->id << " because routine " << waitee->id << " is blocked" << end();
 524   ¦ ¦ waiter->state = RUNNING;
 525   ¦ ¦ waiter->waiting_on_routine_to_block = 0;
 526   ¦ }
diff --git a/html/076continuation.cc.html b/html/076continuation.cc.html
index b6df6ea2..2812b559 100644
--- a/html/076continuation.cc.html
+++ b/html/076continuation.cc.html
@@ -69,187 +69,319 @@ if ('onhashchange' in window) {
   5 //: out of two primitives:
   6 //:
   7 //:  * 'call-with-continuation-mark' marks the top of the call stack and then
-  8 //:    calls the provided function.
+  8 //:    calls the provided recipe.
   9 //:  * 'return-continuation-until-mark' copies the top of the stack
  10 //:    until the mark, and returns it as the result of
- 11 //:    call-with-continuation-mark (which might be a distant ancestor on the call
- 12 //:    stack; intervening calls don't return)
+ 11 //:    'call-with-continuation-mark' (which might be a distant ancestor on the
+ 12 //:    call stack; intervening calls don't return)
  13 //:
  14 //: The resulting slice of the stack can now be called just like a regular
- 15 //: function.
- 16 
- 17 :(before "End Mu Types Initialization")
- 18 type_ordinal continuation = Type_ordinal["continuation"] = Next_type_ordinal++;
- 19 Type[continuation].name = "continuation";
- 20 
- 21 //: A continuation can be called like a recipe.
- 22 :(before "End is_mu_recipe Atom Cases(r)")
- 23 if (r.type->name == "continuation") return true;
- 24 
- 25 //: However, it can't be type-checked like most recipes. Pretend it's like a
- 26 //: header-less recipe.
- 27 :(after "Begin Reagent->Recipe(r, recipe_header)")
- 28 if (r.type->atom && r.type->name == "continuation") {
- 29   result_header.has_header = false;
- 30   return result_header;
- 31 }
- 32 
- 33 :(scenario delimited_continuation)
- 34 recipe main [
- 35   1:continuation <- call-with-continuation-mark f, 77  # 77 is an argument to f
- 36   2:number <- copy 5
- 37   {
- 38   ¦ 2:number <- call 1:continuation, 2:number  # 2 is an argument to g, the 'top' of the continuation
- 39   ¦ 3:boolean <- greater-or-equal 2:number, 8
- 40   ¦ break-if 3:boolean
- 41   ¦ loop
- 42   }
- 43 ]
- 44 recipe f [
- 45   11:number <- next-ingredient
- 46   12:number <- g 11:number
- 47   return 12:number
- 48 ]
- 49 recipe g [
- 50   21:number <- next-ingredient
- 51   rewind-ingredients
- 52   return-continuation-until-mark
- 53   # calls of the continuation start from here
- 54   22:number <- next-ingredient
- 55   23:number <- add 22:number, 1
- 56   return 23:number
- 57 ]
- 58 # first call of 'g' executes the part before return-continuation-until-mark
- 59 +mem: storing 77 in location 21
- 60 +run: {2: "number"} <- copy {5: "literal"}
- 61 +mem: storing 5 in location 2
- 62 # calls of the continuation execute the part after return-continuation-until-mark
- 63 +run: {2: "number"} <- call {1: "continuation"}, {2: "number"}
- 64 +mem: storing 5 in location 22
- 65 +mem: storing 6 in location 2
- 66 +run: {2: "number"} <- call {1: "continuation"}, {2: "number"}
- 67 +mem: storing 6 in location 22
- 68 +mem: storing 7 in location 2
- 69 +run: {2: "number"} <- call {1: "continuation"}, {2: "number"}
- 70 +mem: storing 7 in location 22
- 71 +mem: storing 8 in location 2
- 72 # first call of 'g' does not execute the part after return-continuation-until-mark
- 73 -mem: storing 77 in location 22
- 74 # calls of the continuation don't execute the part before return-continuation-until-mark
- 75 -mem: storing 5 in location 21
- 76 -mem: storing 6 in location 21
- 77 -mem: storing 7 in location 21
- 78 # termination
- 79 -mem: storing 9 in location 2
- 80 
- 81 :(before "End call Fields")
- 82 bool is_base_of_continuation;
- 83 :(before "End call Constructor")
- 84 is_base_of_continuation = false;
- 85 
- 86 :(before "End Primitive Recipe Declarations")
- 87 CALL_WITH_CONTINUATION_MARK,
- 88 :(before "End Primitive Recipe Numbers")
- 89 Recipe_ordinal["call-with-continuation-mark"] = CALL_WITH_CONTINUATION_MARK;
- 90 :(before "End Primitive Recipe Checks")
- 91 case CALL_WITH_CONTINUATION_MARK: {
- 92   break;
- 93 }
- 94 :(before "End Primitive Recipe Implementations")
- 95 case CALL_WITH_CONTINUATION_MARK: {
- 96   // like call, but mark the current call as a 'base of continuation' call
- 97   // before pushing the next one on it
- 98   if (Trace_stream) {
- 99   ¦ ++Trace_stream->callstack_depth;
-100   ¦ trace("trace") << "delimited continuation; incrementing callstack depth to " << Trace_stream->callstack_depth << end();
-101   ¦ assert(Trace_stream->callstack_depth < 9000);  // 9998-101 plus cushion
-102   }
-103   const instruction& caller_instruction = current_instruction();
-104   Current_routine->calls.front().is_base_of_continuation = true;
-105   Current_routine->calls.push_front(call(Recipe_ordinal[current_instruction().ingredients.at(0).name]));
-106   ingredients.erase(ingredients.begin());  // drop the callee
-107   finish_call_housekeeping(caller_instruction, ingredients);
-108   continue;
-109 }
-110 
-111 //: save the slice of current call stack until the 'call-with-continuation-mark'
-112 //: call, and return it as the result.
-113 //: todo: implement delimited continuations in Mu's memory
-114 :(before "End Globals")
-115 map<long long int, call_stack> Delimited_continuation;
-116 long long int Next_delimited_continuation_id = 0;
-117 :(before "End Reset")
-118 Delimited_continuation.clear();
-119 Next_delimited_continuation_id = 0;
-120 
-121 :(before "End Primitive Recipe Declarations")
-122 RETURN_CONTINUATION_UNTIL_MARK,
-123 :(before "End Primitive Recipe Numbers")
-124 Recipe_ordinal["return-continuation-until-mark"] = RETURN_CONTINUATION_UNTIL_MARK;
-125 :(before "End Primitive Recipe Checks")
-126 case RETURN_CONTINUATION_UNTIL_MARK: {
-127   break;
-128 }
-129 :(before "End Primitive Recipe Implementations")
-130 case RETURN_CONTINUATION_UNTIL_MARK: {
-131   // first clear any existing ingredients, to isolate the creation of the
-132   // continuation from its calls
-133   Current_routine->calls.front().ingredient_atoms.clear();
-134   Current_routine->calls.front().next_ingredient_to_process = 0;
-135   // copy the current call stack until the most recent marked call
-136   call_stack::iterator find_base_of_continuation(call_stack& c);  // manual prototype containing '::'
-137   call_stack::iterator base = find_base_of_continuation(Current_routine->calls);
-138   if (base == Current_routine->calls.end()) {
-139   ¦ raise << maybe(current_recipe_name()) << "couldn't find a 'call-with-continuation-mark' to return to\n" << end();
-140   ¦ raise << maybe(current_recipe_name()) << "call stack:\n" << end();
-141   ¦ for (call_stack::iterator p = Current_routine->calls.begin();  p != Current_routine->calls.end();  ++p)
-142   ¦ ¦ raise << maybe(current_recipe_name()) << "  " << get(Recipe, p->running_recipe).name << '\n' << end();
-143   ¦ break;
-144   }
-145   Delimited_continuation[Next_delimited_continuation_id] = call_stack(Current_routine->calls.begin(), base);
-146   while (Current_routine->calls.begin() != base) {
-147   ¦ if (Trace_stream) {
-148   ¦ ¦ --Trace_stream->callstack_depth;
-149   ¦ ¦ assert(Trace_stream->callstack_depth >= 0);
-150   ¦ }
-151   ¦ Current_routine->calls.pop_front();
-152   }
-153   // return it as the result of the marked call
-154   products.resize(1);
-155   products.at(0).push_back(Next_delimited_continuation_id);
-156   ++Next_delimited_continuation_id;
-157   break;  // continue to process rest of marked call
-158 }
-159 
-160 :(code)
-161 call_stack::iterator find_base_of_continuation(call_stack& c) {
-162   for (call_stack::iterator p = c.begin(); p != c.end(); ++p)
-163   ¦ if (p->is_base_of_continuation) return p;
-164   return c.end();
-165 }
-166 
-167 //: overload 'call' for continuations
-168 :(after "Begin Call")
-169 if (current_instruction().ingredients.at(0).type->atom
-170   ¦ && current_instruction().ingredients.at(0).type->name == "continuation") {
-171   // copy multiple calls on to current call stack
-172   assert(scalar(ingredients.at(0)));
-173   if (Delimited_continuation.find(ingredients.at(0).at(0)) == Delimited_continuation.end())
-174   ¦ raise << maybe(current_recipe_name()) << "no such delimited continuation " << current_instruction().ingredients.at(0).original_string << '\n' << end();
-175   const call_stack& new_calls = Delimited_continuation[ingredients.at(0).at(0)];
-176   const call& caller = (SIZE(new_calls) > 1) ? *++new_calls.begin() : Current_routine->calls.front();
-177   for (call_stack::const_reverse_iterator p = new_calls.rbegin(); p != new_calls.rend(); ++p)
-178   ¦ Current_routine->calls.push_front(*p);
-179   if (Trace_stream) {
-180   ¦ Trace_stream->callstack_depth += SIZE(new_calls);
-181   ¦ trace("trace") << "calling delimited continuation; growing callstack depth to " << Trace_stream->callstack_depth << end();
-182   ¦ assert(Trace_stream->callstack_depth < 9000);  // 9998-101 plus cushion
-183   }
-184   ++current_step_index();  // skip past the return-continuation-until-mark
-185   ingredients.erase(ingredients.begin());  // drop the callee
-186   finish_call_housekeeping(to_instruction(caller), ingredients);
-187   continue;
-188 }
+ 15 //: recipe.
+ 16 //:
+ 17 //: See the example programs continuation*.mu to get a sense for the
+ 18 //: possibilities.
+ 19 //:
+ 20 //: Refinements:
+ 21 //:  * You can call a single continuation multiple times, and it will preserve
+ 22 //:    the state of its local variables at each stack frame between calls.
+ 23 //:    The stack frames of a continuation are not destroyed until the
+ 24 //:    continuation goes out of scope. See continuation2.mu.
+ 25 //:  * 'return-continuation-until-mark' doesn't consume the mark, so you can
+ 26 //:    return multiple continuations based on a single mark. In combination
+ 27 //:    with the fact that 'return-continuation-until-mark' can return from
+ 28 //:    regular calls, just as long as there was an earlier call to
+ 29 //:    'call-with-continuation-mark', this gives us a way to create resumable
+ 30 //:    recipes. See continuation3.mu.
+ 31 //:
+ 32 //: Caveats:
+ 33 //:  * At the moment we can't statically type-check continuations. So we raise
+ 34 //:    runtime errors for a call that doesn't return a continuation when the
+ 35 //:    caller expects, or one that returns a continuation when the caller
+ 36 //:    doesn't expect it. This shouldn't cause memory corruption, though.
+ 37 //:    There should still be no way to lookup addresses that aren't allocated.
+ 38 
+ 39 :(before "End Mu Types Initialization")
+ 40 type_ordinal continuation = Type_ordinal["continuation"] = Next_type_ordinal++;
+ 41 Type[continuation].name = "continuation";
+ 42 
+ 43 //: A continuation can be called like a recipe.
+ 44 :(before "End is_mu_recipe Atom Cases(r)")
+ 45 if (r.type->name == "continuation") return true;
+ 46 
+ 47 //: However, it can't be type-checked like most recipes. Pretend it's like a
+ 48 //: header-less recipe.
+ 49 :(after "Begin Reagent->Recipe(r, recipe_header)")
+ 50 if (r.type->atom && r.type->name == "continuation") {
+ 51   result_header.has_header = false;
+ 52   return result_header;
+ 53 }
+ 54 
+ 55 :(scenario delimited_continuation)
+ 56 recipe main [
+ 57   1:continuation <- call-with-continuation-mark f, 77  # 77 is an argument to f
+ 58   2:number <- copy 5
+ 59   {
+ 60   ¦ 2:number <- call 1:continuation, 2:number  # 2 is an argument to g, the 'top' of the continuation
+ 61   ¦ 3:boolean <- greater-or-equal 2:number, 8
+ 62   ¦ break-if 3:boolean
+ 63   ¦ loop
+ 64   }
+ 65 ]
+ 66 recipe f [
+ 67   11:number <- next-ingredient
+ 68   12:number <- g 11:number
+ 69   return 12:number
+ 70 ]
+ 71 recipe g [
+ 72   21:number <- next-ingredient
+ 73   rewind-ingredients
+ 74   return-continuation-until-mark
+ 75   # calls of the continuation start from here
+ 76   22:number <- next-ingredient
+ 77   23:number <- add 22:number, 1
+ 78   return 23:number
+ 79 ]
+ 80 # first call of 'g' executes the part before return-continuation-until-mark
+ 81 +mem: storing 77 in location 21
+ 82 +run: {2: "number"} <- copy {5: "literal"}
+ 83 +mem: storing 5 in location 2
+ 84 # calls of the continuation execute the part after return-continuation-until-mark
+ 85 +run: {2: "number"} <- call {1: "continuation"}, {2: "number"}
+ 86 +mem: storing 5 in location 22
+ 87 +mem: storing 6 in location 2
+ 88 +run: {2: "number"} <- call {1: "continuation"}, {2: "number"}
+ 89 +mem: storing 6 in location 22
+ 90 +mem: storing 7 in location 2
+ 91 +run: {2: "number"} <- call {1: "continuation"}, {2: "number"}
+ 92 +mem: storing 7 in location 22
+ 93 +mem: storing 8 in location 2
+ 94 # first call of 'g' does not execute the part after return-continuation-until-mark
+ 95 -mem: storing 77 in location 22
+ 96 # calls of the continuation don't execute the part before return-continuation-until-mark
+ 97 -mem: storing 5 in location 21
+ 98 -mem: storing 6 in location 21
+ 99 -mem: storing 7 in location 21
+100 # termination
+101 -mem: storing 9 in location 2
+102 
+103 :(before "End call Fields")
+104 bool is_base_of_continuation;
+105 :(before "End call Constructor")
+106 is_base_of_continuation = false;
+107 
+108 :(before "End Primitive Recipe Declarations")
+109 CALL_WITH_CONTINUATION_MARK,
+110 :(before "End Primitive Recipe Numbers")
+111 Recipe_ordinal["call-with-continuation-mark"] = CALL_WITH_CONTINUATION_MARK;
+112 :(before "End Primitive Recipe Checks")
+113 case CALL_WITH_CONTINUATION_MARK: {
+114   break;
+115 }
+116 :(before "End Primitive Recipe Implementations")
+117 case CALL_WITH_CONTINUATION_MARK: {
+118   // like call, but mark the current call as a 'base of continuation' call
+119   // before pushing the next one on it
+120   if (Trace_stream) {
+121   ¦ ++Trace_stream->callstack_depth;
+122   ¦ trace("trace") << "delimited continuation; incrementing callstack depth to " << Trace_stream->callstack_depth << end();
+123   ¦ assert(Trace_stream->callstack_depth < 9000);  // 9998-101 plus cushion
+124   }
+125   const instruction& caller_instruction = current_instruction();
+126   Current_routine->calls.front().is_base_of_continuation = true;
+127   Current_routine->calls.push_front(call(Recipe_ordinal[current_instruction().ingredients.at(0).name]));
+128   ingredients.erase(ingredients.begin());  // drop the callee
+129   finish_call_housekeeping(caller_instruction, ingredients);
+130   continue;
+131 }
+132 
+133 //: save the slice of current call stack until the 'call-with-continuation-mark'
+134 //: call, and return it as the result.
+135 //: todo: implement delimited continuations in Mu's memory
+136 :(before "End Globals")
+137 map<long long int, call_stack> Delimited_continuation;
+138 long long int Next_delimited_continuation_id = 1;  // 0 is null just like an address
+139 :(before "End Reset")
+140 Delimited_continuation.clear();
+141 Next_delimited_continuation_id = 1;
+142 
+143 :(before "End Primitive Recipe Declarations")
+144 RETURN_CONTINUATION_UNTIL_MARK,
+145 :(before "End Primitive Recipe Numbers")
+146 Recipe_ordinal["return-continuation-until-mark"] = RETURN_CONTINUATION_UNTIL_MARK;
+147 :(before "End Primitive Recipe Checks")
+148 case RETURN_CONTINUATION_UNTIL_MARK: {
+149   break;
+150 }
+151 :(before "End Primitive Recipe Implementations")
+152 case RETURN_CONTINUATION_UNTIL_MARK: {
+153   // first clear any existing ingredients, to isolate the creation of the
+154   // continuation from its calls
+155   Current_routine->calls.front().ingredient_atoms.clear();
+156   Current_routine->calls.front().next_ingredient_to_process = 0;
+157   // copy the current call stack until the most recent marked call
+158   call_stack::iterator find_base_of_continuation(call_stack& c);  // manual prototype containing '::'
+159   call_stack::iterator base = find_base_of_continuation(Current_routine->calls);
+160   if (base == Current_routine->calls.end()) {
+161   ¦ raise << maybe(current_recipe_name()) << "couldn't find a 'call-with-continuation-mark' to return to\n" << end();
+162   ¦ raise << maybe(current_recipe_name()) << "call stack:\n" << end();
+163   ¦ for (call_stack::iterator p = Current_routine->calls.begin();  p != Current_routine->calls.end();  ++p)
+164   ¦ ¦ raise << maybe(current_recipe_name()) << "  " << get(Recipe, p->running_recipe).name << '\n' << end();
+165   ¦ break;
+166   }
+167   trace("run") << "creating continuation " << Next_delimited_continuation_id << end();
+168   Delimited_continuation[Next_delimited_continuation_id] = call_stack(Current_routine->calls.begin(), base);
+169   while (Current_routine->calls.begin() != base) {
+170   ¦ if (Trace_stream) {
+171   ¦ ¦ --Trace_stream->callstack_depth;
+172   ¦ ¦ assert(Trace_stream->callstack_depth >= 0);
+173   ¦ }
+174   ¦ Current_routine->calls.pop_front();
+175   }
+176   // return it as the result of the marked call
+177   products.resize(1);
+178   products.at(0).push_back(Next_delimited_continuation_id);
+179   // return any other ingredients passed in
+180   copy(ingredients.begin(), ingredients.end(), inserter(products, products.end()));
+181   ++Next_delimited_continuation_id;
+182   break;  // continue to process rest of marked call
+183 }
+184 
+185 :(code)
+186 call_stack::iterator find_base_of_continuation(call_stack& c) {
+187   for (call_stack::iterator p = c.begin(); p != c.end(); ++p)
+188   ¦ if (p->is_base_of_continuation) return p;
+189   return c.end();
+190 }
+191 
+192 //: overload 'call' for continuations
+193 :(after "Begin Call")
+194 if (current_instruction().ingredients.at(0).type->atom
+195   ¦ && current_instruction().ingredients.at(0).type->name == "continuation") {
+196   // copy multiple calls on to current call stack
+197   assert(scalar(ingredients.at(0)));
+198   trace("run") << "calling continuation " << ingredients.at(0).at(0) << end();
+199   if (Delimited_continuation.find(ingredients.at(0).at(0)) == Delimited_continuation.end())
+200   ¦ raise << maybe(current_recipe_name()) << "no such delimited continuation " << current_instruction().ingredients.at(0).original_string << '\n' << end();
+201   const call_stack& new_calls = Delimited_continuation[ingredients.at(0).at(0)];
+202   const call& caller = (SIZE(new_calls) > 1) ? *++new_calls.begin() : Current_routine->calls.front();
+203   for (call_stack::const_reverse_iterator p = new_calls.rbegin(); p != new_calls.rend(); ++p) {
+204   ¦ Current_routine->calls.push_front(*p);
+205   ¦ // ensure that the presence of a continuation keeps its stack frames from being reclaimed
+206   ¦ int space_address = Current_routine->calls.front().default_space;
+207   ¦ if (space_address != 0) {
+208   ¦ ¦ int refcount = get_or_insert(Memory, space_address);
+209   ¦ ¦ trace("mem") << "incrementing refcount of " << space_address << ": " << refcount << " -> " << refcount+1 << end();
+210   ¦ ¦ put(Memory, space_address, refcount+1);
+211   ¦ }
+212   }
+213   if (Trace_stream) {
+214   ¦ Trace_stream->callstack_depth += SIZE(new_calls);
+215   ¦ trace("trace") << "calling delimited continuation; growing callstack depth to " << Trace_stream->callstack_depth << end();
+216   ¦ assert(Trace_stream->callstack_depth < 9000);  // 9998-101 plus cushion
+217   }
+218   ++current_step_index();  // skip past the return-continuation-until-mark
+219   ingredients.erase(ingredients.begin());  // drop the callee
+220   finish_call_housekeeping(to_instruction(caller), ingredients);
+221   continue;
+222 }
+223 
+224 //: Ensure that the presence of a continuation keeps its stack frames from being reclaimed.
+225 
+226 :(scenario continuations_preserve_local_scopes)
+227 def main [
+228   local-scope
+229   k:continuation <- call-with-continuation-mark f
+230   call k
+231   return 34
+232 ]
+233 def f [
+234   local-scope
+235   g
+236 ]
+237 def g [
+238   local-scope
+239   return-continuation-until-mark
+240   add 1, 1
+241 ]
+242 # entering main
+243 +mem: new alloc: 1000
+244 +run: {k: "continuation"} <- call-with-continuation-mark {f: "recipe-literal"}
+245 # entering f
+246 +mem: new alloc: 1004
+247 # entering g
+248 +mem: new alloc: 1007
+249 # return control to main
+250 +run: return-continuation-until-mark
+251 # no allocs abandoned yet
+252 # finish running main
+253 +run: call {k: "continuation"}
+254 +run: add {1: "literal"}, {1: "literal"}
+255 +run: return {34: "literal"}
+256 # now k is reclaimed
+257 +mem: trying to reclaim local k:continuation
+258 # at this point all allocs in the continuation are abandoned
+259 +mem: automatically abandoning 1007
+260 +mem: automatically abandoning 1004
+261 # finally the alloc for main is abandoned
+262 +mem: automatically abandoning 1000
+263 
+264 :(after "Begin Decrement Refcounts(canonized_x)")
+265 if (is_mu_continuation(canonized_x)) {
+266   int continuation_id = get_or_insert(Memory, canonized_x.value);
+267   trace("run") << "reclaiming continuation " << continuation_id << end();
+268   if (continuation_id == 0) return;
+269   const call_stack& continuation_calls = get(Delimited_continuation, continuation_id);
+270   // temporarily push the stack frames for the continuation one last time on to the call stack
+271   for (call_stack::const_reverse_iterator p = continuation_calls.rbegin(); p != continuation_calls.rend(); ++p)
+272   ¦ Current_routine->calls.push_front(*p);
+273   // reclaim their spaces while popping them
+274   // (because reclaim_default_space() relies on the default-space being reclaimed being at the top of the stack)
+275   for (call_stack::const_iterator p = continuation_calls.begin(); p != continuation_calls.end(); ++p) {
+276   ¦ reclaim_default_space();
+277   ¦ Current_routine->calls.pop_front();
+278   }
+279   return;
+280 }
+281 
+282 :(code)
+283 bool is_mu_continuation(reagent/*copy*/ x) {
+284   canonize_type(x);
+285   return x.type && x.type->atom && x.type->value == get(Type_ordinal, "continuation");
+286 }
+287 
+288 :(scenario continuations_can_return_values)
+289 def main [
+290   local-scope
+291   k:continuation, 1:num/raw <- call-with-continuation-mark f
+292 ]
+293 def f [
+294   local-scope
+295   g
+296 ]
+297 def g [
+298   local-scope
+299   return-continuation-until-mark 34
+300   stash [continuation called]
+301 ]
+302 # entering main
+303 +mem: new alloc: 1000
+304 +run: {k: "continuation"}, {1: "number", "raw": ()} <- call-with-continuation-mark {f: "recipe-literal"}
+305 # entering f
+306 +mem: new alloc: 1004
+307 # entering g
+308 +mem: new alloc: 1007
+309 # return control to main
+310 +run: return-continuation-until-mark {34: "literal"}
+311 # no allocs abandoned yet
+312 +mem: storing 34 in location 1
+313 # end of main
+314 # make sure no memory leaks..
+315 +mem: trying to reclaim local k:continuation
+316 +mem: automatically abandoning 1007
+317 +mem: automatically abandoning 1004
+318 +mem: automatically abandoning 1000
+319 # ..even though we never called the continuation
+320 -app: continuation called
 
diff --git a/html/082scenario_screen.cc.html b/html/082scenario_screen.cc.html index c04ed1ee..cde419df 100644 --- a/html/082scenario_screen.cc.html +++ b/html/082scenario_screen.cc.html @@ -69,7 +69,7 @@ if ('onhashchange' in window) { 4 //: scenario. 'screen-should-contain' can check unicode characters in the fake 5 //: screen 6 - 7 //: first make sure we don't mangle these functions in other transforms + 7 //: first make sure we don't mangle these instructions in other transforms 8 :(before "End initialize_transform_rewrite_literal_string_to_text()") 9 recipes_taking_literal_strings.insert("screen-should-contain"); 10 recipes_taking_literal_strings.insert("screen-should-contain-in-color"); diff --git a/html/085scenario_console.cc.html b/html/085scenario_console.cc.html index 5a7fd154..67b651cc 100644 --- a/html/085scenario_console.cc.html +++ b/html/085scenario_console.cc.html @@ -66,7 +66,7 @@ if ('onhashchange' in window) { 4 //: scenario. Like with the fake screen, 'assume-console' transparently 5 //: supports unicode. 6 - 7 //: first make sure we don't mangle these functions in other transforms + 7 //: first make sure we don't mangle this instruction in other transforms 8 :(before "End initialize_transform_rewrite_literal_string_to_text()") 9 recipes_taking_literal_strings.insert("assume-console"); 10 @@ -128,7 +128,7 @@ if ('onhashchange' in window) { 66 for (int i = 0; i < SIZE(r.steps); ++i) { 67 ¦ const instruction& inst = r.steps.at(i); 68 ¦ if (inst.name == "left-click") { - 69 ¦ ¦ trace(9999, "mem") << "storing 'left-click' event starting at " << Current_routine->alloc << end(); + 69 ¦ ¦ trace("mem") << "storing 'left-click' event starting at " << Current_routine->alloc << end(); 70 ¦ ¦ put(Memory, curr_address, /*tag for 'touch-event' variant of 'event' exclusive-container*/2); 71 ¦ ¦ put(Memory, curr_address+/*skip tag*/1+/*offset of 'type' in 'mouse-event'*/0, TB_KEY_MOUSE_LEFT); 72 ¦ ¦ put(Memory, curr_address+/*skip tag*/1+/*offset of 'row' in 'mouse-event'*/1, to_integer(inst.ingredients.at(0).name)); @@ -136,7 +136,7 @@ if ('onhashchange' in window) { 74 ¦ ¦ curr_address += size_of_event(); 75 ¦ } 76 ¦ else if (inst.name == "press") { - 77 ¦ ¦ trace(9999, "mem") << "storing 'press' event starting at " << curr_address << end(); + 77 ¦ ¦ trace("mem") << "storing 'press' event starting at " << curr_address << end(); 78 ¦ ¦ string key = inst.ingredients.at(0).name; 79 ¦ ¦ if (is_integer(key)) 80 ¦ ¦ ¦ put(Memory, curr_address+1, to_integer(key)); @@ -157,18 +157,18 @@ if ('onhashchange' in window) { 95 ¦ else { 96 ¦ ¦ // keyboard input 97 ¦ ¦ assert(inst.name == "type"); - 98 ¦ ¦ trace(9999, "mem") << "storing 'type' event starting at " << curr_address << end(); + 98 ¦ ¦ trace("mem") << "storing 'type' event starting at " << curr_address << end(); 99 ¦ ¦ const string& contents = inst.ingredients.at(0).name; 100 ¦ ¦ const char* raw_contents = contents.c_str(); 101 ¦ ¦ int num_keyboard_events = unicode_length(contents); 102 ¦ ¦ int curr = 0; 103 ¦ ¦ for (int i = 0; i < num_keyboard_events; ++i) { -104 ¦ ¦ ¦ trace(9999, "mem") << "storing 'text' tag at " << curr_address << end(); +104 ¦ ¦ ¦ trace("mem") << "storing 'text' tag at " << curr_address << end(); 105 ¦ ¦ ¦ put(Memory, curr_address, /*tag for 'text' variant of 'event' exclusive-container*/0); 106 ¦ ¦ ¦ uint32_t curr_character; 107 ¦ ¦ ¦ assert(curr < SIZE(contents)); 108 ¦ ¦ ¦ tb_utf8_char_to_unicode(&curr_character, &raw_contents[curr]); -109 ¦ ¦ ¦ trace(9999, "mem") << "storing character " << curr_character << " at " << curr_address+/*skip exclusive container tag*/1 << end(); +109 ¦ ¦ ¦ trace("mem") << "storing character " << curr_character << " at " << curr_address+/*skip exclusive container tag*/1 << end(); 110 ¦ ¦ ¦ put(Memory, curr_address+/*skip exclusive container tag*/1, curr_character); 111 ¦ ¦ ¦ curr += tb_utf8_char_length(raw_contents[curr]); 112 ¦ ¦ ¦ curr_address += size_of_event(); @@ -178,9 +178,9 @@ if ('onhashchange' in window) { 116 assert(curr_address == event_data_address+size); 117 // wrap the array of events in a console object 118 int console_address = allocate(size_of_console()); -119 trace(9999, "mem") << "storing console in " << console_address << end(); +119 trace("mem") << "storing console in " << console_address << end(); 120 put(Memory, CONSOLE, console_address); -121 trace(9999, "mem") << "storing console data in " << console_address+/*skip refcount*/1+/*offset of 'data' in container 'events'*/1 << end(); +121 trace("mem") << "storing console data in " << console_address+/*skip refcount*/1+/*offset of 'data' in container 'events'*/1 << end(); 122 put(Memory, console_address+/*skip refcount*/1+/*offset of 'data' in container 'events'*/1, event_data_address); 123 // increment refcount for event data 124 put(Memory, event_data_address, 1); diff --git a/html/089scenario_filesystem.cc.html b/html/089scenario_filesystem.cc.html index 77deb8a0..434dcc16 100644 --- a/html/089scenario_filesystem.cc.html +++ b/html/089scenario_filesystem.cc.html @@ -269,31 +269,31 @@ if ('onhashchange' in window) { 207 int curr = resources_data_address + /*skip refcount and length*/2; 208 for (map<string, string>::const_iterator p = contents.begin(); p != contents.end(); ++p) { 209 ¦ put(Memory, curr, new_mu_text(p->first)); -210 ¦ trace(9999, "mem") << "storing file name " << get(Memory, curr) << " in location " << curr << end(); +210 ¦ trace("mem") << "storing file name " << get(Memory, curr) << " in location " << curr << end(); 211 ¦ put(Memory, get(Memory, curr), 1); -212 ¦ trace(9999, "mem") << "storing refcount 1 in location " << get(Memory, curr) << end(); +212 ¦ trace("mem") << "storing refcount 1 in location " << get(Memory, curr) << end(); 213 ¦ ++curr; 214 ¦ put(Memory, curr, new_mu_text(p->second)); -215 ¦ trace(9999, "mem") << "storing file contents " << get(Memory, curr) << " in location " << curr << end(); +215 ¦ trace("mem") << "storing file contents " << get(Memory, curr) << " in location " << curr << end(); 216 ¦ put(Memory, get(Memory, curr), 1); -217 ¦ trace(9999, "mem") << "storing refcount 1 in location " << get(Memory, curr) << end(); +217 ¦ trace("mem") << "storing refcount 1 in location " << get(Memory, curr) << end(); 218 ¦ ++curr; 219 } 220 curr = resources_data_address+/*skip refcount*/1; 221 put(Memory, curr, SIZE(contents)); // size of array -222 trace(9999, "mem") << "storing resources size " << get(Memory, curr) << " in location " << curr << end(); +222 trace("mem") << "storing resources size " << get(Memory, curr) << " in location " << curr << end(); 223 put(Memory, resources_data_address, 1); // initialize refcount -224 trace(9999, "mem") << "storing refcount 1 in location " << resources_data_address << end(); +224 trace("mem") << "storing refcount 1 in location " << resources_data_address << end(); 225 // wrap the resources data in a 'resources' object 226 int resources_address = allocate(size_of_resources()); 227 curr = resources_address+/*skip refcount*/1+/*offset of 'data' element*/1; 228 put(Memory, curr, resources_data_address); -229 trace(9999, "mem") << "storing resources data address " << resources_data_address << " in location " << curr << end(); +229 trace("mem") << "storing resources data address " << resources_data_address << " in location " << curr << end(); 230 put(Memory, resources_address, 1); // initialize refcount -231 trace(9999, "mem") << "storing refcount 1 in location " << resources_address << end(); +231 trace("mem") << "storing refcount 1 in location " << resources_address << end(); 232 // save in product 233 put(Memory, RESOURCES, resources_address); -234 trace(9999, "mem") << "storing resources address " << resources_address << " in location " << RESOURCES << end(); +234 trace("mem") << "storing resources address " << resources_address << " in location " << RESOURCES << end(); 235 } 236 237 int size_of_resources() { diff --git a/html/099hardware_checks.cc.html b/html/099hardware_checks.cc.html index 66ae664c..80835903 100644 --- a/html/099hardware_checks.cc.html +++ b/html/099hardware_checks.cc.html @@ -61,9 +61,9 @@ if ('onhashchange' in window) {
- 1 //: Let's raise errors when students use real hardware in any functions
- 2 //: besides 'main'. Part of the goal is to teach them testing hygiene and
- 3 //: dependency injection.
+ 1 //: Let's raise errors when students use real hardware in any recipes besides
+ 2 //: 'main'. Part of the goal is to teach them testing hygiene and dependency
+ 3 //: injection.
  4 //:
  5 //: This is easy to sidestep, it's for feedback rather than safety.
  6 
diff --git a/html/101run_sandboxed.cc.html b/html/101run_sandboxed.cc.html
index bf52a190..0dde51a3 100644
--- a/html/101run_sandboxed.cc.html
+++ b/html/101run_sandboxed.cc.html
@@ -153,7 +153,7 @@ if ('onhashchange' in window) {
  89 // reads a string, tries to call it as code (treating it as a test), saving
  90 // all errors.
  91 // returns true if successfully called (no errors found during load and transform)
- 92 bool run_interactive(int address) {
+ 92 bool run_interactive(int address) {
  93   assert(contains_key(Recipe_ordinal, "interactive") && get(Recipe_ordinal, "interactive") != 0);
  94   // try to sandbox the run as best you can
  95   // todo: test this
@@ -161,7 +161,7 @@ if ('onhashchange' in window) {
  97   ¦ for (int i = 1; i < Reserved_for_tests; ++i)
  98   ¦ ¦ Memory.erase(i);
  99   }
-100   string command = trim(strip_comments(read_mu_text(address)));
+100   string command = trim(strip_comments(read_mu_text(address)));
 101   Name[get(Recipe_ordinal, "interactive")].clear();
 102   run_code_begin(/*should_stash_snapshots*/true);
 103   if (command.empty()) return false;
@@ -549,10 +549,10 @@ if ('onhashchange' in window) {
 485   return result.str();
 486 }
 487 
-488 int stringified_value_of_location(int address) {
+488 int stringified_value_of_location(int address) {
 489   // convert to string
 490   ostringstream out;
-491   out << no_scientific(get_or_insert(Memory, address));
+491   out << no_scientific(get_or_insert(Memory, address));
 492   return new_mu_text(out.str());
 493 }
 494 
-- 
cgit 1.4.1-2-gfad0