https://github.com/akkartik/mu/blob/master/023boolean.cc

      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 && 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(/*skip alloc id*/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