1 //: Boolean primitives
  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 && ingredients.at(i).at(0);
 30   products.resize(1);
 31   products.at(0).push_back(result);
 32   break;
 33 }
 34 
 35 :(scenario and)
 36 def main [
 37   1:bool <- copy 1
 38   2:bool <- copy 0
 39   3:bool <- and 1:bool, 2:bool
 40 ]
 41 +mem: storing 0 in location 3
 42 
 43 :(scenario and_2)
 44 def main [
 45   1:bool <- and 1, 1
 46 ]
 47 +mem: storing 1 in location 1
 48 
 49 :(scenario and_multiple)
 50 def main [
 51   1:bool <- and 1, 1, 0
 52 ]
 53 +mem: storing 0 in location 1
 54 
 55 :(scenario and_multiple_2)
 56 def main [
 57   1:bool <- and 1, 1, 1
 58 ]
 59 +mem: storing 1 in location 1
 60 
 61 :(before "End Primitive Recipe Declarations")
 62 OR,
 63 :(before "End Primitive Recipe Numbers")
 64 put(Recipe_ordinal, "or", OR);
 65 :(before "End Primitive Recipe Checks")
 66 case OR: {
 67   for (int i = 0;  i < SIZE(inst.ingredients);  ++i) {
 68   ¦ if (!is_mu_scalar(inst.ingredients.at(i))) {
 69   ¦ ¦ raise << maybe(get(Recipe, r).name) << "'and' requires boolean ingredients, but got '" << inst.ingredients.at(i).original_string << "'\n" << end();
 70   ¦ ¦ goto finish_checking_instruction;
 71   ¦ }
 72   }
 73   if (SIZE(inst.products) > 1) {
 74   ¦ raise << maybe(get(Recipe, r).name) << "'or' yields exactly one product in '" << to_original_string(inst) << "'\n" << end();
 75   ¦ break;
 76   }
 77   if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
 78   ¦ raise << maybe(get(Recipe, r).name) << "'or' should yield a boolean, but got '" << inst.products.at(0).original_string << "'\n" << end();
 79   ¦ break;
 80   }
 81   break;
 82 }
 83 :(before "End Primitive Recipe Implementations")
 84 case OR: {
 85   bool result = false;
 86   for (int i = 0;  i < SIZE(ingredients);  ++i)
 87   ¦ result = result || ingredients.at(i).at(0);
 88   products.resize(1);
 89   products.at(0).push_back(result);
 90   break;
 91 }
 92 
 93 :(scenario or)
 94 def main [
 95   1:bool <- copy 1
 96   2:bool <- copy 0
 97   3:bool <- or 1:bool, 2:bool
 98 ]
 99 +mem: storing 1 in location 3
100 
101 :(scenario or_2)
102 def main [
103   1:bool <- or 0, 0
104 ]
105 +mem: storing 0 in location 1
106 
107 :(scenario or_multiple)
108 def main [
109   1:bool <- and 0, 0, 0
110 ]
111 +mem: storing 0 in location 1
112 
113 :(scenario or_multiple_2)
114 def main [
115   1:bool <- or 0, 0, 1
116 ]
117 +mem: storing 1 in location 1
118 
119 :(before "End Primitive Recipe Declarations")
120 NOT,
121 :(before "End Primitive Recipe Numbers")
122 put(Recipe_ordinal, "not", NOT);
123 :(before "End Primitive Recipe Checks")
124 case NOT: {
125   if (SIZE(inst.products) != SIZE(inst.ingredients)) {
126   ¦ raise << "ingredients and products should match in '" << to_original_string(inst) << "'\n" << end();
127   ¦ break;
128   }
129   for (int i = 0;  i < SIZE(inst.ingredients);  ++i) {
130   ¦ if (!is_mu_scalar(inst.ingredients.at(i))) {
131   ¦ ¦ raise << maybe(get(Recipe, r).name) << "'not' requires boolean ingredients, but got '" << inst.ingredients.at(i).original_string << "'\n" << end();
132   ¦ ¦ goto finish_checking_instruction;
133   ¦ }
134   }
135   for (int i = 0;  i < SIZE(inst.products);  ++i) {
136   ¦ if (is_dummy(inst.products.at(i))) continue;
137   ¦ if (!is_mu_boolean(inst.products.at(i))) {
138   ¦ ¦ raise << maybe(get(Recipe, r).name) << "'not' should yield a boolean, but got '" << inst.products.at(i).original_string << "'\n" << end();
139   ¦ ¦ goto finish_checking_instruction;
140   ¦ }
141   }
142   break;
143 }
144 :(before "End Primitive Recipe Implementations")
145 case NOT: {
146   products.resize(SIZE(ingredients));
147   for (int i = 0;  i < SIZE(ingredients);  ++i) {
148   ¦ products.at(i).push_back(!ingredients.at(i).at(0));
149   }
150   break;
151 }
152 
153 :(scenario not)
154 def main [
155   1:bool <- copy 1
156   2:bool <- not 1:bool
157 ]
158 +mem: storing 0 in location 2
159 
160 :(scenario not_multiple)
161 def main [
162   1:bool, 2:bool, 3:bool <- not 1, 0, 1
163 ]
164 +mem: storing 0 in location 1
165 +mem: storing 1 in location 2
166 +mem: storing 0 in location 3