diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-10-22 16:04:47 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-10-22 16:04:47 -0700 |
commit | 3b107f1863930433e771a630dfbba095fa1fd6b0 (patch) | |
tree | 6f579d003f3cb4d392d68d8aeac059195b639581 | |
parent | e939023612da044098e649e1e77cacceb73c564d (diff) | |
download | mu-3b107f1863930433e771a630dfbba095fa1fd6b0.tar.gz |
3554 - flag unexpected header for recipe 'main'
As long as Mu operates atop Unix, we need to make these assumptions. Thanks Ella Couch for finding this loophole.
-rw-r--r-- | 053recipe_header.cc | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/053recipe_header.cc b/053recipe_header.cc index a98b4c54..9845b3fa 100644 --- a/053recipe_header.cc +++ b/053recipe_header.cc @@ -521,6 +521,49 @@ def add2 x:num, y:num -> x:num [ ] +error: main: '3:num <- add2 1:num, 2:num' should write to '1:num' rather than '3:num' +//: One special-case is recipe 'main'. Make sure it's only ever taking in text +//: ingredients, and returning a single number. + +:(scenario recipe_header_ingredients_constrained_for_main) +% Hide_errors = true; +def main x:num [ +] ++error: ingredients of recipe 'main' must all be text (address:array:character) + +:(scenario recipe_header_products_constrained_for_main) +% Hide_errors = true; +def main -> x:text [ +] ++error: recipe 'main' must return at most a single product, a number + +:(scenario recipe_header_products_constrained_for_main_2) +% Hide_errors = true; +def main -> x:num, y:num [ +] ++error: recipe 'main' must return at most a single product, a number + +:(after "Transform.push_back(expand_type_abbreviations)") +Transform.push_back(check_recipe_header_constraints); +:(code) +void check_recipe_header_constraints(const recipe_ordinal r) { + const recipe& caller = get(Recipe, r); + if (caller.name != "main") return; + if (!caller.has_header) return; + reagent/*local*/ expected_ingredient("x:address:array:character"); + for (int i = 0; i < SIZE(caller.ingredients); ++i) { + if (!types_strictly_match(expected_ingredient, caller.ingredients.at(i))) { + raise << "ingredients of recipe 'main' must all be text (address:array:character)\n" << end(); + break; + } + } + int nprod = SIZE(caller.products); + reagent/*local*/ expected_product("x:number"); + if (nprod > 1 + || (nprod == 1 && !types_strictly_match(expected_product, caller.products.at(0)))) { + raise << "recipe 'main' must return at most a single product, a number\n" << end(); + } +} + :(before "End Includes") using std::min; using std::max; |