https://github.com/akkartik/mu/blob/master/025compare.cc
1
2
3 :(before "End Primitive Recipe Declarations")
4 EQUAL,
5 :(before "End Primitive Recipe Numbers")
6 put(Recipe_ordinal, "equal", EQUAL);
7 :(before "End Primitive Recipe Checks")
8 case EQUAL: {
9 if (SIZE(inst.ingredients) <= 1) {
10 raise << maybe(get(Recipe, r).name) << "'equal' needs at least two ingredients to compare in '" << to_original_string(inst) << "'\n" << end();
11 break;
12 }
13 const reagent& exemplar = inst.ingredients.at(0);
14 for (int i = 1; i < SIZE(inst.ingredients); ++i) {
15 if (!types_match(inst.ingredients.at(i), exemplar) && !types_match(exemplar, inst.ingredients.at(i))) {
16 raise << maybe(get(Recipe, r).name) << "'equal' expects ingredients to be all of the same type, but got '" << to_original_string(inst) << "'\n" << end();
17 goto finish_checking_instruction;
18 }
19 }
20 if (SIZE(inst.products) > 1) {
21 raise << maybe(get(Recipe, r).name) << "'equal' yields exactly one product in '" << to_original_string(inst) << "'\n" << end();
22 break;
23 }
24 if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
25 raise << maybe(get(Recipe, r).name) << "'equal' should yield a boolean, but got '" << inst.products.at(0).original_string << "'\n" << end();
26 break;
27 }
28 break;
29 }
30 :(before "End Primitive Recipe Implementations")
31 case EQUAL: {
32 vector<double>& exemplar = ingredients.at(0);
33 bool result = true;
34 for (int i = 1; i < SIZE(ingredients); ++i) {
35 if (SIZE(ingredients.at(i)) != SIZE(exemplar)) {
36 result = false;
37 break;
38 }
39 if (!equal(ingredients.at(i).begin(), ingredients.at(i).end(), exemplar.begin())) {
40 result = false;
41 break;
42 }
43 }
44 products.resize(1);
45 products.at(0).push_back(result);
46 break;
47 }
48
49 :(scenario equal)
50 def main [
51 1:num <- copy 34
52 2:num <- copy 33
53 3:bool <- equal 1:num, 2:num
54 ]
55 +mem: location 1 is 34
56 +mem: location 2 is 33
57 +mem: storing 0 in location 3
58
59 :(scenario equal_2)
60 def main [
61 1:num <- copy 34
62 2:num <- copy 34
63 3:bool <- equal 1:num, 2:num
64 ]
65 +mem: location 1 is 34
66 +mem: location 2 is 34
67 +mem: storing 1 in location 3
68
69 :(scenario equal_multiple)
70 def main [
71 1:bool <- equal 34, 34, 34
72 ]
73 +mem: storing 1 in location 1
74
75 :(scenario equal_multiple_2)
76 def main [
77 1:bool <- equal 34, 34, 35
78 ]
79 +mem: storing 0 in location 1
80
81 :(before "End Primitive Recipe Declarations")
82 NOT_EQUAL,
83 :(before "End Primitive Recipe Numbers")
84 put(Recipe_ordinal, "not-equal", NOT_EQUAL);
85 :(before "End Primitive Recipe Checks")
86 case NOT_EQUAL: {
87 if (SIZE(inst.ingredients) != 2) {
88 raise << maybe(get(Recipe, r).name) << "'equal' needs two ingredients to compare in '" << to_original_string(inst) << "'\n" << end();
89 break;
90 }
91 const reagent& exemplar = inst.ingredients.at(0);
92 if (!types_match(inst.ingredients.at(1), exemplar) && !types_match(exemplar, inst.ingredients.at(1))) {
93 raise << maybe(get(Recipe, r).name) << "'equal' expects ingredients to be all of the same type, but got '" << to_original_string(inst) << "'\n" << end();
94 goto finish_checking_instruction;
95 }
96 if (SIZE(inst.products) > 1) {
97 raise << maybe(get(Recipe, r).name) << "'equal' yields exactly one product in '" << to_original_string(inst) << "'\n" << end();
98 break;
99 }
100 if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
101 raise << maybe(get(Recipe, r).name) << "'equal' should yield a boolean, but got '" << inst.products.at(0).original_string << "'\n" << end();
102 break;
103 }
104 break;
105 }
106 :(before "End Primitive Recipe Implementations")
107 case NOT_EQUAL: {
108 vector<double>& exemplar = ingredients.at(0);
109 products.resize(1);
110 if (SIZE(ingredients.at(1)) != SIZE(exemplar)) {
111 products.at(0).push_back(true);
112 break;
113 }
114 bool equal_ingredients = equal(ingredients.at(1).begin(), ingredients.at(1).end(), exemplar.begin());
115 products.at(0).push_back(!equal_ingredients);
116 break;
117 }
118
119 :(scenario not_equal)
120 def main [
121 1:num <- copy 34
122 2:num <- copy 33
123 3:bool <- not-equal 1:num, 2:num
124 ]
125 +mem: location 1 is 34
126 +mem: location 2 is 33
127 +mem: storing 1 in location 3
128
129 :(scenario not_equal_2)
130 def main [
131 1:num <- copy 34
132 2:num <- copy 34
133 3:bool <- not-equal 1:num, 2:num
134 ]
135 +mem: location 1 is 34
136 +mem: location 2 is 34
137 +mem: storing 0 in location 3
138
139 :(before "End Primitive Recipe Declarations")
140 GREATER_THAN,
141 :(before "End Primitive Recipe Numbers")
142 put(Recipe_ordinal, "greater-than", GREATER_THAN);
143 :(before "End Primitive Recipe Checks")
144 case GREATER_THAN: {
145 if (SIZE(inst.ingredients) <= 1) {
146 raise << maybe(get(Recipe, r).name) << "'greater-than' needs at least two ingredients to compare in '" << to_original_string(inst) << "'\n" << end();
147 break;
148 }
149 for (int i = 0; i < SIZE(inst.ingredients); ++i) {
150 if (!is_mu_number(inst.ingredients.at(i))) {
151 raise << maybe(get(Recipe, r).name) << "'greater-than' can only compare numbers; got '" << inst.ingredients.at(i).original_string << "'\n" << end();
152 goto finish_checking_instruction;
153 }
154 }
155 if (SIZE(inst.products) > 1) {
156 raise << maybe(get(Recipe, r).name) << "'greater-than' yields exactly one product in '" << to_original_string(inst) << "'\n" << end();
157 break;
158 }
159 if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
160 raise << maybe(get(Recipe, r).name) << "'greater-than' should yield a boolean, but got '" << inst.products.at(0).original_string << "'\n" << end();
161 break;
162 }
163 break;
164 }
165 :(before "End Primitive Recipe Implementations")
166 case GREATER_THAN: {
167 bool result = true;
168 for (int i = 1; i < SIZE(ingredients); ++i) {
169 if (ingredients.at(i-1).at(0) <= ingredients.at(i).at(0)) {
170 result = false;
171 }
172 }
173 products.resize(1);
174 products.at(0).push_back(result);
175 break;
176 }
177
178 :(scenario greater_than)
179 def main [
180 1:num <- copy 34
181 2:num <- copy 33
182 3:bool <- greater-than 1:num, 2:num
183 ]
184 +mem: storing 1 in location 3
185
186 :(scenario greater_than_2)
187 def main [
188 1:num <- copy 34
189 2:num <- copy 34
190 3:bool <- greater-than 1:num, 2:num
191 ]
192 +mem: storing 0 in location 3
193
194 :(scenario greater_than_multiple)
195 def main [
196 1:bool <- greater-than 36, 35, 34
197 ]
198 +mem: storing 1 in location 1
199
200 :(scenario greater_than_multiple_2)
201 def main [
202 1:bool <- greater-than 36, 35, 35
203 ]
204 +mem: storing 0 in location 1
205
206 :(before "End Primitive Recipe Declarations")
207 LESSER_THAN,
208 :(before "End Primitive Recipe Numbers")
209 put(Recipe_ordinal, "lesser-than", LESSER_THAN);
210 :(before "End Primitive Recipe Checks")
211 case LESSER_THAN: {
212 if (SIZE(inst.ingredients) <= 1) {
213 raise << maybe(get(Recipe, r).name) << "'lesser-than' needs at least two ingredients to compare in '" << to_original_string(inst) << "'\n" << end();
214 break;
215 }
216 for (int i = 0; i < SIZE(inst.ingredients); ++i) {
217 if (!is_mu_number(inst.ingredients.at(i))) {
218 raise << maybe(get(Recipe, r).name) << "'lesser-than' can only compare numbers; got '" << inst.ingredients.at(i).original_string << "'\n" << end();
219 goto finish_checking_instruction;
220 }
221 }
222 if (SIZE(inst.products) > 1) {
223 raise << maybe(get(Recipe, r).name) << "'lesser-than' yields exactly one product in '" << to_original_string(inst) << "'\n" << end();
224 break;
225 }
226 if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
227 raise << maybe(get(Recipe, r).name) << "'lesser-than' should yield a boolean, but got '" << inst.products.at(0).original_string << "'\n" << end();
228 break;
229 }
230 break;
231 }
232 :(before "End Primitive Recipe Implementations")
233 case LESSER_THAN: {
234 bool result = true;
235 for (int i = 1; i < SIZE(ingredients); ++i) {
236 if (ingredients.at(i-1).at(0) >= ingredients.at(i).at(0)) {
237 result = false;
238 }
239 }
240 products.resize(1);
241 products.at(0).push_back(result);
242 break;
243 }
244
245 :(scenario lesser_than)
246 def main [
247 1:num <- copy 32
248 2:num <- copy 33
249 3:bool <- lesser-than 1:num, 2:num
250 ]
251 +mem: storing 1 in location 3
252
253 :(scenario lesser_than_2)
254 def main [
255 1:num <- copy 34
256 2:num <- copy 33
257 3:bool <- lesser-than 1:num, 2:num
258 ]
259 +mem: storing 0 in location 3
260
261 :(scenario lesser_than_multiple)
262 def main [
263 1:bool <- lesser-than 34, 35, 36
264 ]
265 +mem: storing 1 in location 1
266
267 :(scenario lesser_than_multiple_2)
268 def main [
269 1:bool <- lesser-than 34, 35, 35
270 ]
271 +mem: storing 0 in location 1
272
273 :(before "End Primitive Recipe Declarations")
274 GREATER_OR_EQUAL,
275 :(before "End Primitive Recipe Numbers")
276 put(Recipe_ordinal, "greater-or-equal", GREATER_OR_EQUAL);
277 :(before "End Primitive Recipe Checks")
278 case GREATER_OR_EQUAL: {
279 if (SIZE(inst.ingredients) <= 1) {
280 raise << maybe(get(Recipe, r).name) << "'greater-or-equal' needs at least two ingredients to compare in '" << to_original_string(inst) << "'\n" << end();
281 break;
282 }
283 for (int i = 0; i < SIZE(inst.ingredients); ++i) {
284 if (!is_mu_number(inst.ingredients.at(i))) {
285 raise << maybe(get(Recipe, r).name) << "'greater-or-equal' can only compare numbers; got '" << inst.ingredients.at(i).original_string << "'\n" << end();
286 goto finish_checking_instruction;
287 }
288 }
289 if (SIZE(inst.products) > 1) {
290 raise << maybe(get(Recipe, r).name) << "'greater-or-equal' yields exactly one product in '" << to_original_string(inst) << "'\n" << end();
291 break;
292 }
293 if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
294 raise << maybe(get(Recipe, r).name) << "'greater-or-equal' should yield a boolean, but got '" << inst.products.at(0).original_string << "'\n" << end();
295 break;
296 }
297 break;
298 }
299 :(before "End Primitive Recipe Implementations")
300 case GREATER_OR_EQUAL: {
301 bool result = true;
302 for (int i = 1; i < SIZE(ingredients); ++i) {
303 if (ingredients.at(i-1).at(0) < ingredients.at(i).at(0)) {
304 result = false;
305 }
306 }
307 products.resize(1);
308 products.at(0).push_back(result);
309 break;
310 }
311
312 :(scenario greater_or_equal)
313 def main [
314 1:num <- copy 34
315 2:num <- copy 33
316 3:bool <- greater-or-equal 1:num, 2:num
317 ]
318 +mem: storing 1 in location 3
319
320 :(scenario greater_or_equal_2)
321 def main [
322 1:num <- copy 34
323 2:num <- copy 34
324 3:bool <- greater-or-equal 1:num, 2:num
325 ]
326 +mem: storing 1 in location 3
327
328 :(scenario greater_or_equal_3)
329 def main [
330 1:num <- copy 34
331 2:num <- copy 35
332 3:bool <- greater-or-equal 1:num, 2:num
333 ]
334 +mem: storing 0 in location 3
335
336 :(scenario greater_or_equal_multiple)
337 def main [
338 1:bool <- greater-or-equal 36, 35, 35
339 ]
340 +mem: storing 1 in location 1
341
342 :(scenario greater_or_equal_multiple_2)
343 def main [
344 1:bool <- greater-or-equal 36, 35, 36
345 ]
346 +mem: storing 0 in location 1
347
348 :(before "End Primitive Recipe Declarations")
349 LESSER_OR_EQUAL,
350 :(before "End Primitive Recipe Numbers")
351 put(Recipe_ordinal, "lesser-or-equal", LESSER_OR_EQUAL);
352 :(before "End Primitive Recipe Checks")
353 case LESSER_OR_EQUAL: {
354 if (SIZE(inst.ingredients) <= 1) {
355 raise << maybe(get(Recipe, r).name) << "'lesser-or-equal' needs at least two ingredients to compare in '" << to_original_string(inst) << "'\n" << end();
356 break;
357 }
358 for (int i = 0; i < SIZE(inst.ingredients); ++i) {
359 if (!is_mu_number(inst.ingredients.at(i))) {
360 raise << maybe(get(Recipe, r).name) << "'lesser-or-equal' can only compare numbers; got '" << inst.ingredients.at(i).original_string << "'\n" << end();
361 goto finish_checking_instruction;
362 }
363 }
364 if (SIZE(inst.products) > 1) {
365 raise << maybe(get(Recipe, r).name) << "'greater-or-equal' yields exactly one product in '" << to_original_string(inst) << "'\n" << end();
366 break;
367 }
368 if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
369 raise << maybe(get(Recipe, r).name) << "'greater-or-equal' should yield a boolean, but got '" << inst.products.at(0).original_string << "'\n" << end();
370 break;
371 }
372 break;
373 }
374 :(before "End Primitive Recipe Implementations")
375 case LESSER_OR_EQUAL: {
376 bool result = true;
377 for (int i = 1; i < SIZE(ingredients); ++i) {
378 if (ingredients.at(i-1).at(0) > ingredients.at(i).at(0)) {
379 result = false;
380 }
381 }
382 products.resize(1);
383 products.at(0).push_back(result);
384 break;
385 }
386
387 :(scenario lesser_or_equal)
388 def main [
389 1:num <- copy 32
390 2:num <- copy 33
391 3:bool <- lesser-or-equal 1:num, 2:num
392 ]
393 +mem: storing 1 in location 3
394
395 :(scenario lesser_or_equal_2)
396 def main [
397 1:num <- copy 33
398 2:num <- copy 33
399 3:bool <- lesser-or-equal 1:num, 2:num
400 ]
401 +mem: storing 1 in location 3
402
403 :(scenario lesser_or_equal_3)
404 def main [
405 1:num <- copy 34
406 2:num <- copy 33
407 3:bool <- lesser-or-equal 1:num, 2:num
408 ]
409 +mem: storing 0 in location 3
410
411 :(scenario lesser_or_equal_multiple)
412 def main [
413 1:bool <- lesser-or-equal 34, 35, 35
414 ]
415 +mem: storing 1 in location 1
416
417 :(scenario lesser_or_equal_multiple_2)
418 def main [
419 1:bool <- lesser-or-equal 34, 35, 34
420 ]
421 +mem: storing 0 in location 1
422
423 :(before "End Primitive Recipe Declarations")
424 MAX,
425 :(before "End Primitive Recipe Numbers")
426 put(Recipe_ordinal, "max", MAX);
427 :(before "End Primitive Recipe Checks")
428 case MAX: {
429 if (SIZE(inst.ingredients) <= 1) {
430 raise << maybe(get(Recipe, r).name) << "'max' needs at least two ingredients to compare in '" << to_original_string(inst) << "'\n" << end();
431 break;
432 }
433 for (int i = 0; i < SIZE(inst.ingredients); ++i) {
434 if (!is_mu_number(inst.ingredients.at(i))) {
435 raise << maybe(get(Recipe, r).name) << "'max' can only compare numbers; got '" << inst.ingredients.at(i).original_string << "'\n" << end();
436 goto finish_checking_instruction;
437 }
438 }
439 if (SIZE(inst.products) > 1) {
440 raise << maybe(get(Recipe, r).name) << "'max' yields exactly one product in '" << to_original_string(inst) << "'\n" << end();
441 break;
442 }
443 if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
444 raise << maybe(get(Recipe, r).name) << "'max' should yield a number, but got '" << inst.products.at(0).original_string << "'\n" << end();
445 break;
446 }
447 break;
448 }
449 :(before "End Primitive Recipe Implementations")
450 case MAX: {
451 int result = ingredients.at(0).at(0);
452 for (int i = 1; i < SIZE(ingredients); ++i) {
453 if (ingredients.at(i).at(0) > result) {
454 result = ingredients.at(i).at(0);
455 }
456 }
457 products.resize(1);
458 products.at(0).push_back(result);
459 break;
460 }
461
462 :(before "End Primitive Recipe Declarations")
463 MIN,
464 :(before "End Primitive Recipe Numbers")
465 put(Recipe_ordinal, "min", MIN);
466 :(before "End Primitive Recipe Checks")
467 case MIN: {
468 if (SIZE(inst.ingredients) <= 1) {
469 raise << maybe(get(Recipe, r).name) << "'min' needs at least two ingredients to compare in '" << to_original_string(inst) << "'\n" << end();
470 break;
471 }
472 for (int i = 0; i < SIZE(inst.ingredients); ++i) {
473 if (!is_mu_number(inst.ingredients.at(i))) {
474 raise << maybe(get(Recipe, r).name) << "'min' can only compare numbers; got '" << inst.ingredients.at(i).original_string << "'\n" << end();
475 goto finish_checking_instruction;
476 }
477 }
478 if (SIZE(inst.products) > 1) {
479 raise << maybe(get(Recipe, r).name) << "'min' yields exactly one product in '" << to_original_string(inst) << "'\n" << end();
480 break;
481 }
482 if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
483 raise << maybe(get(Recipe, r).name) << "'min' should yield a number, but got '" << inst.products.at(0).original_string << "'\n" << end();
484 break;
485 }
486 break;
487 }
488 :(before "End Primitive Recipe Implementations")
489 case MIN: {
490 int result = ingredients.at(0).at(0);
491 for (int i = 1; i < SIZE(ingredients); ++i) {
492 if (ingredients.at(i).at(0) < result) {
493 result = ingredients.at(i).at(0);
494 }
495 }
496 products.resize(1);
497 products.at(0).push_back(result);
498 break;
499 }