https://github.com/akkartik/mu/blob/master/043space.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 :(before "End Mu Types Initialization")
17 put(Type_abbreviations, "space", new_type_tree("address:array:location"));
18
19 :(scenario set_default_space)
20 def main [
21
22 10:num/alloc-id, 11:num <- copy 0, 1000
23
24 1000:num <- copy 0
25 1001:num <- copy 5
26
27 default-space:space <- copy 10:&:@:location
28
29
30
31
32
33
34 2:num <- copy 93
35 ]
36 +mem: storing 93 in location 1004
37
38 :(scenario lookup_sidesteps_default_space)
39 def main [
40
41 10:num/alloc-id, 11:num <- copy 0, 1000
42
43 1000:num <- copy 0
44 1001:num <- copy 5
45
46 2000:num/alloc-id, 2001:num <- copy 0, 34
47
48 default-space:space <- copy 10:&:@:location
49
50 2:num, 3:num <- copy 0, 2000
51 20:num/raw <- copy *2:&:num
52 ]
53 +mem: storing 2000 in location 1005
54 +mem: storing 34 in location 20
55
56
57
58 :(scenarios transform)
59 :(scenario convert_names_passes_default_space)
60 % Hide_errors = true;
61 def main [
62 default-space:num <- copy 0
63 x:num <- copy 1
64 ]
65 +name: assign x 2
66 -name: assign default-space 1
67 -name: assign default-space 2
68 :(scenarios run)
69
70 :(before "End is_disqualified Special-cases")
71 if (x.name == "default-space")
72 x.initialized = true;
73 :(before "End is_special_name Special-cases")
74 if (s == "default-space") return true;
75
76
77
78 :(before "End call Fields")
79 int default_space;
80 :(before "End call Constructor")
81 default_space = 0;
82
83 :(before "Begin canonize(x) Lookups")
84 absolutize(x);
85 :(code)
86 void absolutize(reagent& x) {
87 if (is_raw(x) || is_dummy(x)) return;
88 if (x.name == "default-space") return;
89 if (!x.initialized)
90 raise << to_original_string(current_instruction()) << ": reagent not initialized: '" << x.original_string << "'\n" << end();
91 x.set_value(address(x.value, space_base(x)));
92 x.properties.push_back(pair<string, string_tree*>("raw", NULL));
93 assert(is_raw(x));
94 }
95
96
97 int space_base(const reagent& x) {
98 return current_call().default_space ? (current_call().default_space + 1) : 0;
99 }
100
101 int address(int offset, int base) {
102 assert(offset >= 0);
103 if (base == 0) return offset;
104 int size = get_or_insert(Memory, base);
105 if (offset >= size) {
106
107 raise << current_recipe_name() << ": location " << offset << " is out of bounds " << size << " at " << base << '\n' << end();
108 DUMP("");
109 exit(1);
110 return 0;
111 }
112 return base + 1 + offset;
113 }
114
115
116
117 :(after "Begin Preprocess write_memory(x, data)")
118 if (x.name == "default-space") {
119 if (!is_mu_space(x))
120 raise << maybe(current_recipe_name()) << "'default-space' should be of type address:array:location, but is " << to_string(x.type) << '\n' << end();
121 if (SIZE(data) != 2)
122 raise << maybe(current_recipe_name()) << "'default-space' getting data from non-address\n" << end();
123 current_call().default_space = data.at(1);
124 return;
125 }
126 :(code)
127 bool is_mu_space(reagent x) {
128 canonize_type(x);
129 if (!is_compound_type_starting_with(x.type, "address")) return false;
130 drop_from_type(x, "address");
131 if (!is_compound_type_starting_with(x.type, "array")) return false;
132 drop_from_type(x, "array");
133 return x.type && x.type->atom && x.type->name == "location";
134 }
135
136 :(scenario get_default_space)
137 def main [
138
139 10:num/alloc-id, 11:num <- copy 0, 1000
140
141 1000:num <- copy 0
142 1001:num <- copy 5
143
144 default-space:space <- copy 10:space
145 2:space/raw <- copy default-space:space
146 ]
147 +mem: storing 1000 in location 3
148
149 :(after "Begin Preprocess read_memory(x)")
150 if (x.name == "default-space") {
151 vector<double> result;
152 result.push_back(0);
153 result.push_back(current_call().default_space);
154 return result;
155 }
156
157
158
159 :(scenario lookup_sidesteps_default_space_in_get)
160 def main [
161
162 10:num/alloc-id, 11:num <- copy 0, 1000
163
164 1000:num <- copy 0
165 1001:num <- copy 5
166
167 2000:num/alloc-id, 2001:num/x, 2002:num/y <- copy 0, 34, 35
168
169 default-space:space <- copy 10:space
170
171 2:num, 3:num <- copy 0, 2000
172 3000:num/raw <- get *2:&:point, 1:offset
173 ]
174 +mem: storing 35 in location 3000
175
176 :(before "Read element" following "case GET:")
177 element.properties.push_back(pair<string, string_tree*>("raw", NULL));
178
179
180
181 :(scenario lookup_sidesteps_default_space_in_index)
182 def main [
183
184 10:num/alloc-id, 11:num <- copy 0, 1000
185
186 1000:num <- copy 0
187 1001:num <- copy 5
188
189 20:num/alloc-id, 21:num <- copy 0, 2000
190
191 2000:num/alloc-id, 2001:num/length, 2002:num/index:0, 2003:num/index:1 <- copy 0, 2, 34, 35
192
193 default-space:space <- copy 10:&:@:location
194 1:&:@:num <- copy 20:&:@:num/raw
195 3000:num/raw <- index *1:&:@:num, 1
196 ]
197 +mem: storing 35 in location 3000
198
199 :(before "Read element" following "case INDEX:")
200 element.properties.push_back(pair<string, string_tree*>("raw", NULL));
201
202
203
204
205 :(scenario local_scope)
206 def main [
207 local-scope
208 x:num <- copy 0
209 y:num <- copy 3
210 ]
211
212 +mem: array length is 4
213
214 :(before "End is_disqualified Special-cases")
215 if (x.name == "number-of-locals")
216 x.initialized = true;
217 :(before "End is_special_name Special-cases")
218 if (s == "number-of-locals") return true;
219
220 :(before "End Rewrite Instruction(curr, recipe result)")
221
222
223
224
225
226 if (curr.name == "local-scope") {
227 rewrite_default_space_instruction(curr);
228 }
229 :(code)
230 void rewrite_default_space_instruction(instruction& curr) {
231 if (!curr.ingredients.empty())
232 raise << "'" << to_original_string(curr) << "' can't take any ingredients\n" << end();
233 curr.name = "new";
234 curr.ingredients.push_back(reagent("location:type"));
235 curr.ingredients.push_back(reagent("number-of-locals:literal"));
236 if (!curr.products.empty())
237 raise << "local-scope can't take any results\n" << end();
238 curr.products.push_back(reagent("default-space:space"));
239 }
240 :(after "Begin Preprocess read_memory(x)")
241 if (x.name == "number-of-locals") {
242 vector<double> result;
243 result.push_back(Name[get(Recipe_ordinal, current_recipe_name())][""]);
244 if (result.back() == 0)
245 raise << "no space allocated for default-space in recipe " << current_recipe_name() << "; are you using names?\n" << end();
246 return result;
247 }
248 :(after "Begin Preprocess write_memory(x, data)")
249 if (x.name == "number-of-locals") {
250 raise << maybe(current_recipe_name()) << "can't write to special name 'number-of-locals'\n" << end();
251 return;
252 }
253
254
255
256 :(before "End Globals")
257 bool Hide_missing_default_space_errors = true;
258 :(before "End Checks")
259 Transform.push_back(check_default_space);
260 :(code)
261 void check_default_space(const recipe_ordinal r) {
262 if (Hide_missing_default_space_errors) return;
263 const recipe& caller = get(Recipe, r);
264
265
266 if (!contains_non_special_name(r)) return;
267 trace(9991, "transform") << "--- check that recipe " << caller.name << " sets default-space" << end();
268 if (caller.steps.empty()) return;
269 if (!starts_by_setting_default_space(caller))
270 raise << caller.name << " does not seem to start with 'local-scope' or 'default-space'\n" << end();
271 }
272 bool starts_by_setting_default_space(const recipe& r) {
273 return !r.steps.empty()
274 && !r.steps.at(0).products.empty()
275 && r.steps.at(0).products.at(0).name == "default-space";
276 }
277
278 :(after "Load Mu Prelude")
279 Hide_missing_default_space_errors = false;
280 :(after "Test Runs")
281 Hide_missing_default_space_errors = true;
282 :(after "Running Main")
283 Hide_missing_default_space_errors = false;
284
285 :(code)
286 bool contains_non_special_name(const recipe_ordinal r) {
287 for (map<string, int>::iterator p = Name[r].begin(); p != Name[r].end(); ++p) {
288 if (p->first.empty()) continue;
289 if (p->first.find("stash_") == 0) continue;
290 if (!is_special_name(p->first))
291 return true;
292 }
293 return false;
294 }