about summary refs log tree commit diff stats
path: root/059shape_shifting_recipe.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-11-15 00:37:29 -0800
committerKartik K. Agaram <vc@akkartik.com>2015-11-15 00:37:29 -0800
commitef96f57ce264c8e0bd98f6e8622d1c1e2eceafb2 (patch)
treef2113d385fde9c4b9579521402eab5ec9c1f208d /059shape_shifting_recipe.cc
parent7ecb3374340c02cc2c54abf4a5d4a617f362b4c4 (diff)
downloadmu-ef96f57ce264c8e0bd98f6e8622d1c1e2eceafb2.tar.gz
2441 - never miss any specializations
I was failing to specialize calls containing literals. And then I had to
deal with whether literals should map to numbers or characters. (Answer:
both.)

One of the issues that still remains: shape-shifting recipes can't be
called with literals for addresses, even if it's 0.
Diffstat (limited to '059shape_shifting_recipe.cc')
-rw-r--r--059shape_shifting_recipe.cc48
1 files changed, 44 insertions, 4 deletions
diff --git a/059shape_shifting_recipe.cc b/059shape_shifting_recipe.cc
index bc63d616..feffd410 100644
--- a/059shape_shifting_recipe.cc
+++ b/059shape_shifting_recipe.cc
@@ -34,6 +34,11 @@ if (Current_routine->calls.front().running_step_index == 0
   raise_error << "ran into unspecialized shape-shifting recipe " << current_recipe_name() << '\n' << end();
 }
 
+//: Make sure we don't match up literals with type ingredients without
+//: specialization.
+:(before "End valid_type_for_literal Special-cases")
+if (contains_type_ingredient_name(r)) return false;
+
 //: We'll be creating recipes without loading them from anywhere by
 //: *specializing* existing recipes, so make sure we don't clear any of those
 //: when we start running tests.
@@ -202,14 +207,16 @@ void save_or_deduce_type_name(reagent& x, map<string, string_tree*>& type_name)
 }
 
 void compute_type_ingredient_mappings(const recipe& exemplar, const instruction& inst, map<string, const string_tree*>& mappings, const recipe& caller_recipe, bool* error) {
-  for (long long int i = 0; i < SIZE(exemplar.ingredients); ++i) {
+  long long int limit = min(SIZE(inst.ingredients), SIZE(exemplar.ingredients));
+  for (long long int i = 0; i < limit; ++i) {
     const reagent& exemplar_reagent = exemplar.ingredients.at(i);
     reagent ingredient = inst.ingredients.at(i);
     assert(ingredient.properties.at(0).second);
     canonize_type(ingredient);
     accumulate_type_ingredients(exemplar_reagent, ingredient, mappings, exemplar, inst, caller_recipe, error);
   }
-  for (long long int i = 0; i < SIZE(exemplar.products); ++i) {
+  limit = min(SIZE(inst.products), SIZE(exemplar.products));
+  for (long long int i = 0; i < limit; ++i) {
     const reagent& exemplar_reagent = exemplar.products.at(i);
     reagent product = inst.products.at(i);
     assert(product.properties.at(0).second);
@@ -218,6 +225,10 @@ void compute_type_ingredient_mappings(const recipe& exemplar, const instruction&
   }
 }
 
+inline long long int min(long long int a, long long int b) {
+  return (a < b) ? a : b;
+}
+
 void accumulate_type_ingredients(const reagent& exemplar_reagent, reagent& refinement, map<string, const string_tree*>& mappings, const recipe& exemplar, const instruction& call_instruction, const recipe& caller_recipe, bool* error) {
   assert(refinement.properties.at(0).second);
   accumulate_type_ingredients(exemplar_reagent.properties.at(0).second, refinement.properties.at(0).second, mappings, exemplar, exemplar_reagent, call_instruction, caller_recipe, error);
@@ -237,10 +248,13 @@ void accumulate_type_ingredients(const string_tree* exemplar_type, const string_
     }
     if (!contains_key(mappings, exemplar_type->value)) {
       trace(9993, "transform") << "adding mapping from " << exemplar_type->value << " to " << debug_string(refinement_type) << end();
-      put(mappings, exemplar_type->value, new string_tree(*refinement_type));
+      if (refinement_type->value == "literal")
+        put(mappings, exemplar_type->value, new string_tree("number"));
+      else
+        put(mappings, exemplar_type->value, new string_tree(*refinement_type));
     }
     else {
-      if (!deeply_equal(get(mappings, exemplar_type->value), refinement_type)) {
+      if (!deeply_equal_types(get(mappings, exemplar_type->value), refinement_type)) {
         raise_error << maybe(caller_recipe.name) << "no call found for '" << call_instruction.to_string() << "'\n" << end();
         *error = true;
         return;
@@ -467,3 +481,29 @@ recipe bar x:_elem -> y:_elem [
   y <- add x, 1
 ]
 +mem: storing 4 in location 1
+
+:(scenario specialize_with_literal)
+recipe main [
+  local-scope
+  # permit literal to map to number
+  1:number/raw <- foo 3
+]
+recipe foo x:_elem -> y:_elem [
+  local-scope
+  load-ingredients
+  y <- add x, 1
+]
++mem: storing 4 in location 1
+
+:(scenario specialize_with_literal_2)
+recipe main [
+  local-scope
+  # permit literal to map to character
+  1:character/raw <- foo 3
+]
+recipe foo x:_elem -> y:_elem [
+  local-scope
+  load-ingredients
+  y <- add x, 1
+]
++mem: storing 4 in location 1