about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--046check_type_by_name.cc1
-rw-r--r--056shape_shifting_recipe.cc1
-rw-r--r--072recipe.cc82
3 files changed, 60 insertions, 24 deletions
diff --git a/046check_type_by_name.cc b/046check_type_by_name.cc
index 3fd3fdd6..df5a2a6d 100644
--- a/046check_type_by_name.cc
+++ b/046check_type_by_name.cc
@@ -36,6 +36,7 @@ void check_or_set_types_by_name(const recipe_ordinal r) {
 }
 
 void deduce_missing_type(set<reagent>& known, reagent& x, const recipe& caller) {
+  // Deduce Missing Type(x, caller)
   if (x.type) return;
   if (is_jump_target(x.name)) {
     x.type = new type_tree("label");
diff --git a/056shape_shifting_recipe.cc b/056shape_shifting_recipe.cc
index bae60527..edded1b0 100644
--- a/056shape_shifting_recipe.cc
+++ b/056shape_shifting_recipe.cc
@@ -314,6 +314,7 @@ void save_or_deduce_type_name(reagent& x, map<string, type_tree*>& type, const r
     trace(9994, "transform") << "    deducing type to " << names_to_string(x.type) << end();
     return;
   }
+  // Type Check in Type-ingredient-aware check_or_set_types_by_name
   // This is different from check_or_set_types_by_name.
   // We've found it useful in the past for tracking down bugs in
   // specialization.
diff --git a/072recipe.cc b/072recipe.cc
index 34b49b3f..d05e8575 100644
--- a/072recipe.cc
+++ b/072recipe.cc
@@ -21,31 +21,21 @@ put(Type_ordinal, "recipe-literal", 0);
 type_ordinal recipe = put(Type_ordinal, "recipe", Next_type_ordinal++);
 get_or_insert(Type, recipe).name = "recipe";
 
-:(after "Begin transform_names Ingredient Special-cases(ingredient, inst, caller)")
-if (is_recipe_literal(ingredient, caller)) {
-  initialize_recipe_literal(ingredient);
-  continue;
-}
-:(after "Begin transform_names Product Special-cases(product, inst, caller)")
-if (is_recipe_literal(product, caller)) {
-  initialize_recipe_literal(product);
-  continue;
-}
+:(after "Deduce Missing Type(x, caller)")
+if (!x.type)
+  try_initialize_recipe_literal(x, caller);
+:(before "Type Check in Type-ingredient-aware check_or_set_types_by_name")
+if (!x.type)
+  try_initialize_recipe_literal(x, variant);
 :(code)
-bool is_recipe_literal(const reagent& x, const recipe& caller) {
-  if (x.type) return false;
-  if (!contains_key(Recipe_ordinal, x.name)) return false;
-  if (contains_reagent_with_type(caller, x.name)) {
-    raise << maybe(caller.name) << "you can't use '" << x.name << "' as a recipe literal when it's also a variable\n" << end();
-    return false;
-  }
-  return true;
-}
-void initialize_recipe_literal(reagent& x) {
+void try_initialize_recipe_literal(reagent& x, const recipe& caller) {
+  if (x.type) return;
+  if (!contains_key(Recipe_ordinal, x.name)) return;
+  if (contains_reagent_with_non_recipe_literal_type(caller, x.name)) return;
   x.type = new type_tree("recipe-literal");
   x.set_value(get(Recipe_ordinal, x.name));
 }
-bool contains_reagent_with_type(const recipe& caller, const string& name) {
+bool contains_reagent_with_non_recipe_literal_type(const recipe& caller, const string& name) {
   for (int i = 0;  i < SIZE(caller.steps);  ++i) {
     const instruction& inst = caller.steps.at(i);
     for (int i = 0;  i < SIZE(inst.ingredients);  ++i)
@@ -58,8 +48,7 @@ bool contains_reagent_with_type(const recipe& caller, const string& name) {
 bool is_matching_non_recipe_literal(const reagent& x, const string& name) {
   if (x.name != name) return false;
   if (!x.type) return false;
-  if (!x.type->atom) return false;
-  return x.type->value != get(Type_ordinal, "recipe-literal");
+  return !x.type->atom || x.type->name != "recipe-literal";
 }
 
 //: It's confusing to use variable names that are also recipe names. Always
@@ -71,7 +60,6 @@ def main [
   a:bool <- equal break 0
   break:bool <- copy 0
 ]
-+error: main: you can't use 'break' as a recipe literal when it's also a variable
 +error: main: missing type for 'break' in 'a:bool <- equal break, 0'
 
 :(before "End Primitive Recipe Declarations")
@@ -130,6 +118,19 @@ def f x:num -> y:num [
 ]
 +mem: storing 34 in location 2
 
+:(scenario call_literal_recipe_repeatedly)
+def main [
+  1:num <- call f, 34
+  1:num <- call f, 35
+]
+def f x:num -> y:num [
+  local-scope
+  load-ingredients
+  y <- copy x
+]
++mem: storing 34 in location 1
++mem: storing 35 in location 1
+
 :(scenario call_shape_shifting_recipe)
 def main [
   1:num <- call f, 34
@@ -141,6 +142,39 @@ def f x:_elem -> y:_elem [
 ]
 +mem: storing 34 in location 1
 
+:(scenario call_shape_shifting_recipe_inside_shape_shifting_recipe)
+def main [
+  1:num <- f 34
+]
+def f x:_elem -> y:_elem [
+  local-scope
+  load-ingredients
+  y <- call g x
+]
+def g x:_elem -> y:_elem [
+  local-scope
+  load-ingredients
+  y <- copy x
+]
++mem: storing 34 in location 1
+
+:(scenario call_shape_shifting_recipe_repeatedly_inside_shape_shifting_recipe)
+def main [
+  1:num <- f 34
+]
+def f x:_elem -> y:_elem [
+  local-scope
+  load-ingredients
+  y <- call g x
+  y <- call g x
+]
+def g x:_elem -> y:_elem [
+  local-scope
+  load-ingredients
+  y <- copy x
+]
++mem: storing 34 in location 1
+
 //:: check types for 'call' instructions
 
 :(scenario call_check_literal_recipe)