diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-05-05 21:47:59 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-05-05 21:59:50 -0700 |
commit | e76a27f3edfa0703a204f3ab30ce01b58877f6af (patch) | |
tree | b9ff84216ac81d78b6d14dbbf7211981cb30e153 /056static_dispatch.cc | |
parent | 5d5116e3343b5f6efa289e35e1c29b761db12068 (diff) | |
download | mu-e76a27f3edfa0703a204f3ab30ce01b58877f6af.tar.gz |
2929 - fix a bug in static dispatch
Thanks Caleb for finding this. We'd been using sandboxes for so long, I hadn't tried a null/0 screen/console in a while and somewhere down the road Mu stopped matching 0 against concrete addresses.
Diffstat (limited to '056static_dispatch.cc')
-rw-r--r-- | 056static_dispatch.cc | 74 |
1 files changed, 63 insertions, 11 deletions
diff --git a/056static_dispatch.cc b/056static_dispatch.cc index 353b4b50..5271fe13 100644 --- a/056static_dispatch.cc +++ b/056static_dispatch.cc @@ -175,14 +175,18 @@ string best_variant(instruction& inst, const recipe& caller_recipe) { if (!candidates.empty()) return best_variant(inst, candidates).name; // Static Dispatch Phase 2 - //: (shape-shifting recipes in a later layer) - // End Static Dispatch Phase 2 + candidates = strictly_matching_variants_except_literal_zero_against_address(inst, variants); + if (!candidates.empty()) return best_variant(inst, candidates).name; // Static Dispatch Phase 3 - candidates = strictly_matching_variants_except_literal_against_boolean(inst, variants); - if (!candidates.empty()) return best_variant(inst, candidates).name; + //: (shape-shifting recipes in a later layer) + // End Static Dispatch Phase 3 // Static Dispatch Phase 4 + candidates = strictly_matching_variants_except_literal_against_address_or_boolean(inst, variants); + if (!candidates.empty()) return best_variant(inst, candidates).name; + + // Static Dispatch Phase 5 candidates = matching_variants(inst, variants); if (!candidates.empty()) return best_variant(inst, candidates).name; @@ -240,28 +244,65 @@ bool all_header_reagents_strictly_match(const instruction& inst, const recipe& v return true; } -// phase 3 -vector<recipe_ordinal> strictly_matching_variants_except_literal_against_boolean(const instruction& inst, vector<recipe_ordinal>& variants) { +// phase 2 +vector<recipe_ordinal> strictly_matching_variants_except_literal_zero_against_address(const instruction& inst, vector<recipe_ordinal>& variants) { + vector<recipe_ordinal> result; + for (int i = 0; i < SIZE(variants); ++i) { + if (variants.at(i) == -1) continue; + trace(9992, "transform") << "checking variant (strict) " << i << ": " << header_label(variants.at(i)) << end(); + if (all_header_reagents_strictly_match_except_literal_zero_against_address(inst, get(Recipe, variants.at(i)))) + result.push_back(variants.at(i)); + } + return result; +} + +bool all_header_reagents_strictly_match_except_literal_zero_against_address(const instruction& inst, const recipe& variant) { + for (int i = 0; i < min(SIZE(inst.ingredients), SIZE(variant.ingredients)); ++i) { + if (!types_strictly_match_except_literal_zero_against_address(variant.ingredients.at(i), inst.ingredients.at(i))) { + trace(9993, "transform") << "strict match failed: ingredient " << i << end(); + return false; + } + } + for (int i = 0; i < min(SIZE(inst.products), SIZE(variant.products)); ++i) { + if (is_dummy(inst.products.at(i))) continue; + if (!types_strictly_match(variant.products.at(i), inst.products.at(i))) { + trace(9993, "transform") << "strict match failed: product " << i << end(); + return false; + } + } + return true; +} + +bool types_strictly_match_except_literal_zero_against_address(const reagent& to, const reagent& from) { + // to sidestep type-checking, use /unsafe in the source. + // this will be highlighted in red inside vim. just for setting up some tests. + if (is_literal(from) && is_mu_address(to)) + return from.name == "0"; + return types_strictly_match(to, from); +} + +// phase 4 +vector<recipe_ordinal> strictly_matching_variants_except_literal_against_address_or_boolean(const instruction& inst, vector<recipe_ordinal>& variants) { vector<recipe_ordinal> result; for (int i = 0; i < SIZE(variants); ++i) { if (variants.at(i) == -1) continue; trace(9992, "transform") << "checking variant (strict except literals-against-booleans) " << i << ": " << header_label(variants.at(i)) << end(); - if (all_header_reagents_strictly_match_except_literal_against_boolean(inst, get(Recipe, variants.at(i)))) + if (all_header_reagents_strictly_match_except_literal_against_address_or_boolean(inst, get(Recipe, variants.at(i)))) result.push_back(variants.at(i)); } return result; } -bool all_header_reagents_strictly_match_except_literal_against_boolean(const instruction& inst, const recipe& variant) { +bool all_header_reagents_strictly_match_except_literal_against_address_or_boolean(const instruction& inst, const recipe& variant) { for (int i = 0; i < min(SIZE(inst.ingredients), SIZE(variant.ingredients)); ++i) { - if (!types_strictly_match_except_literal_against_boolean(variant.ingredients.at(i), inst.ingredients.at(i))) { + if (!types_strictly_match_except_literal_against_address_or_boolean(variant.ingredients.at(i), inst.ingredients.at(i))) { trace(9993, "transform") << "strict match failed: ingredient " << i << end(); return false; } } for (int i = 0; i < min(SIZE(variant.products), SIZE(inst.products)); ++i) { if (is_dummy(inst.products.at(i))) continue; - if (!types_strictly_match_except_literal_against_boolean(variant.products.at(i), inst.products.at(i))) { + if (!types_strictly_match_except_literal_against_address_or_boolean(variant.products.at(i), inst.products.at(i))) { trace(9993, "transform") << "strict match failed: product " << i << end(); return false; } @@ -269,7 +310,18 @@ bool all_header_reagents_strictly_match_except_literal_against_boolean(const ins return true; } -// phase 4 +bool types_strictly_match_except_literal_against_address_or_boolean(const reagent& to, const reagent& from) { + // to sidestep type-checking, use /unsafe in the source. + // this will be highlighted in red inside vim. just for setting up some tests. + if (is_literal(from) + && to.type && to.type->value == get(Type_ordinal, "boolean")) + return boolean_matches_literal(to, from); + if (is_literal(from) && is_mu_address(to)) + return from.name == "0"; + return types_strictly_match(to, from); +} + +// phase 5 vector<recipe_ordinal> matching_variants(const instruction& inst, vector<recipe_ordinal>& variants) { vector<recipe_ordinal> result; for (int i = 0; i < SIZE(variants); ++i) { |