diff options
-rw-r--r-- | 026call.cc | 47 | ||||
-rw-r--r-- | 039location_array.cc | 46 | ||||
-rw-r--r-- | 042name.cc | 7 | ||||
-rw-r--r-- | 043space.cc | 70 | ||||
-rw-r--r-- | 045closure_name.cc | 4 | ||||
-rw-r--r-- | 046check_type_by_name.cc | 17 | ||||
-rw-r--r-- | 057immutable.cc | 6 | ||||
-rw-r--r-- | 073scheduler.cc | 2 |
8 files changed, 128 insertions, 71 deletions
diff --git a/026call.cc b/026call.cc index a82917f1..6b7a14f7 100644 --- a/026call.cc +++ b/026call.cc @@ -69,6 +69,8 @@ routine::routine(recipe_ordinal r) { //:: now update routine's helpers +//: macro versions for a slight speedup + :(delete{} "int& current_step_index()") :(delete{} "recipe_ordinal currently_running_recipe()") :(delete{} "const string& current_recipe_name()") @@ -84,6 +86,51 @@ routine::routine(recipe_ordinal r) { #define to_instruction(call) get(Recipe, (call).running_recipe).steps.at((call).running_step_index) #define current_instruction() to_instruction(current_call()) +//: function versions for debugging + +:(code) +//? :(before "End Globals") +//? bool Foo2 = false; +//? :(code) +//? call& current_call() { +//? if (Foo2) cerr << __FUNCTION__ << '\n'; +//? return Current_routine->calls.front(); +//? } +//? :(replace{} "int& current_step_index()") +//? int& current_step_index() { +//? assert(!Current_routine->calls.empty()); +//? if (Foo2) cerr << __FUNCTION__ << '\n'; +//? return current_call().running_step_index; +//? } +//? :(replace{} "recipe_ordinal currently_running_recipe()") +//? recipe_ordinal currently_running_recipe() { +//? assert(!Current_routine->calls.empty()); +//? if (Foo2) cerr << __FUNCTION__ << '\n'; +//? return current_call().running_recipe; +//? } +//? :(replace{} "const string& current_recipe_name()") +//? const string& current_recipe_name() { +//? assert(!Current_routine->calls.empty()); +//? if (Foo2) cerr << __FUNCTION__ << '\n'; +//? return get(Recipe, current_call().running_recipe).name; +//? } +//? :(replace{} "const recipe& current_recipe()") +//? const recipe& current_recipe() { +//? assert(!Current_routine->calls.empty()); +//? if (Foo2) cerr << __FUNCTION__ << '\n'; +//? return get(Recipe, current_call().running_recipe); +//? } +//? :(replace{} "const instruction& current_instruction()") +//? const instruction& current_instruction() { +//? assert(!Current_routine->calls.empty()); +//? if (Foo2) cerr << __FUNCTION__ << '\n'; +//? return to_instruction(current_call()); +//? } +//? :(code) +//? const instruction& to_instruction(const call& call) { +//? return get(Recipe, call.running_recipe).steps.at(call.running_step_index); +//? } + :(after "Defined Recipe Checks") // not a primitive; check that it's present in the book of recipes if (!contains_key(Recipe, inst.operation)) { diff --git a/039location_array.cc b/039location_array.cc deleted file mode 100644 index 1c12d316..00000000 --- a/039location_array.cc +++ /dev/null @@ -1,46 +0,0 @@ -:(before "End Primitive Recipe Declarations") -TO_LOCATION_ARRAY, -:(before "End Primitive Recipe Numbers") -put(Recipe_ordinal, "to-location-array", TO_LOCATION_ARRAY); -:(before "End Primitive Recipe Checks") -case TO_LOCATION_ARRAY: { - const recipe& caller = get(Recipe, r); - if (!is_address_of_array_of_numbers(inst.products.at(0))) { - raise << maybe(caller.name) << "product of 'to-location-array' has incorrect type: '" << to_original_string(inst) << "'\n" << end(); - break; - } - break; -} -:(code) -bool is_address_of_array_of_numbers(reagent/*copy*/ x) { - canonize_type(x); - if (!is_compound_type_starting_with(x.type, "address")) return false; - drop_from_type(x, "address"); - if (!is_compound_type_starting_with(x.type, "array")) return false; - drop_from_type(x, "array"); - return x.type && x.type->atom && x.type->value == get(Type_ordinal, "number"); -} -bool is_compound_type_starting_with(const type_tree* type, const string& expected_name) { - if (!type) return false; - if (type->atom) return false; - if (!type->left->atom) return false; - return type->left->value == get(Type_ordinal, expected_name); -} - -:(before "End Primitive Recipe Implementations") -case TO_LOCATION_ARRAY: { - int array_size = SIZE(ingredients.at(0)); - int allocation_size = array_size + /*refcount and length*/2; - ensure_space(allocation_size); - const int result = Current_routine->alloc; - products.resize(1); - products.at(0).push_back(result); - // initialize array refcount - put(Memory, result, 0); - // initialize array length - put(Memory, result+1, array_size); - // now copy over data - for (int i = 0; i < array_size; ++i) - put(Memory, result+2+i, ingredients.at(0).at(i)); - break; -} diff --git a/042name.cc b/042name.cc index 34e3efe0..6aaf6066 100644 --- a/042name.cc +++ b/042name.cc @@ -130,6 +130,13 @@ type_ordinal skip_addresses(type_tree* type) { return base_type->left->value; } +bool is_compound_type_starting_with(const type_tree* type, const string& expected_name) { + if (!type) return false; + if (type->atom) return false; + if (!type->left->atom) return false; + return type->left->value == get(Type_ordinal, expected_name); +} + int find_element_name(const type_ordinal t, const string& name, const string& recipe_name) { const type_info& container = get(Type, t); for (int i = 0; i < SIZE(container.elements); ++i) diff --git a/043space.cc b/043space.cc index 2f11c6c2..ce6e5623 100644 --- a/043space.cc +++ b/043space.cc @@ -86,7 +86,9 @@ int address(int offset, int base) { int size = get_or_insert(Memory, base); if (offset >= size) { // todo: test - raise << "location " << offset << " is out of bounds " << size << " at " << base << '\n' << end(); + raise << current_recipe_name() << ": location " << offset << " is out of bounds " << size << " at " << base << '\n' << end(); + DUMP(""); + exit(1); return 0; } return base + /*skip length*/1 + offset; @@ -96,14 +98,19 @@ int address(int offset, int base) { :(after "Begin Preprocess write_memory(x, data)") if (x.name == "default-space") { - if (!scalar(data) || !is_space(x)) + if (!scalar(data) || !is_mu_space(x)) raise << maybe(current_recipe_name()) << "'default-space' should be of type address:array:location, but is " << to_string(x.type) << '\n' << end(); current_call().default_space = data.at(0); return; } :(code) -bool is_space(const reagent& r) { - return is_address_of_array_of_numbers(r); +bool is_mu_space(reagent/*copy*/ x) { + canonize_type(x); + if (!is_compound_type_starting_with(x.type, "address")) return false; + drop_from_type(x, "address"); + if (!is_compound_type_starting_with(x.type, "array")) return false; + drop_from_type(x, "array"); + return x.type && x.type->atom && x.type->name == "location"; } :(scenario get_default_space) @@ -237,14 +244,34 @@ reclaim_default_space(); :(code) void reclaim_default_space() { if (!Reclaim_memory) return; - const recipe_ordinal r = get(Recipe_ordinal, current_recipe_name()); - const recipe& exiting_recipe = get(Recipe, r); - if (!starts_by_setting_default_space(exiting_recipe)) return; - // Reclaim default-space - decrement_refcount(current_call().default_space, - exiting_recipe.steps.at(0).products.at(0).type->right, - /*refcount*/1 + /*array length*/1 + /*number-of-locals*/Name[r][""]); + reagent default_space("default-space:address:array:location"); + decrement_any_refcounts(default_space); } +:(after "Begin Decrement Refcounts(canonized_x)") +if (is_mu_space(canonized_x)) { + int space_address = (canonized_x.name == "default-space") ? current_call().default_space : get_or_insert(Memory, canonized_x.value); + if (space_address == 0) return; + // this branch relies on global state + string recipe_name; + if (has_property(canonized_x, "names")) { + assert(property(canonized_x, "names")->atom); + recipe_name = property(canonized_x, "names")->value; + } + else { + if (canonized_x.name != "default-space") + cerr << current_recipe_name() << ": " << to_string(canonized_x) << '\n'; + assert(canonized_x.name == "default-space"); + recipe_name = current_recipe_name(); + } + const recipe_ordinal space_recipe_ordinal = get(Recipe_ordinal, recipe_name); + const recipe& space_recipe = get(Recipe, space_recipe_ordinal); + if (canonized_x.name == "default-space" && !has_property(canonized_x, "names") && !starts_by_setting_default_space(space_recipe)) return; + // Reclaim Space(space_address, space_recipe_ordinal, space_recipe) + decrement_refcount(space_address, canonized_x.type->right, + /*refcount*/1 + /*array length*/1 + /*number-of-locals*/Name[space_recipe_ordinal][""]); + return; +} +:(code) bool starts_by_setting_default_space(const recipe& r) { return !r.steps.empty() && !r.steps.at(0).products.empty() @@ -263,12 +290,16 @@ def main [ # local-scope +mem: automatically abandoning 1000 -:(before "Reclaim default-space") -if (get_or_insert(Memory, current_call().default_space) <= 1) { +:(before "Reclaim Space(space_address, space_recipe_ordinal, space_recipe)") +if (get_or_insert(Memory, space_address) <= 1) { set<string> reclaimed_locals; trace(9999, "mem") << "trying to reclaim locals" << end(); - for (int i = /*leave default space for last*/1; i < SIZE(exiting_recipe.steps); ++i) { - const instruction& inst = exiting_recipe.steps.at(i); + // update any refcounts for variables in the space -- in the context of the space + call_stack calls_stash = save_call_stack(space_address, space_recipe_ordinal); + Current_routine->calls.swap(calls_stash); + // no early returns until we restore 'calls' below + for (int i = /*leave default space for last*/1; i < SIZE(space_recipe.steps); ++i) { + const instruction& inst = space_recipe.steps.at(i); for (int i = 0; i < SIZE(inst.products); ++i) { reagent/*copy*/ product = inst.products.at(i); if (reclaimed_locals.find(product.name) != reclaimed_locals.end()) continue; @@ -282,6 +313,15 @@ if (get_or_insert(Memory, current_call().default_space) <= 1) { decrement_any_refcounts(product); } } + Current_routine->calls.swap(calls_stash); // restore +} +:(code) +call_stack save_call_stack(int space_address, recipe_ordinal space_recipe_ordinal) { + call dummy_call(space_recipe_ordinal); + dummy_call.default_space = space_address; + call_stack result; + result.push_front(dummy_call); + return result; } :(scenario local_variables_can_outlive_call) diff --git a/045closure_name.cc b/045closure_name.cc index f7c0082f..0f67e2d2 100644 --- a/045closure_name.cc +++ b/045closure_name.cc @@ -47,7 +47,7 @@ void collect_surrounding_spaces(const recipe_ordinal r) { for (int j = 0; j < SIZE(inst.products); ++j) { if (is_literal(inst.products.at(j))) continue; if (inst.products.at(j).name != "0") continue; - if (!is_space(inst.products.at(j))) { + if (!is_mu_space(inst.products.at(j))) { raise << "slot 0 should always have type address:array:location, but is '" << to_string(inst.products.at(j)) << "'\n" << end(); continue; } @@ -159,7 +159,7 @@ def new-scope [ ] def use-scope [ local-scope - outer:space <- next-ingredient + outer:space/names:new-scope <- next-ingredient 0:space/names:new-scope <- copy outer:space return *x:&:num/space:1 ] diff --git a/046check_type_by_name.cc b/046check_type_by_name.cc index 83b80571..3fd3fdd6 100644 --- a/046check_type_by_name.cc +++ b/046check_type_by_name.cc @@ -25,25 +25,34 @@ void check_or_set_types_by_name(const recipe_ordinal r) { for (int i = 0; i < SIZE(caller.steps); ++i) { instruction& inst = caller.steps.at(i); for (int in = 0; in < SIZE(inst.ingredients); ++in) { - deduce_missing_type(known, inst.ingredients.at(in)); + deduce_missing_type(known, inst.ingredients.at(in), caller); check_type(known, inst.ingredients.at(in), caller); } for (int out = 0; out < SIZE(inst.products); ++out) { - deduce_missing_type(known, inst.products.at(out)); + deduce_missing_type(known, inst.products.at(out), caller); check_type(known, inst.products.at(out), caller); } } } -void deduce_missing_type(set<reagent>& known, reagent& x) { +void deduce_missing_type(set<reagent>& known, reagent& x, const recipe& caller) { if (x.type) return; if (is_jump_target(x.name)) { x.type = new type_tree("label"); return; } if (known.find(x) == known.end()) return; - x.type = new type_tree(*known.find(x)->type); + const reagent& exemplar = *known.find(x); + x.type = new type_tree(*exemplar.type); trace(9992, "transform") << x.name << " <= " << names_to_string(x.type) << end(); + // spaces are special; their type includes their /names property + if (is_mu_space(x) && !has_property(x, "names")) { + if (!has_property(exemplar, "names")) { + raise << maybe(caller.name) << "missing /names property for space variable '" << exemplar.name << "'\n" << end(); + return; + } + x.properties.push_back(pair<string, string_tree*>("names", new string_tree(*property(exemplar, "names")))); + } } void check_type(set<reagent>& known, const reagent& x, const recipe& caller) { diff --git a/057immutable.cc b/057immutable.cc index 4657ade0..6cfcacef 100644 --- a/057immutable.cc +++ b/057immutable.cc @@ -316,16 +316,16 @@ def bar [ //: when checking for immutable ingredients, remember to take space into account :(scenario check_space_of_reagents_in_immutability_checks) def main [ - a:space <- new-closure + a:space/names:new-closure <- new-closure b:&:num <- new number:type run-closure b:&:num, a:space ] def new-closure [ local-scope x:&:num <- new number:type - return default-space + return default-space/names:new-closure ] -def run-closure x:&:num, s:space [ +def run-closure x:&:num, s:space/names:new-closure [ local-scope load-ingredients 0:space/names:new-closure <- copy s diff --git a/073scheduler.cc b/073scheduler.cc index fb1a3f51..d9ebef51 100644 --- a/073scheduler.cc +++ b/073scheduler.cc @@ -313,7 +313,7 @@ def main [ local-scope n:&:num <- copy 12000/unsafe # pretend allocation with a known address *n <- copy 23 - space:space <- create-space n + space:space/names:create-space <- create-space n n2:&:num <- copy 13000/unsafe n3:num <- use-space space, n2 ] |