diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2015-09-30 01:57:23 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2015-09-30 01:57:23 -0700 |
commit | 4e49b29e63b0d369b81318ac822dc06ce06786b5 (patch) | |
tree | d78b822660f33f40eea08c6747245fb729877073 | |
parent | a0d7a15594990974808cc613a4814d1f86471b5e (diff) | |
download | mu-4e49b29e63b0d369b81318ac822dc06ce06786b5.tar.gz |
2221
-rw-r--r-- | 020run.cc | 1 | ||||
-rw-r--r-- | 021check_type_by_instruction.cc | 9 | ||||
-rw-r--r-- | 022arithmetic.cc | 3 | ||||
-rw-r--r-- | 023boolean.cc | 52 |
4 files changed, 46 insertions, 19 deletions
diff --git a/020run.cc b/020run.cc index 910a1d2d..d1e405a7 100644 --- a/020run.cc +++ b/020run.cc @@ -91,7 +91,6 @@ void run_current_routine() cout << "not a primitive op: " << current_instruction().operation << '\n'; } } - finish_instruction: if (SIZE(products) < SIZE(current_instruction().products)) { raise << SIZE(products) << " vs " << SIZE(current_instruction().products) << ": failed to write to all products! " << current_instruction().to_string() << end(); } diff --git a/021check_type_by_instruction.cc b/021check_type_by_instruction.cc index 0ac5a530..b5fb8197 100644 --- a/021check_type_by_instruction.cc +++ b/021check_type_by_instruction.cc @@ -104,5 +104,12 @@ bool is_mu_number(reagent r) { || r.properties.at(0).second.at(0) == "literal"; if (r.types.empty()) return false; if (r.types.at(0) == Type_ordinal["character"]) return true; // permit arithmetic on unicode code points - return !r.types.empty() && r.types.at(0) == Type_ordinal["number"]; + return r.types.at(0) == Type_ordinal["number"]; +} + +bool is_mu_scalar(reagent r) { + if (is_literal(r)) + return r.properties.at(0).second.at(0) != "literal-string"; + if (is_mu_array(r)) return false; + return size_of(r) == 1; } diff --git a/022arithmetic.cc b/022arithmetic.cc index 9eca7e11..66aefbc8 100644 --- a/022arithmetic.cc +++ b/022arithmetic.cc @@ -6,6 +6,7 @@ ADD, Recipe_ordinal["add"] = ADD; :(before "End Primitive Recipe Type Checks") case ADD: { + // primary goal of these checks is to forbid address arithmetic for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { if (!is_mu_number(inst.ingredients.at(i))) { raise << Recipe[r].name << ": 'add' requires number ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); @@ -78,7 +79,7 @@ case SUBTRACT: { break; } for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { - if (is_raw(inst.ingredients.at(i))) continue; // offsets in tests + if (is_raw(inst.ingredients.at(i))) continue; // permit address offset computations in tests if (!is_mu_number(inst.ingredients.at(i))) { raise << Recipe[r].name << ": 'subtract' requires number ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); goto finish_checking_instruction; diff --git a/023boolean.cc b/023boolean.cc index ead678cf..b0debe6b 100644 --- a/023boolean.cc +++ b/023boolean.cc @@ -4,16 +4,21 @@ AND, :(before "End Primitive Recipe Numbers") Recipe_ordinal["and"] = AND; +:(before "End Primitive Recipe Type Checks") +case AND: { + for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { + if (!is_mu_scalar(inst.ingredients.at(i))) { + raise << Recipe[r].name << ": 'and' requires boolean ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); + goto finish_checking_instruction; + } + } + break; +} :(before "End Primitive Recipe Implementations") case AND: { bool result = true; - for (long long int i = 0; i < SIZE(ingredients); ++i) { - if (!scalar(ingredients.at(i))) { - raise << current_recipe_name() << ": 'and' requires boolean ingredients, but got " << current_instruction().ingredients.at(i).original_string << '\n' << end(); - goto finish_instruction; - } + for (long long int i = 0; i < SIZE(ingredients); ++i) result = result && ingredients.at(i).at(0); - } products.resize(1); products.at(0).push_back(result); break; @@ -49,16 +54,21 @@ recipe main [ OR, :(before "End Primitive Recipe Numbers") Recipe_ordinal["or"] = OR; +:(before "End Primitive Recipe Type Checks") +case OR: { + for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { + if (!is_mu_scalar(inst.ingredients.at(i))) { + raise << Recipe[r].name << ": 'and' requires boolean ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); + goto finish_checking_instruction; + } + } + break; +} :(before "End Primitive Recipe Implementations") case OR: { bool result = false; - for (long long int i = 0; i < SIZE(ingredients); ++i) { - if (!scalar(ingredients.at(i))) { - raise << current_recipe_name() << ": 'or' requires boolean ingredients, but got " << current_instruction().ingredients.at(i).original_string << '\n' << end(); - goto finish_instruction; - } + for (long long int i = 0; i < SIZE(ingredients); ++i) result = result || ingredients.at(i).at(0); - } products.resize(1); products.at(0).push_back(result); break; @@ -94,14 +104,24 @@ recipe main [ NOT, :(before "End Primitive Recipe Numbers") Recipe_ordinal["not"] = NOT; +:(before "End Primitive Recipe Type Checks") +case NOT: { + if (SIZE(inst.products) > SIZE(inst.ingredients)) { + raise << Recipe[r].name << ": 'not' cannot have fewer ingredients than products in '" << inst.to_string() << "'\n" << end(); + break; + } + for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { + if (!is_mu_scalar(inst.ingredients.at(i))) { + raise << Recipe[r].name << ": 'not' requires boolean ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); + goto finish_checking_instruction; + } + } + break; +} :(before "End Primitive Recipe Implementations") case NOT: { products.resize(SIZE(ingredients)); for (long long int i = 0; i < SIZE(ingredients); ++i) { - if (!scalar(ingredients.at(i))) { - raise << current_recipe_name() << ": 'not' requires boolean ingredients, but got " << current_instruction().ingredients.at(i).original_string << '\n' << end(); - goto finish_instruction; - } products.at(i).push_back(!ingredients.at(i).at(0)); } break; |