about summary refs log tree commit diff stats
path: root/058shape_shifting_recipe.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-04-27 22:28:55 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-04-27 22:28:55 -0700
commit5b22547bb352f6e5a98ddd8ff42f37861a8e16ea (patch)
treecf531cce10d5f570f55dd54a46361dad882a14f6 /058shape_shifting_recipe.cc
parentb1ddb414006352b2d3af3652263a536acbd2702e (diff)
downloadmu-5b22547bb352f6e5a98ddd8ff42f37861a8e16ea.tar.gz
2880
Turns out we don't need a primitive to return an empty value of
arbitrary type. Just create it on the heap using 'new'.

But this uncovered *yet* another bug, sigh. When I specialize generic
functions I was running all transforms on the generated functions after
specialization completed. But there's one transform that includes code
from elsewhere. If such code included type-ingredients -- kaboom. Now
fixed and there's a test, so I've got that going for me which is nice.
Diffstat (limited to '058shape_shifting_recipe.cc')
-rw-r--r--058shape_shifting_recipe.cc30
1 files changed, 28 insertions, 2 deletions
diff --git a/058shape_shifting_recipe.cc b/058shape_shifting_recipe.cc
index 6067fe7e..0384dd57 100644
--- a/058shape_shifting_recipe.cc
+++ b/058shape_shifting_recipe.cc
@@ -61,6 +61,8 @@ if (!candidates.empty()) {
   if (!variant.steps.empty()) {
     trace(9992, "transform") << "transforming new specialization: " << variant.name << end();
     for (int t = 0; t < SIZE(Transform); ++t) {
+      // one exception: skip tangle, which would have already occurred inside new_variant above
+      if (Transform.at(t) == insert_fragments) continue;
       (*Transform.at(t))(new_recipe_ordinal);
     }
   }
@@ -230,8 +232,14 @@ recipe_ordinal new_variant(recipe_ordinal exemplar, const instruction& inst, con
   recipe& new_recipe = get(Recipe, new_recipe_ordinal);
   new_recipe.name = new_name;
   trace(9993, "transform") << "switching " << inst.name << " to specialized " << header_label(new_recipe_ordinal) << end();
-  // Since the exemplar never ran any transforms, we have to redo some of the
-  // work of the check_types_by_name transform while supporting type-ingredients.
+
+  // Replace type ingredients with concrete types in new_recipe.
+  //
+  // preprocessing: micro-manage a couple of transforms
+  // a) perform tangle *before* replacing type ingredients, just in case
+  // inserted code involves type ingredients
+  insert_fragments(new_recipe_ordinal);
+  // b) do the work of check_types_by_name while supporting type-ingredients
   compute_type_names(new_recipe);
   // that gives enough information to replace type-ingredients with concrete types
   {
@@ -1027,3 +1035,21 @@ def main [
   foo *z
 ]
 # shouldn't crash
+
+:(scenario tangle_shape_shifting_recipe)
+# shape-shifting recipe
+def foo a:_elem [
+  local-scope
+  load-ingredients
+  <label1>
+]
+# tangle some code that refers to the type ingredient
+after <label1> [
+  b:_elem <- copy a
+]
+# trigger specialization
+def main [
+  local-scope
+  foo 34
+]
+$exit: 0