diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2015-09-28 23:36:39 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2015-09-28 23:36:39 -0700 |
commit | bb58e1797e8a813891d2ba8ceabcfb518c6f8050 (patch) | |
tree | 38ac76c87f12339766189621db31ec01017d9539 /020_check_type_by_instruction.cc | |
parent | 86a6c9cd8952b4600f648519a64a86156d1a3e10 (diff) | |
download | mu-bb58e1797e8a813891d2ba8ceabcfb518c6f8050.tar.gz |
2214
Diffstat (limited to '020_check_type_by_instruction.cc')
-rw-r--r-- | 020_check_type_by_instruction.cc | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/020_check_type_by_instruction.cc b/020_check_type_by_instruction.cc new file mode 100644 index 00000000..d1eb9694 --- /dev/null +++ b/020_check_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<string, vector<type_ordinal> > 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<pair<string, vector<string> > >::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<recipe_ordinal> tmp = load(form); + transform_all(); +} |