From c6b3b04ac85f05065fef9626270d914dc4428484 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Tue, 29 Sep 2015 22:26:40 -0700 Subject: 2217 --- 020_check_type_by_instruction.cc | 97 ---------------------------------------- 020check_type_by_instruction.cc | 97 ++++++++++++++++++++++++++++++++++++++++ 048_check_type_by_name.cc | 91 ------------------------------------- 048check_type_by_name.cc | 91 +++++++++++++++++++++++++++++++++++++ 4 files changed, 188 insertions(+), 188 deletions(-) delete mode 100644 020_check_type_by_instruction.cc create mode 100644 020check_type_by_instruction.cc delete mode 100644 048_check_type_by_name.cc create mode 100644 048check_type_by_name.cc diff --git a/020_check_type_by_instruction.cc b/020_check_type_by_instruction.cc deleted file mode 100644 index d1eb9694..00000000 --- a/020_check_type_by_instruction.cc +++ /dev/null @@ -1,97 +0,0 @@ - - -:(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 - -:(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); -} - -bool is_literal(const reagent& r) { - return SIZE(r.types) == 1 && r.types.at(0) == 0; -} - -// helper for tests -void run(string form) { - vector tmp = load(form); - transform_all(); -} diff --git a/020check_type_by_instruction.cc b/020check_type_by_instruction.cc new file mode 100644 index 00000000..d1eb9694 --- /dev/null +++ b/020check_type_by_instruction.cc @@ -0,0 +1,97 @@ + + +:(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 + +:(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); +} + +bool is_literal(const reagent& r) { + return SIZE(r.types) == 1 && r.types.at(0) == 0; +} + +// helper for tests +void run(string form) { + vector tmp = load(form); + transform_all(); +} diff --git a/048_check_type_by_name.cc b/048_check_type_by_name.cc deleted file mode 100644 index 8510d02c..00000000 --- a/048_check_type_by_name.cc +++ /dev/null @@ -1,91 +0,0 @@ -//: Some simple sanity checks for types, and also attempts to guess them where -//: they aren't provided. -//: -//: You still have to provide the full type the first time you mention a -//: variable in a recipe. You have to explicitly name :offset and :variant -//: every single time. You can't use the same name with multiple types in a -//: single recipe. - -:(scenario transform_warns_on_reusing_name_with_different_type) -% Hide_warnings = true; -recipe main [ - x:number <- copy 1 - x:boolean <- copy 1 -] -+warn: x used with multiple types in main - -:(after "int main") - Transform.push_back(check_types_by_name); - -:(code) -void check_types_by_name(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); - for (long long int in = 0; in < SIZE(inst.ingredients); ++in) { - deduce_missing_type(metadata, inst.ingredients.at(in)); - check_metadata(metadata, inst.ingredients.at(in), r); - } - for (long long int out = 0; out < SIZE(inst.products); ++out) { - deduce_missing_type(metadata, inst.products.at(out)); - check_metadata(metadata, inst.products.at(out), r); - } - } -} - -void check_metadata(map >& metadata, const reagent& x, const recipe_ordinal r) { - if (is_literal(x)) return; - if (is_raw(x)) return; - // if you use raw locations you're probably doing something unsafe - if (is_integer(x.name)) return; - if (x.types.empty()) return; // will throw a more precise warning elsewhere - if (metadata.find(x.name) == metadata.end()) - metadata[x.name] = x.types; - if (metadata[x.name] != x.types) - raise << x.name << " used with multiple types in " << Recipe[r].name << '\n' << end(); -} - -:(scenario transform_fills_in_missing_types) -recipe main [ - x:number <- copy 1 - y:number <- add x, 1 -] - -:(code) -void deduce_missing_type(map >& metadata, reagent& x) { - if (!x.types.empty()) return; - if (metadata.find(x.name) == metadata.end()) return; - copy(metadata[x.name].begin(), metadata[x.name].end(), inserter(x.types, x.types.begin())); - assert(x.properties.at(0).second.empty()); - x.properties.at(0).second.resize(metadata[x.name].size()); - x.properties.push_back(pair >("as-before", vector())); -} - -:(scenario transform_fills_in_missing_types_in_product) -recipe main [ - x:number <- copy 1 - x <- copy 2 -] - -:(scenario transform_fills_in_missing_types_in_product_and_ingredient) -recipe main [ - x:number <- copy 1 - x <- add x, 1 -] -+mem: storing 2 in location 1 - -:(scenario transform_warns_on_missing_types_in_first_mention) -% Hide_warnings = true; -recipe main [ - x <- copy 1 - x:number <- copy 2 -] -+warn: missing type in 'x <- copy 1' - -:(scenario typo_in_address_type_warns) -% Hide_warnings = true; -recipe main [ - y:address:charcter <- new character:type - *y <- copy 67 -] -+warn: unknown type: charcter diff --git a/048check_type_by_name.cc b/048check_type_by_name.cc new file mode 100644 index 00000000..8510d02c --- /dev/null +++ b/048check_type_by_name.cc @@ -0,0 +1,91 @@ +//: Some simple sanity checks for types, and also attempts to guess them where +//: they aren't provided. +//: +//: You still have to provide the full type the first time you mention a +//: variable in a recipe. You have to explicitly name :offset and :variant +//: every single time. You can't use the same name with multiple types in a +//: single recipe. + +:(scenario transform_warns_on_reusing_name_with_different_type) +% Hide_warnings = true; +recipe main [ + x:number <- copy 1 + x:boolean <- copy 1 +] ++warn: x used with multiple types in main + +:(after "int main") + Transform.push_back(check_types_by_name); + +:(code) +void check_types_by_name(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); + for (long long int in = 0; in < SIZE(inst.ingredients); ++in) { + deduce_missing_type(metadata, inst.ingredients.at(in)); + check_metadata(metadata, inst.ingredients.at(in), r); + } + for (long long int out = 0; out < SIZE(inst.products); ++out) { + deduce_missing_type(metadata, inst.products.at(out)); + check_metadata(metadata, inst.products.at(out), r); + } + } +} + +void check_metadata(map >& metadata, const reagent& x, const recipe_ordinal r) { + if (is_literal(x)) return; + if (is_raw(x)) return; + // if you use raw locations you're probably doing something unsafe + if (is_integer(x.name)) return; + if (x.types.empty()) return; // will throw a more precise warning elsewhere + if (metadata.find(x.name) == metadata.end()) + metadata[x.name] = x.types; + if (metadata[x.name] != x.types) + raise << x.name << " used with multiple types in " << Recipe[r].name << '\n' << end(); +} + +:(scenario transform_fills_in_missing_types) +recipe main [ + x:number <- copy 1 + y:number <- add x, 1 +] + +:(code) +void deduce_missing_type(map >& metadata, reagent& x) { + if (!x.types.empty()) return; + if (metadata.find(x.name) == metadata.end()) return; + copy(metadata[x.name].begin(), metadata[x.name].end(), inserter(x.types, x.types.begin())); + assert(x.properties.at(0).second.empty()); + x.properties.at(0).second.resize(metadata[x.name].size()); + x.properties.push_back(pair >("as-before", vector())); +} + +:(scenario transform_fills_in_missing_types_in_product) +recipe main [ + x:number <- copy 1 + x <- copy 2 +] + +:(scenario transform_fills_in_missing_types_in_product_and_ingredient) +recipe main [ + x:number <- copy 1 + x <- add x, 1 +] ++mem: storing 2 in location 1 + +:(scenario transform_warns_on_missing_types_in_first_mention) +% Hide_warnings = true; +recipe main [ + x <- copy 1 + x:number <- copy 2 +] ++warn: missing type in 'x <- copy 1' + +:(scenario typo_in_address_type_warns) +% Hide_warnings = true; +recipe main [ + y:address:charcter <- new character:type + *y <- copy 67 +] ++warn: unknown type: charcter -- cgit 1.4.1-2-gfad0