https://github.com/akkartik/mu/blob/master/023boolean.cc
1
2
3 :(before "End Primitive Recipe Declarations")
4 AND,
5 :(before "End Primitive Recipe Numbers")
6 put(Recipe_ordinal, "and", AND);
7 :(before "End Primitive Recipe Checks")
8 case AND: {
9 for (int i = 0; i < SIZE(inst.ingredients); ++i) {
10 if (!is_mu_scalar(inst.ingredients.at(i))) {
11 raise << maybe(get(Recipe, r).name) << "'and' requires boolean ingredients, but got '" << inst.ingredients.at(i).original_string << "'\n" << end();
12 goto finish_checking_instruction;
13 }
14 }
15 if (SIZE(inst.products) > 1) {
16 raise << maybe(get(Recipe, r).name) << "'and' yields exactly one product in '" << to_original_string(inst) << "'\n" << end();
17 break;
18 }
19 if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
20 raise << maybe(get(Recipe, r).name) << "'and' should yield a boolean, but got '" << inst.products.at(0).original_string << "'\n" << end();
21 break;
22 }
23 break;
24 }
25 :(before "End Primitive Recipe Implementations")
26 case AND: {
27 bool result = true;
28 for (int i = 0; i < SIZE(ingredients); ++i)
29 result = result && scalar_ingredient(ingredients, i);
30 products.resize(1);
31 products.at(0).push_back(result);
32 break;
33 }
34 :(code)
35 double scalar_ingredient(const vector<vector<double> >& ingredients, int i) {
36 if (is_mu_address(current_instruction().ingredients.at(i)))
37 return ingredients.at(i).at(1);
38 return ingredients.at(i).at(0);
39 }
40
41 :(scenario and)
42 def main [
43 1:bool <- copy true
44 2:bool <- copy false
45 3:bool <- and 1:bool, 2:bool
46 ]
47 +mem: storing 0 in location 3
48
49 :(scenario and_2)
50 def main [
51 1:bool <- and true, true
52 ]
53 +mem: storing 1 in location 1
54
55 :(scenario and_multiple)
56 def main [
57 1:bool <- and true, true, false
58 ]
59 +mem: storing 0 in location 1
60
61 :(scenario and_multiple_2)
62 def main [
63 1:bool <- and true, true, true
64 ]
65 +mem: storing 1 in location 1
66
67 :(before "End Primitive Recipe Declarations")
68 OR,
69 :(before "End Primitive Recipe Numbers")
70 put(Recipe_ordinal, "or", OR);
71 :(before "End Primitive Recipe Checks")
72 case OR: {
73 for (int i = 0; i < SIZE(inst.ingredients); ++i) {
74 if (!is_mu_scalar(inst.ingredients.at(i))) {
75 raise << maybe(get(Recipe, r).name) << "'and' requires boolean ingredients, but got '" << inst.ingredients.at(i).original_string << "'\n" << end();
76 goto finish_checking_instruction;
77 }
78 }
79 if (SIZE(inst.products) > 1) {
80 raise << maybe(get(Recipe, r).name) << "'or' yields exactly one product in '" << to_original_string(inst) << "'\n" << end();
81 break;
82 }
83 if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
84 raise << maybe(get(Recipe, r).name) << "'or' should yield a boolean, but got '" << inst.products.at(0).original_string << "'\n" << end();
85 break;
86 }
87 break;
88 }
89 :(before "End Primitive Recipe Implementations")
90 case OR: {
91 bool result = false;
92 for (int i = 0; i < SIZE(ingredients); ++i)
93 result = result || scalar_ingredient(ingredients, i);
94 products.resize(1);
95 products.at(0).push_back(result);
96 break;
97 }
98
99 :(scenario or)
100 def main [
101 1:bool <- copy true
102 2:bool <- copy false
103 3:bool <- or 1:bool, 2:bool
104 ]
105 +mem: storing 1 in location 3
106
107 :(scenario or_2)
108 def main [
109 1:bool <- or false, false
110 ]
111 +mem: storing 0 in location 1
112
113 :(scenario or_multiple)
114 def main [
115 1:bool <- or false, false, false
116 ]
117 +mem: storing 0 in location 1
118
119 :(scenario or_multiple_2)
120 def main [
121 1:bool <- or false, false, true
122 ]
123 +mem: storing 1 in location 1
124
125 :(before "End Primitive Recipe Declarations")
126 NOT,
127 :(before "End Primitive Recipe Numbers")
128 put(Recipe_ordinal, "not", NOT);
129 :(before "End Primitive Recipe Checks")
130 case NOT: {
131 if (SIZE(inst.products) != SIZE(inst.ingredients)) {
132 raise << "ingredients and products should match in '" << to_original_string(inst) << "'\n" << end();
133 break;
134 }
135 for (int i = 0; i < SIZE(inst.ingredients); ++i) {
136 if (!is_mu_scalar(inst.ingredients.at(i)) && !is_mu_address(inst.ingredients.at(i))) {
137 raise << maybe(get(Recipe, r).name) << "'not' requires ingredients that can be interpreted as boolean, but got '" << inst.ingredients.at(i).original_string << "'\n" << end();
138 goto finish_checking_instruction;
139 }
140 }
141 for (int i = 0; i < SIZE(inst.products); ++i) {
142 if (is_dummy(inst.products.at(i))) continue;
143 if (!is_mu_boolean(inst.products.at(i))) {
144 raise << maybe(get(Recipe, r).name) << "'not' should yield a boolean, but got '" << inst.products.at(i).original_string << "'\n" << end();
145 goto finish_checking_instruction;
146 }
147 }
148 break;
149 }
150 :(before "End Primitive Recipe Implementations")
151 case NOT: {
152 products.resize(SIZE(ingredients));
153 for (int i = 0; i < SIZE(ingredients); ++i) {
154 products.at(i).push_back(!scalar_ingredient(ingredients, i));
155 }
156 break;
157 }
158
159 :(scenario not)
160 def main [
161 1:bool <- copy true
162 2:bool <- not 1:bool
163 ]
164 +mem: storing 0 in location 2
165
166 :(scenario not_multiple)
167 def main [
168 1:bool, 2:bool, 3:bool <- not true, false, true
169 ]
170 +mem: storing 0 in location 1
171 +mem: storing 1 in location 2
172 +mem: storing 0 in location 3