1
2
3
4
5
6
7
8
9 :(scenario transform_fails_on_reusing_name_with_different_type)
10 % Hide_errors = true;
11 def main [
12 x:num <- copy 1
13 x:bool <- copy 1
14 ]
15 +error: main: 'x' used with multiple types
16
17 :(after "Transform.push_back(expand_type_abbreviations)")
18 Transform.push_back(check_or_set_types_by_name);
19
20 :(code)
21 void check_or_set_types_by_name(const recipe_ordinal r) {
22 trace(9991, "transform") << "--- deduce types for recipe " << get(Recipe, r).name << end();
23 recipe& caller = get(Recipe, r);
24 set<reagent> known;
25 for (int i = 0; i < SIZE(caller.steps); ++i) {
26 instruction& inst = caller.steps.at(i);
27 for (int in = 0; in < SIZE(inst.ingredients); ++in) {
28 deduce_missing_type(known, inst.ingredients.at(in), caller);
29 check_type(known, inst.ingredients.at(in), caller);
30 }
31 for (int out = 0; out < SIZE(inst.products); ++out) {
32 deduce_missing_type(known, inst.products.at(out), caller);
33 check_type(known, inst.products.at(out), caller);
34 }
35 }
36 }
37
38 void deduce_missing_type(set<reagent>& known, reagent& x, const recipe& caller) {
39
40 if (x.type) return;
41 if (is_jump_target(x.name)) {
42 x.type = new type_tree("label");
43 return;
44 }
45 if (known.find(x) == known.end()) return;
46 const reagent& exemplar = *known.find(x);
47 x.type = new type_tree(*exemplar.type);
48 trace(9992, "transform") << x.name << " <= " << names_to_string(x.type) << end();
49
50 if (is_mu_space(x) && !has_property(x, "names")) {
51 if (!has_property(exemplar, "names")) {
52 raise << maybe(caller.name) << "missing /names property for space variable '" << exemplar.name << "'\n" << end();
53 return;
54 }
55 x.properties.push_back(pair<string, string_tree*>("names", new string_tree(*property(exemplar, "names"))));
56 }
57 }
58
59 void check_type(set<reagent>& known, const reagent& x, const recipe& caller) {
60 if (is_literal(x)) return;
61 if (is_integer(x.name)) return;
62 if (!x.type) return;
63 if (is_jump_target(x.name)) {
64 if (!x.type->atom || x.type->name != "label")
65 raise << maybe(caller.name) << "non-label '" << x.name << "' must begin with a letter\n" << end();
66 return;
67 }
68 if (known.find(x) == known.end()) {
69 trace(9992, "transform") << x.name << " => " << names_to_string(x.type) << end();
70 known.insert(x);
71 }
72 if (!types_strictly_match(known.find(x)->type, x.type)) {
73 raise << maybe(caller.name) << "'" << x.name << "' used with multiple types\n" << end();
74 return;
75 }
76 if (is_mu_array(x)) {
77 if (!x.type->right) {
78 raise << maybe(caller.name) << "'" << x.name << ": can't be just an array. What is it an array of?\n" << end();
79 return;
80 }
81 if (!x.type->right->right) {
82 raise << caller.name << " can't determine the size of array variable '" << x.name << "'. Either allocate it separately and make the type of '" << x.name << "' an address, or specify the length of the array in the type of '" << x.name << "'.\n" << end();
83 return;
84 }
85 }
86 }
87
88 :(scenario transform_fills_in_missing_types)
89 def main [
90 x:num <- copy 1
91 y:num <- add x, 1
92 ]
93
94 +mem: storing 2 in location 2
95
96 :(scenario transform_fills_in_missing_types_in_product)
97 def main [
98 x:num <- copy 1
99 x <- copy 2
100 ]
101
102 +mem: storing 2 in location 1
103
104 :(scenario transform_fills_in_missing_types_in_product_and_ingredient)
105 def main [
106 x:num <- copy 1
107 x <- add x, 1
108 ]
109
110 +mem: storing 2 in location 1
111
112 :(scenario transform_fills_in_missing_label_type)
113 def main [
114 jump +target
115 1:num <- copy 0
116 +target
117 ]
118 -mem: storing 0 in location 1
119
120 :(scenario transform_fails_on_missing_types_in_first_mention)
121 % Hide_errors = true;
122 def main [
123 x <- copy 1
124 x:num <- copy 2
125 ]
126 +error: main: missing type for 'x' in 'x <- copy 1'
127
128 :(scenario transform_fails_on_wrong_type_for_label)
129 % Hide_errors = true;
130 def main [
131 +foo:num <- copy 34
132 ]
133 +error: main: non-label '+foo' must begin with a letter
134
135 :(scenario typo_in_address_type_fails)
136 % Hide_errors = true;
137 def main [
138 y:&:charcter <- new character:type
139 *y <- copy 67
140 ]
141 +error: main: unknown type charcter in 'y:&:charcter <- new character:type'
142
143 :(scenario array_type_without_size_fails)
144 % Hide_errors = true;
145 def main [
146 x:@:num <- merge 2, 12, 13
147 ]
148 +error: main can't determine the size of array variable 'x'. Either allocate it separately and make the type of 'x' an address, or specify the length of the array in the type of 'x'.
149
150 :(scenarios transform)
151 :(scenario transform_checks_types_of_identical_reagents_in_multiple_spaces)
152 def foo [
153 ]
154 def main [
155 local-scope
156 0:space/names:foo <- copy 0
157 x:bool <- copy 1/true
158 x:num/space:1 <- copy 34
159 x/space:1 <- copy 35
160 ]
161 $error: 0
162
163 :(scenario transform_handles_empty_reagents)
164 % Hide_errors = true;
165 def main [
166 add *
167 ]
168 +error: illegal name '*'
169