about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2017-12-04 10:24:50 -0800
committerKartik K. Agaram <vc@akkartik.com>2017-12-04 10:24:50 -0800
commita87118d98906d2eda0265fba6cfef8b979f8d8ec (patch)
tree74d0e584aad6ad6990e1c63be0ef53bdd818d406
parent8050782c17560ef33a85bd739da8158f9c530e39 (diff)
downloadmu-a87118d98906d2eda0265fba6cfef8b979f8d8ec.tar.gz
4137 - perform specialization on indirect calls
https://lobste.rs/s/esqphf/what_are_you_working_on_this_week#c_ajgfim
-rw-r--r--054static_dispatch.cc23
-rw-r--r--072recipe.cc25
2 files changed, 39 insertions, 9 deletions
diff --git a/054static_dispatch.cc b/054static_dispatch.cc
index 566bb7ad..8037892e 100644
--- a/054static_dispatch.cc
+++ b/054static_dispatch.cc
@@ -166,18 +166,23 @@ void resolve_ambiguous_calls(const recipe_ordinal r) {
   for (int index = 0;  index < SIZE(caller_recipe.steps);  ++index) {
     instruction& inst = caller_recipe.steps.at(index);
     if (inst.is_label) continue;
-    if (non_ghost_size(get_or_insert(Recipe_variants, inst.name)) == 0) continue;
-    trace(9992, "transform") << "instruction " << to_original_string(inst) << end();
-    Resolve_stack.push_front(call(r, index));
-    string new_name = best_variant(inst, caller_recipe);
-    if (!new_name.empty())
-      inst.name = new_name;
-    assert(Resolve_stack.front().running_recipe == r);
-    assert(Resolve_stack.front().running_step_index == index);
-    Resolve_stack.pop_front();
+    resolve_ambiguous_call(r, index, inst, caller_recipe);
   }
 }
 
+void resolve_ambiguous_call(const recipe_ordinal r, int index, instruction& inst, const recipe& caller_recipe) {
+  // End resolve_ambiguous_call(r, index, inst, caller_recipe) Special-cases
+  if (non_ghost_size(get_or_insert(Recipe_variants, inst.name)) == 0) return;
+  trace(9992, "transform") << "instruction " << to_original_string(inst) << end();
+  Resolve_stack.push_front(call(r, index));
+  string new_name = best_variant(inst, caller_recipe);
+  if (!new_name.empty())
+    inst.name = new_name;
+  assert(Resolve_stack.front().running_recipe == r);
+  assert(Resolve_stack.front().running_step_index == index);
+  Resolve_stack.pop_front();
+}
+
 string best_variant(const instruction& inst, const recipe& caller_recipe) {
   const vector<recipe_ordinal>& variants = get(Recipe_variants, inst.name);
   vector<recipe_ordinal> candidates;
diff --git a/072recipe.cc b/072recipe.cc
index ca8932ed..f77949e1 100644
--- a/072recipe.cc
+++ b/072recipe.cc
@@ -159,6 +159,31 @@ def f x:point -> y:point [
 +error: main: ingredient 0 has the wrong type at '2:num <- call {1: (recipe point -> point)}, 34'
 +error: main: product 0 has the wrong type at '2:num <- call {1: (recipe point -> point)}, 34'
 
+:(scenario call_check_shape_shifting_recipe)
+def main [
+  1:num <- call f, 34
+]
+def f x:_elem -> y:_elem [
+  local-scope
+  load-ingredients
+  y <- copy x
+]
++mem: storing 34 in location 1
+
+:(before "End resolve_ambiguous_call(r, index, inst, caller_recipe) Special-cases")
+if (inst.name == "call" && !inst.ingredients.empty() && inst.ingredients.at(0).type && inst.ingredients.at(0).type->atom && inst.ingredients.at(0).type->name == "recipe-literal") {
+  instruction inst2;
+  inst2.name = inst.ingredients.at(0).name;
+  for (int i = /*skip recipe*/1;  i < SIZE(inst.ingredients);  ++i)
+    inst2.ingredients.push_back(inst.ingredients.at(i));
+  for (int i = 0;  i < SIZE(inst.products);  ++i)
+    inst2.products.push_back(inst.products.at(i));
+  resolve_ambiguous_call(r, index, inst2, caller_recipe);
+  inst.ingredients.at(0).name = inst2.name;
+  inst.ingredients.at(0).set_value(get(Recipe_ordinal, inst2.name));
+  return;
+}
+
 :(after "Transform.push_back(check_instruction)")
 Transform.push_back(check_indirect_calls_against_header);  // idempotent
 :(code)