From 86a6c9cd8952b4600f648519a64a86156d1a3e10 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Mon, 28 Sep 2015 22:21:15 -0700 Subject: 2213 - start moving type checks out of 'run' That way we only have to check each static instruction once, rather than every time it runs. --- 020run.cc | 39 -------------------------- 031address.cc | 5 +--- 032array.cc | 28 +++++++++++++++++++ 048_check_type_by_instruction.cc | 59 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 43 deletions(-) create mode 100644 048_check_type_by_instruction.cc diff --git a/020run.cc b/020run.cc index 6b28e3ff..116d44a7 100644 --- a/020run.cc +++ b/020run.cc @@ -83,20 +83,6 @@ void run_current_routine() switch (current_instruction().operation) { // Primitive Recipe Implementations case COPY: { - if (SIZE(current_instruction().products) != SIZE(ingredients)) { - raise << "ingredients and products should match in '" << current_instruction().to_string() << "'\n" << end(); - break; - } - for (long long int i = 0; i < SIZE(ingredients); ++i) { - if (!is_mu_array(current_instruction().ingredients.at(i)) && is_mu_array(current_instruction().products.at(i))) { - raise << current_recipe_name() << ": can't copy " << current_instruction().ingredients.at(i).original_string << " to array " << current_instruction().products.at(i).original_string << "\n" << end(); - goto finish_instruction; - } - if (is_mu_array(current_instruction().ingredients.at(i)) && !is_mu_array(current_instruction().products.at(i))) { - raise << current_recipe_name() << ": can't copy array " << current_instruction().ingredients.at(i).original_string << " to " << current_instruction().products.at(i).original_string << "\n" << end(); - goto finish_instruction; - } - } copy(ingredients.begin(), ingredients.end(), inserter(products, products.begin())); break; } @@ -317,10 +303,6 @@ bool is_literal(const reagent& r) { return SIZE(r.types) == 1 && r.types.at(0) == 0; } -bool is_mu_array(reagent r) { - return !r.types.empty() && r.types.at(0) == Type_ordinal["array"]; -} - :(code) // helper for tests void run(string form) { @@ -352,27 +334,6 @@ recipe main [ ] -mem: storing 34 in location 0 -:(scenario copy_checks_reagent_count) -% Hide_warnings = true; -recipe main [ - 1:number <- copy 34, 35 -] -+warn: ingredients and products should match in '1:number <- copy 34, 35' - -:(scenario write_scalar_to_array_disallowed) -% Hide_warnings = true; -recipe main [ - 1:array:number <- copy 34 -] -+warn: main: can't copy 34 to array 1:array:number - -:(scenario write_scalar_to_array_disallowed_2) -% Hide_warnings = true; -recipe main [ - 1:number, 2:array:number <- copy 34, 35 -] -+warn: main: can't copy 35 to array 2:array:number - //: mu is robust to various combinations of commas and spaces. You just have //: to put spaces around the '<-'. diff --git a/031address.cc b/031address.cc index 38a891ef..22a57189 100644 --- a/031address.cc +++ b/031address.cc @@ -29,9 +29,6 @@ if (x.value == 0) { return; } -:(after "bool is_mu_array(reagent r)") -r = canonize(r); - //: writes to address 0 always loudly fail :(scenario store_to_0_warns) % Hide_warnings = true; @@ -69,7 +66,7 @@ reagent lookup_memory(reagent x) { // populate types copy(++x.types.begin(), x.types.end(), inserter(result.types, result.types.begin())); - // drop-one 'lookup' + // drop one 'lookup' long long int i = 0; long long int len = SIZE(x.properties); for (i = 0; i < len; ++i) { diff --git a/032array.cc b/032array.cc index 1b8d5900..7ad84367 100644 --- a/032array.cc +++ b/032array.cc @@ -332,3 +332,31 @@ case LENGTH: { recipe_ordinal r = current_instruction().operation; if (r == CREATE_ARRAY || r == INDEX || r == INDEX_ADDRESS || r == LENGTH) return false; + +:(code) +bool is_mu_array(reagent r) { + if (is_literal(r)) return false; + while (has_property(r, "lookup")) { + if (r.types.empty()) { + raise << "can't lookup non-address: " << r.original_string << '\n' << end(); + return false; + } + if (r.types.at(0) != Type_ordinal["address"]) { + raise << "can't lookup non-address: " << r.original_string << '\n' << end(); + return false; + } + r.types.erase(r.types.begin()); + drop_one_lookup(r); + } + return !r.types.empty() && r.types.at(0) == Type_ordinal["array"]; +} + +void drop_one_lookup(reagent& r) { + for (vector > >::iterator p = r.properties.begin(); p != r.properties.end(); ++p) { + if (p->first == "lookup") { + r.properties.erase(p); + return; + } + } + assert(false); +} diff --git a/048_check_type_by_instruction.cc b/048_check_type_by_instruction.cc new file mode 100644 index 00000000..dab8916b --- /dev/null +++ b/048_check_type_by_instruction.cc @@ -0,0 +1,59 @@ + + +:(after "int main") + Transform.push_back(check_types_by_instruction); + +:(code) +void check_types_by_instruction(const recipe_ordinal r) { + map > metadata; + for (long long int i = 0; i < SIZE(Recipe[r].steps); ++i) { + instruction& inst = Recipe[r].steps.at(i); + switch (inst.operation) { + // Primitive Recipe Type Checks + case COPY: { + if (SIZE(inst.products) != SIZE(inst.ingredients)) { + raise << "ingredients and products should match in '" << inst.to_string() << "'\n" << end(); + break; + } + for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { + if (!is_mu_array(inst.ingredients.at(i)) && is_mu_array(inst.products.at(i))) { + raise << Recipe[r].name << ": can't copy " << inst.ingredients.at(i).original_string << " to array " << inst.products.at(i).original_string << "\n" << end(); + goto finish_checking_instruction; + } + if (is_mu_array(inst.ingredients.at(i)) && !is_mu_array(inst.products.at(i))) { + raise << Recipe[r].name << ": can't copy array " << inst.ingredients.at(i).original_string << " to " << inst.products.at(i).original_string << "\n" << end(); + goto finish_checking_instruction; + } + } + break; + } + // End Primitive Recipe Type Checks + default: { + // Defined Recipe Type Checks + // End Defined Recipe Type Checks + } + } + finish_checking_instruction:; + } +} + +:(scenario copy_checks_reagent_count) +% Hide_warnings = true; +recipe main [ + 1:number <- copy 34, 35 +] ++warn: ingredients and products should match in '1:number <- copy 34, 35' + +:(scenario write_scalar_to_array_disallowed) +% Hide_warnings = true; +recipe main [ + 1:array:number <- copy 34 +] ++warn: main: can't copy 34 to array 1:array:number + +:(scenario write_scalar_to_array_disallowed_2) +% Hide_warnings = true; +recipe main [ + 1:number, 2:array:number <- copy 34, 35 +] ++warn: main: can't copy 35 to array 2:array:number -- cgit 1.4.1-2-gfad0