about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-11-27 18:10:15 -0800
committerKartik K. Agaram <vc@akkartik.com>2015-11-27 18:10:15 -0800
commit7f193a0e006c44604918b54c853bd49508dbe8fd (patch)
treea937f880fa2e7a64666c8ceb262dc16de9f777be
parent0ddcab7bc0e856dfe5e0556e972f3c21fd16d6d1 (diff)
downloadmu-7f193a0e006c44604918b54c853bd49508dbe8fd.tar.gz
2482 - better choice between valid variants
Literal '0' ingredients should map to numbers before addresses.
-rw-r--r--021check_instruction.cc8
-rw-r--r--031address.cc2
-rw-r--r--057static_dispatch.cc33
3 files changed, 38 insertions, 5 deletions
diff --git a/021check_instruction.cc b/021check_instruction.cc
index f79ae140..930eacde 100644
--- a/021check_instruction.cc
+++ b/021check_instruction.cc
@@ -82,15 +82,19 @@ recipe main [
 $error: 0
 
 :(code)
+bool types_match(const reagent& lhs, const reagent& rhs) {
+  if (!is_unsafe(rhs) && is_literal(rhs)) return valid_type_for_literal(lhs, rhs) && size_of(rhs) == size_of(lhs);
+  return types_strictly_match(lhs, rhs);
+}
+
 // copy arguments because later layers will want to make changes to them
 // without perturbing the caller
-bool types_match(reagent lhs, reagent rhs) {
+bool types_strictly_match(reagent lhs, reagent rhs) {
   // '_' never raises type error
   if (is_dummy(lhs)) return true;
   // 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_unsafe(rhs)) return true;
-  if (is_literal(rhs)) return valid_type_for_literal(lhs, rhs) && size_of(rhs) == size_of(lhs);
   if (!lhs.type) return !rhs.type;
   return types_match(lhs.type, rhs.type);
 }
diff --git a/031address.cc b/031address.cc
index 4d012ad5..040037bd 100644
--- a/031address.cc
+++ b/031address.cc
@@ -61,7 +61,7 @@ void lookup_memory(reagent& x) {
   drop_one_lookup(x);
 }
 
-:(after "bool types_match(reagent lhs, reagent rhs)")
+:(after "bool types_strictly_match(reagent lhs, reagent rhs)")
   if (!canonize_type(lhs)) return false;
   if (!canonize_type(rhs)) return false;
 
diff --git a/057static_dispatch.cc b/057static_dispatch.cc
index f38b813d..bc9fd8e2 100644
--- a/057static_dispatch.cc
+++ b/057static_dispatch.cc
@@ -140,6 +140,7 @@ void replace_best_variant(instruction& inst, const recipe& caller_recipe) {
 }
 
 long long int variant_score(const instruction& inst, recipe_ordinal variant) {
+  long long int result = 100;
   if (variant == -1) return -1;  // ghost from a previous test
   if (!contains_key(Recipe, variant)) {
     assert(variant < MAX_PRIMITIVE_RECIPES);
@@ -155,6 +156,14 @@ long long int variant_score(const instruction& inst, recipe_ordinal variant) {
       trace(9993, "transform") << "mismatch: ingredient " << i << end();
       return -1;
     }
+    if (types_strictly_match(header_ingredients.at(i), inst.ingredients.at(i))) {
+      trace(9993, "transform") << "strict match: ingredient " << i << end();
+    }
+    else {
+      // slight penalty for things like coercing literal 0 to an address
+      trace(9993, "transform") << "non-strict match: ingredient " << i << end();
+      result--;
+    }
   }
   if (SIZE(inst.products) > SIZE(get(Recipe, variant).products)) {
     trace(9993, "transform") << "too few products" << end();
@@ -166,10 +175,18 @@ long long int variant_score(const instruction& inst, recipe_ordinal variant) {
       trace(9993, "transform") << "mismatch: product " << i << end();
       return -1;
     }
+    if (types_strictly_match(header_products.at(i), inst.products.at(i))) {
+      trace(9993, "transform") << "strict match: ingredient " << i << end();
+    }
+    else {
+      // slight penalty for things like coercing literal 0 to an address
+      trace(9993, "transform") << "non-strict match: ingredient " << i << end();
+      result--;
+    }
   }
   // the greater the number of unused ingredients, the lower the score
-  return 100 - (SIZE(get(Recipe, variant).products)-SIZE(inst.products))
-             - (SIZE(inst.ingredients)-SIZE(get(Recipe, variant).ingredients));  // ok to go negative
+  return result - (SIZE(get(Recipe, variant).products)-SIZE(inst.products))
+                - (SIZE(inst.ingredients)-SIZE(get(Recipe, variant).ingredients));  // ok to go negative
 }
 
 :(scenario static_dispatch_disabled_on_headerless_definition)
@@ -212,3 +229,15 @@ recipe equal x:number, y:number -> z:boolean [
 +mem: storing 0 in location 3
 # comparing booleans continues to use primitive
 +mem: storing 1 in location 6
+
+:(scenario static_dispatch_prefers_literals_to_be_numbers_rather_than_addresses)
+recipe main [
+  1:number <- foo 0
+]
+recipe foo x:address:number -> y:number [
+  reply 34
+]
+recipe foo x:number -> y:number [
+  reply 35
+]
++mem: storing 35 in location 1