1
2
3
4
5
6
7 :(before "End Globals")
8 vector<type_tree*> Real_hardware_types;
9 :(before "Begin transform_all")
10 setup_real_hardware_types();
11 :(before "End transform_all")
12 teardown_real_hardware_types();
13 :(code)
14 void setup_real_hardware_types() {
15 Real_hardware_types.push_back(parse_type("address:screen"));
16 Real_hardware_types.push_back(parse_type("address:console"));
17 Real_hardware_types.push_back(parse_type("address:resources"));
18 }
19 type_tree* parse_type(string s) {
20 reagent x("x:"+s);
21 type_tree* result = x.type;
22 x.type = NULL;
23 return result;
24 }
25 void teardown_real_hardware_types() {
26 for (int i = 0; i < SIZE(Real_hardware_types); ++i)
27 delete Real_hardware_types.at(i);
28 Real_hardware_types.clear();
29 }
30
31 :(before "End Checks")
32 Transform.push_back(check_for_misuse_of_real_hardware);
33 :(code)
34 void check_for_misuse_of_real_hardware(const recipe_ordinal r) {
35 const recipe& caller = get(Recipe, r);
36 if (caller.name == "main") return;
37 if (starts_with(caller.name, "scenario_")) return;
38 trace(9991, "transform") << "--- check if recipe " << caller.name << " has any dependency-injection mistakes" << end();
39 for (int index = 0; index < SIZE(caller.steps); ++index) {
40 const instruction& inst = caller.steps.at(index);
41 if (is_primitive(inst.operation)) continue;
42 for (int i = 0; i < SIZE(inst.ingredients); ++i) {
43 const reagent& ing = inst.ingredients.at(i);
44 if (!is_literal(ing) || ing.name != "0") continue;
45 const recipe& callee = get(Recipe, inst.operation);
46 if (!callee.has_header) continue;
47 if (i >= SIZE(callee.ingredients)) continue;
48 const reagent& expected_ing = callee.ingredients.at(i);
49 for (int j = 0; j < SIZE(Real_hardware_types); ++j) {
50 if (*Real_hardware_types.at(j) == *expected_ing.type)
51 raise << maybe(caller.name) << "'" << to_original_string(inst) << "': only 'main' can pass 0 into a " << to_string(expected_ing.type) << '\n' << end();
52 }
53 }
54 }
55 }
56
57 :(scenarios transform)
58 :(scenario warn_on_using_real_screen_directly_in_non_main_recipe)
59 % Hide_errors = true;
60 def foo [
61 print 0, 34
62 ]
63 +error: foo: 'print 0, 34': only 'main' can pass 0 into a (address screen)