2713 - require booleans for boolean operations

Thanks Ella Couch for finding this bug. It's helped me find errors in
mu's code itself.
This commit is contained in:
Kartik K. Agaram 2016-02-26 13:27:23 -08:00
parent 1b76245c63
commit bff0fa4508
4 changed files with 70 additions and 5 deletions

View File

@ -12,6 +12,14 @@ case AND: {
goto finish_checking_instruction;
}
}
if (SIZE(inst.products) > 1) {
raise << maybe(get(Recipe, r).name) << "'and' yields exactly one product in '" << to_string(inst) << "'\n" << end();
break;
}
if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
raise << maybe(get(Recipe, r).name) << "'and' should yield a boolean, but got " << inst.products.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
@ -62,6 +70,14 @@ case OR: {
goto finish_checking_instruction;
}
}
if (SIZE(inst.products) > 1) {
raise << maybe(get(Recipe, r).name) << "'or' yields exactly one product in '" << to_string(inst) << "'\n" << end();
break;
}
if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
raise << maybe(get(Recipe, r).name) << "'or' should yield a boolean, but got " << inst.products.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
@ -116,6 +132,13 @@ case NOT: {
goto finish_checking_instruction;
}
}
for (long long int i = 0; i < SIZE(inst.products); ++i) {
if (is_dummy(inst.products.at(i))) continue;
if (!is_mu_boolean(inst.products.at(i))) {
raise << maybe(get(Recipe, r).name) << "'not' should yield a boolean, but got " << inst.products.at(i).original_string << '\n' << end();
goto finish_checking_instruction;
}
}
break;
}
:(before "End Primitive Recipe Implementations")

View File

@ -10,6 +10,14 @@ case EQUAL: {
raise << maybe(get(Recipe, r).name) << "'equal' needs at least two ingredients to compare in '" << to_string(inst) << "'\n" << end();
break;
}
if (SIZE(inst.products) > 1) {
raise << maybe(get(Recipe, r).name) << "'equal' yields exactly one product in '" << to_string(inst) << "'\n" << end();
break;
}
if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
raise << maybe(get(Recipe, r).name) << "'equal' should yield a boolean, but got " << inst.products.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
@ -31,7 +39,7 @@ case EQUAL: {
recipe main [
1:number <- copy 34
2:number <- copy 33
3:number <- equal 1:number, 2:number
3:boolean <- equal 1:number, 2:number
]
+mem: location 1 is 34
+mem: location 2 is 33
@ -41,7 +49,7 @@ recipe main [
recipe main [
1:number <- copy 34
2:number <- copy 34
3:number <- equal 1:number, 2:number
3:boolean <- equal 1:number, 2:number
]
+mem: location 1 is 34
+mem: location 2 is 34
@ -49,13 +57,13 @@ recipe main [
:(scenario equal_multiple)
recipe main [
1:number <- equal 34, 34, 34
1:boolean <- equal 34, 34, 34
]
+mem: storing 1 in location 1
:(scenario equal_multiple_2)
recipe main [
1:number <- equal 34, 34, 35
1:boolean <- equal 34, 34, 35
]
+mem: storing 0 in location 1
@ -75,6 +83,14 @@ case GREATER_THAN: {
goto finish_checking_instruction;
}
}
if (SIZE(inst.products) > 1) {
raise << maybe(get(Recipe, r).name) << "'greater-than' yields exactly one product in '" << to_string(inst) << "'\n" << end();
break;
}
if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
raise << maybe(get(Recipe, r).name) << "'greater-than' should yield a boolean, but got " << inst.products.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
@ -134,6 +150,14 @@ case LESSER_THAN: {
goto finish_checking_instruction;
}
}
if (SIZE(inst.products) > 1) {
raise << maybe(get(Recipe, r).name) << "'lesser-than' yields exactly one product in '" << to_string(inst) << "'\n" << end();
break;
}
if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
raise << maybe(get(Recipe, r).name) << "'lesser-than' should yield a boolean, but got " << inst.products.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
@ -193,6 +217,14 @@ case GREATER_OR_EQUAL: {
goto finish_checking_instruction;
}
}
if (SIZE(inst.products) > 1) {
raise << maybe(get(Recipe, r).name) << "'greater-or-equal' yields exactly one product in '" << to_string(inst) << "'\n" << end();
break;
}
if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
raise << maybe(get(Recipe, r).name) << "'greater-or-equal' should yield a boolean, but got " << inst.products.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
@ -260,6 +292,14 @@ case LESSER_OR_EQUAL: {
goto finish_checking_instruction;
}
}
if (SIZE(inst.products) > 1) {
raise << maybe(get(Recipe, r).name) << "'greater-or-equal' yields exactly one product in '" << to_string(inst) << "'\n" << end();
break;
}
if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_boolean(inst.products.at(0))) {
raise << maybe(get(Recipe, r).name) << "'greater-or-equal' should yield a boolean, but got " << inst.products.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")

View File

@ -83,6 +83,8 @@ recipe foo [
:(after "bool is_mu_number(reagent r)")
if (!canonize_type(r)) return false;
:(after "bool is_mu_boolean(reagent r)")
if (!canonize_type(r)) return false;
:(after "Update product While Type-checking Merge")
if (!canonize_type(product)) continue;

View File

@ -351,7 +351,7 @@ recipe main [
1:address:shared:array:character <- new [abc]
2:number <- hash 1:address:shared:array:character
3:number <- hash_old 1:address:shared:array:character
4:number <- equal 2:number, 3:number
4:boolean <- equal 2:number, 3:number
]
+mem: storing 1 in location 4