about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--010vm.cc5
-rw-r--r--052tangle.cc87
2 files changed, 72 insertions, 20 deletions
diff --git a/010vm.cc b/010vm.cc
index 9e6b4e24..41a63e2c 100644
--- a/010vm.cc
+++ b/010vm.cc
@@ -35,6 +35,7 @@ struct instruction {
   recipe_ordinal operation;  // Recipe_ordinal[name]
   vector<reagent> ingredients;  // only if !is_label
   vector<reagent> products;  // only if !is_label
+  // End instruction Fields
   instruction();
   void clear();
   string to_string() const;
@@ -171,7 +172,9 @@ Next_recipe_ordinal = 1000;  // consistent new numbers for each test
 //:: Helpers
 
 :(code)
-instruction::instruction() :is_label(false), operation(IDLE) {}
+instruction::instruction() :is_label(false), operation(IDLE) {
+  // End instruction Constructor
+}
 void instruction::clear() { is_label=false; label.clear(); operation=IDLE; ingredients.clear(); products.clear(); }
 
 // Reagents have the form <name>:<type>:<type>:.../<property>/<property>/...
diff --git a/052tangle.cc b/052tangle.cc
index 3b0f75df..3392acbf 100644
--- a/052tangle.cc
+++ b/052tangle.cc
@@ -42,31 +42,35 @@ else if (command == "after") {
   After_fragments[label].steps.insert(After_fragments[label].steps.begin(), tmp.steps.begin(), tmp.steps.end());
 }
 
-//: after all recipes are loaded, insert fragments at appropriate labels
+//: after all recipes are loaded, insert fragments at appropriate labels.
 
 :(after "int main")
   Transform.push_back(insert_fragments);
 
+//; We might need to perform multiple passes, in case inserted fragments
+//: include more labels that need further insertions. Track which labels we've
+//: already processed using an extra field.
+:(before "End instruction Fields")
+mutable bool tangle_done;
+:(before "End instruction Constructor")
+tangle_done = false;
+
 :(code)
 void insert_fragments(const recipe_ordinal r) {
-  // Copy into a new vector because insertions invalidate iterators.
-  vector<instruction> result;
-  set<string /*label*/> fragments_inserted_this_recipe;
-  long long int fragments_originally_inserted = 0;
-  while (true) {  // repeat passes until convergence (inserted fragments might include more labels)
+  bool made_progress = true;
+  while (made_progress) {
+    made_progress = false;
+    // create a new vector because insertions invalidate iterators
+    vector<instruction> result;
     for (long long int i = 0; i < SIZE(Recipe[r].steps); ++i) {
       const instruction inst = Recipe[r].steps.at(i);
-      if (!inst.is_label) {
-        result.push_back(inst);
-        continue;
-      }
-      if (fragments_inserted_this_recipe.find(inst.label) != fragments_inserted_this_recipe.end()) {
-        // already processed in a previous pass; ignore
+      if (!inst.is_label || inst.tangle_done) {
         result.push_back(inst);
         continue;
       }
+      inst.tangle_done = true;
+      made_progress = true;
       Fragments_used.insert(inst.label);
-      fragments_inserted_this_recipe.insert(inst.label);
       if (Before_fragments.find(inst.label) != Before_fragments.end()) {
 //?         cerr << "loading code before " << inst.label << '\n'; //? 1
         result.insert(result.end(), Before_fragments[inst.label].steps.begin(), Before_fragments[inst.label].steps.end());
@@ -78,12 +82,6 @@ void insert_fragments(const recipe_ordinal r) {
       }
     }
     Recipe[r].steps.swap(result);
-    if (fragments_originally_inserted == SIZE(fragments_inserted_this_recipe)) {
-      break;  // converged
-    }
-    // not yet converged; prepare next pass
-    result.clear();
-    fragments_originally_inserted = SIZE(fragments_inserted_this_recipe);
   }
 }
 
@@ -242,3 +240,54 @@ after +label1 [
 +mem: storing 11 in location 4
 # nothing else
 $mem: 8
+
+:(scenario tangle_tangles_into_all_labels_with_same_name_2)
+recipe main [
+  1:number <- copy 10
+  +label1
+  +label1
+  4:number <- copy 10
+]
+before +label1 [
+  2:number <- copy 12
+]
+after +label1 [
+  3:number <- copy 12
+]
++mem: storing 10 in location 1
++mem: storing 12 in location 2
+# label1
++mem: storing 12 in location 3
++mem: storing 12 in location 2
+# label1
++mem: storing 12 in location 3
++mem: storing 10 in location 4
+# nothing else
+$mem: 6
+
+:(scenario tangle_tangles_into_all_labels_with_same_name_3)
+recipe main [
+  1:number <- copy 10
+  +label1
+  +foo
+  4:number <- copy 10
+]
+before +label1 [
+  2:number <- copy 12
+]
+after +label1 [
+  3:number <- copy 12
+]
+after +foo [
+  +label1
+]
++mem: storing 10 in location 1
++mem: storing 12 in location 2
+# label1
++mem: storing 12 in location 3
++mem: storing 12 in location 2
+# +foo/label1
++mem: storing 12 in location 3
++mem: storing 10 in location 4
+# nothing else
+$mem: 6