diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-01-18 13:27:53 -0800 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-01-18 14:32:29 -0800 |
commit | 60448ff155897a514929ae961409f1d25b163cd2 (patch) | |
tree | b8c6d272ea1f572166f996f552c9052a82a7d113 | |
parent | 4c2229fb2d1f762afcbdd41d62b7f0ee9df6a60f (diff) | |
download | mu-60448ff155897a514929ae961409f1d25b163cd2.tar.gz |
2565 - typecheck 'call' on literal recipes
-rw-r--r-- | 061recipe.cc | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/061recipe.cc b/061recipe.cc index 56ccc8d1..6f6163ca 100644 --- a/061recipe.cc +++ b/061recipe.cc @@ -70,7 +70,55 @@ case CALL: { continue; } +//:: check types for 'call' instructions + +:(scenario call_check_literal_recipe) +% Hide_errors = true; +recipe main [ + 1:number <- call f, 34 +] +recipe f x:boolean -> y:boolean [ + local-scope + load-ingredients + y <- copy x +] ++error: main: ingredient 0 has the wrong type at '1:number <- call f, 34' ++error: main: product 0 has the wrong type at '1:number <- call f, 34' + +:(after "Transform.push_back(check_instruction)") +Transform.push_back(check_indirect_calls_against_header); // idempotent :(code) +void check_indirect_calls_against_header(const recipe_ordinal r) { + trace(9991, "transform") << "--- type-check 'call' instructions inside recipe " << get(Recipe, r).name << end(); + const recipe& caller = get(Recipe, r); + for (long long int i = 0; i < SIZE(caller.steps); ++i) { + const instruction& inst = caller.steps.at(i); + if (inst.operation != CALL) continue; + if (inst.ingredients.empty()) continue; // error raised above + const reagent& callee = inst.ingredients.at(0); + if (!is_mu_recipe(callee)) continue; // error raised above + const recipe callee_header = is_literal(callee) ? get(Recipe, callee.value) : from_reagent(inst.ingredients.at(0)); + if (!callee_header.has_header) continue; + for (long int i = /*skip callee*/1; i < min(SIZE(inst.ingredients), SIZE(callee_header.ingredients)+/*skip callee*/1); ++i) { + if (!types_coercible(callee_header.ingredients.at(i-/*skip callee*/1), inst.ingredients.at(i))) + raise_error << maybe(caller.name) << "ingredient " << i-/*skip callee*/1 << " has the wrong type at '" << inst.to_string() << "'\n" << end(); + } + for (long int i = 0; i < min(SIZE(inst.products), SIZE(callee_header.products)); ++i) { + if (is_dummy(inst.products.at(i))) continue; + if (!types_coercible(callee_header.products.at(i), inst.products.at(i))) + raise_error << maybe(caller.name) << "product " << i << " has the wrong type at '" << inst.to_string() << "'\n" << end(); + } + } +} + +recipe from_reagent(const reagent& r) { + assert(r.properties.at(0).second->value == "recipe"); + recipe result_header; // will contain only ingredients and products, nothing else + for (const string_tree* curr = r.properties.at(0).second->right; curr; curr=curr->right) { + } + return result_header; +} + bool is_mu_recipe(reagent r) { if (!r.type) return false; if (r.properties.at(0).second->value == "recipe") return true; |