<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>Mu - 052tangle.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> <meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy="> <meta name="colorscheme" content="minimal"> <style type="text/css"> <!-- pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 12pt; font-size: 1em; } .Constant { color: #00a0a0; } .traceAbsent { color: #c00000; } .traceContains { color: #008000; } .muRecipe { color: #ff8700; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #800080; } .Special { color: #c00000; } .Identifier { color: #c0a020; } .Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; } --> </style> <script type='text/javascript'> <!-- --> </script> </head> <body> <pre id='vimCodeElement'> <span class="Comment">//: Allow code for recipes to be pulled in from multiple places and inserted</span> <span class="Comment">//: at special labels called 'waypoints' using two new top-level commands:</span> <span class="Comment">//: before</span> <span class="Comment">//: after</span> <span class="Comment">//: Most labels are local: they must be unique to a recipe, and are invisible</span> <span class="Comment">//: outside the recipe. However, waypoints are global: a recipe can have</span> <span class="Comment">//: multiple of them, you can't use them as jump targets.</span> <span class="Delimiter">:(before "End is_jump_target Special-cases")</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_waypoint<span class="Delimiter">(</span>label<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">//: Waypoints are always surrounded by '<>', e.g. <handle-request>.</span> <span class="Delimiter">:(code)</span> <span class="Normal">bool</span> is_waypoint<span class="Delimiter">(</span>string label<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Identifier">return</span> *label<span class="Delimiter">.</span>begin<span class="Delimiter">()</span> == <span class="Constant">'<'</span> && *label<span class="Delimiter">.</span>rbegin<span class="Delimiter">()</span> == <span class="Constant">'>'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario tangle_before)</span> <span class="muRecipe">def</span> main [ <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> <label1> <span class="Constant">3</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="muRecipe">before</span> <label1> [ <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="traceContains">+mem: storing 0 in location 1</span> <span class="traceContains">+mem: storing 0 in location 2</span> <span class="traceContains">+mem: storing 0 in location 3</span> <span class="Comment"># nothing else</span> $mem: <span class="Constant">3</span> <span class="Comment">//: while loading recipes, load before/after fragments</span> <span class="Delimiter">:(before "End Globals")</span> map<string <span class="Comment">/*</span><span class="Comment">label</span><span class="Comment">*/</span><span class="Delimiter">,</span> recipe> Before_fragments<span class="Delimiter">,</span> After_fragments<span class="Delimiter">;</span> set<string <span class="Comment">/*</span><span class="Comment">label</span><span class="Comment">*/</span>> Fragments_used<span class="Delimiter">;</span> <span class="Delimiter">:(before "End Setup")</span> Before_fragments<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> After_fragments<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> Fragments_used<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Delimiter">:(before "End Command Handlers")</span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>command == <span class="Constant">"before"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> string label = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>label<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">));</span> raise << <span class="Constant">"incomplete 'before' block at end of file</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> recipe tmp<span class="Delimiter">;</span> slurp_body<span class="Delimiter">(</span>in<span class="Delimiter">,</span> tmp<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_waypoint<span class="Delimiter">(</span>label<span class="Delimiter">))</span> Before_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>Before_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">());</span> <span class="Normal">else</span> raise << <span class="Constant">"can't tangle before non-waypoint "</span> << label << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Comment">// End before Command Handler</span> <span class="Delimiter">}</span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>command == <span class="Constant">"after"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> string label = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>label<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">));</span> raise << <span class="Constant">"incomplete 'after' block at end of file</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> recipe tmp<span class="Delimiter">;</span> slurp_body<span class="Delimiter">(</span>in<span class="Delimiter">,</span> tmp<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_waypoint<span class="Delimiter">(</span>label<span class="Delimiter">))</span> After_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>After_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">());</span> <span class="Normal">else</span> raise << <span class="Constant">"can't tangle after non-waypoint "</span> << label << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Comment">// End after Command Handler</span> <span class="Delimiter">}</span> <span class="Comment">//: after all recipes are loaded, insert fragments at appropriate labels.</span> <span class="Delimiter">:(after "Begin Instruction Inserting/Deleting Transforms")</span> Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>insert_fragments<span class="Delimiter">);</span> <span class="Comment">// NOT idempotent</span> <span class="Comment">//: We might need to perform multiple passes, in case inserted fragments</span> <span class="Comment">//: include more labels that need further insertions. Track which labels we've</span> <span class="Comment">//: already processed using an extra field.</span> <span class="Delimiter">:(before "End instruction Fields")</span> <span class="Normal">mutable</span> <span class="Normal">bool</span> tangle_done<span class="Delimiter">;</span> <span class="Delimiter">:(before "End instruction Constructor")</span> tangle_done = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">:(code)</span> <span class="Normal">void</span> insert_fragments<span class="Delimiter">(</span><span class="Normal">const</span> recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> insert_fragments<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Normal">void</span> insert_fragments<span class="Delimiter">(</span>recipe& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"--- insert fragments into recipe "</span> << r<span class="Delimiter">.</span>name << end<span class="Delimiter">();</span> <span class="Normal">bool</span> made_progress = <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Normal">int</span> pass = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Normal">while</span> <span class="Delimiter">(</span>made_progress<span class="Delimiter">)</span> <span class="Delimiter">{</span> made_progress = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// create a new vector because insertions invalidate iterators</span> vector<instruction> result<span class="Delimiter">;</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>r<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">const</span> instruction& inst = r<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>is_label || !is_waypoint<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">)</span> || inst<span class="Delimiter">.</span>tangle_done<span class="Delimiter">)</span> <span class="Delimiter">{</span> result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">);</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> inst<span class="Delimiter">.</span>tangle_done = <span class="Constant">true</span><span class="Delimiter">;</span> made_progress = <span class="Constant">true</span><span class="Delimiter">;</span> Fragments_used<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">);</span> ostringstream prefix<span class="Delimiter">;</span> prefix << <span class="Constant">'+'</span> << r<span class="Delimiter">.</span>name << <span class="Constant">'_'</span> << pass << <span class="Constant">'_'</span> << i<span class="Delimiter">;</span> <span class="Comment">// ok to use contains_key even though Before_fragments uses [],</span> <span class="Comment">// because appending an empty recipe is a noop</span> <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Before_fragments<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>label<span class="Delimiter">))</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"insert fragments before label "</span> << inst<span class="Delimiter">.</span>label << end<span class="Delimiter">();</span> append_fragment<span class="Delimiter">(</span>result<span class="Delimiter">,</span> Before_fragments[inst<span class="Delimiter">.</span>label]<span class="Delimiter">.</span>steps<span class="Delimiter">,</span> prefix<span class="Delimiter">.</span>str<span class="Delimiter">());</span> <span class="Delimiter">}</span> result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>After_fragments<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>label<span class="Delimiter">))</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"insert fragments after label "</span> << inst<span class="Delimiter">.</span>label << end<span class="Delimiter">();</span> append_fragment<span class="Delimiter">(</span>result<span class="Delimiter">,</span> After_fragments[inst<span class="Delimiter">.</span>label]<span class="Delimiter">.</span>steps<span class="Delimiter">,</span> prefix<span class="Delimiter">.</span>str<span class="Delimiter">());</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> r<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>swap<span class="Delimiter">(</span>result<span class="Delimiter">);</span> ++pass<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Normal">void</span> append_fragment<span class="Delimiter">(</span>vector<instruction>& base<span class="Delimiter">,</span> <span class="Normal">const</span> vector<instruction>& patch<span class="Delimiter">,</span> <span class="Normal">const</span> string prefix<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// append 'patch' to 'base' while keeping 'base' oblivious to any new jump</span> <span class="Comment">// targets in 'patch' oblivious to 'base' by prepending 'prefix' to them.</span> <span class="Comment">// we might tangle the same fragment at multiple points in a single recipe,</span> <span class="Comment">// and we need to avoid duplicate jump targets.</span> <span class="Comment">// so we'll keep jump targets local to the specific before/after fragment</span> <span class="Comment">// that introduces them.</span> set<string> jump_targets<span class="Delimiter">;</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>patch<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">const</span> instruction& inst = patch<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>is_label && is_jump_target<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">))</span> jump_targets<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>patch<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> instruction inst = patch<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>is_label<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>jump_targets<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>label<span class="Delimiter">))</span> inst<span class="Delimiter">.</span>label = prefix+inst<span class="Delimiter">.</span>label<span class="Delimiter">;</span> base<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">);</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> j = <span class="Constant">0</span><span class="Delimiter">;</span> j < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> reagent& x = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_jump_target<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">)</span> && contains_key<span class="Delimiter">(</span>jump_targets<span class="Delimiter">,</span> x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> x<span class="Delimiter">.</span>name = prefix+x<span class="Delimiter">.</span>name<span class="Delimiter">;</span> <span class="Delimiter">}</span> base<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Comment">//: complain about unapplied fragments</span> <span class="Comment">//: This can't run during transform because later (shape-shifting recipes)</span> <span class="Comment">//: we'll encounter situations where fragments might get used long after</span> <span class="Comment">//: they're loaded, and we might run transform_all in between. To avoid</span> <span class="Comment">//: spurious errors, run this check right at the end, after all code is</span> <span class="Comment">//: loaded, right before we run main.</span> <span class="Delimiter">:(before "End Commandline Parsing")</span> check_insert_fragments<span class="Delimiter">();</span> <span class="Delimiter">:(code)</span> <span class="Normal">void</span> check_insert_fragments<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Normal">for</span> <span class="Delimiter">(</span>map<string<span class="Delimiter">,</span> recipe>::iterator p = Before_fragments<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Before_fragments<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Fragments_used<span class="Delimiter">,</span> p<span class="Delimiter">-></span>first<span class="Delimiter">))</span> raise << <span class="Constant">"could not locate insert before label "</span> << p<span class="Delimiter">-></span>first << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Normal">for</span> <span class="Delimiter">(</span>map<string<span class="Delimiter">,</span> recipe>::iterator p = After_fragments<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != After_fragments<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Fragments_used<span class="Delimiter">,</span> p<span class="Delimiter">-></span>first<span class="Delimiter">))</span> raise << <span class="Constant">"could not locate insert after label "</span> << p<span class="Delimiter">-></span>first << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario tangle_before_and_after)</span> <span class="muRecipe">def</span> main [ <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> <label1> <span class="Constant">4</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="muRecipe">before</span> <label1> [ <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="muRecipe">after</span> <label1> [ <span class="Constant">3</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="traceContains">+mem: storing 0 in location 1</span> <span class="traceContains">+mem: storing 0 in location 2</span> <span class="Comment"># label1</span> <span class="traceContains">+mem: storing 0 in location 3</span> <span class="traceContains">+mem: storing 0 in location 4</span> <span class="Comment"># nothing else</span> $mem: <span class="Constant">4</span> <span class="Delimiter">:(scenario tangle_ignores_jump_target)</span> <span class="Special">% Hide_errors = true;</span> <span class="muRecipe">def</span> main [ <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> +label1 <span class="Constant">4</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="muRecipe">before</span> +label1 [ <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="traceContains">+error: can't tangle before non-waypoint +label1</span> <span class="Delimiter">:(scenario tangle_keeps_labels_separate)</span> <span class="muRecipe">def</span> main [ <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> <label1> <label2> <span class="Constant">6</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="muRecipe">before</span> <label1> [ <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="muRecipe">after</span> <label1> [ <span class="Constant">3</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="muRecipe">before</span> <label2> [ <span class="Constant">4</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="muRecipe">after</span> <label2> [ <span class="Constant">5</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="traceContains">+mem: storing 0 in location 1</span> <span class="traceContains">+mem: storing 0 in location 2</span> <span class="Comment"># label1</span> <span class="traceContains">+mem: storing 0 in location 3</span> <span class="Comment"># 'after' fragments for earlier label always go before 'before' fragments for later label</span> <span class="traceContains">+mem: storing 0 in location 4</span> <span class="Comment"># label2</span> <span class="traceContains">+mem: storing 0 in location 5</span> <span class="traceContains">+mem: storing 0 in location 6</span> <span class="Comment"># nothing else</span> $mem: <span class="Constant">6</span> <span class="Delimiter">:(scenario tangle_stacks_multiple_fragments)</span> <span class="muRecipe">def</span> main [ <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> <label1> <span class="Constant">6</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="muRecipe">before</span> <label1> [ <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="muRecipe">after</span> <label1> [ <span class="Constant">3</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="muRecipe">before</span> <label1> [ <span class="Constant">4</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="muRecipe">after</span> <label1> [ <span class="Constant">5</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="traceContains">+mem: storing 0 in location 1</span> <span class="Comment"># 'before' fragments stack in order</span> <span class="traceContains">+mem: storing 0 in location 2</span> <span class="traceContains">+mem: storing 0 in location 4</span> <span class="Comment"># label1</span> <span class="Comment"># 'after' fragments stack in reverse order</span> <span class="traceContains">+mem: storing 0 in location 5</span> <span class="traceContains">+mem: storing 0 in location 3</span> <span class="traceContains">+mem: storing 0 in location 6</span> <span class="Comment"># nothing else</span> $mem: <span class="Constant">6</span> <span class="Delimiter">:(scenario tangle_supports_fragments_with_multiple_instructions)</span> <span class="muRecipe">def</span> main [ <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> <label1> <span class="Constant">6</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="muRecipe">before</span> <label1> [ <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Constant">3</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="muRecipe">after</span> <label1> [ <span class="Constant">4</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Constant">5</span>:num<span class="Special"> <- </span>copy <span class="Constant">0</span> ] <span class="traceContains">+mem: storing 0 in location 1</span> <span class="traceContains">+mem: storing 0 in location 2</span> <span class="traceContains">+mem: storing 0 in location 3</span> <span class="Comment"># label1</span> <span class="traceContains">+mem: storing 0 in location 4</span> <span class="traceContains">+mem: storing 0 in location 5</span> <span class="traceContains">+mem: storing 0 in location 6</span> <span class="Comment"># nothing else</span> $mem: <span class="Constant">6</span> <span class="Delimiter">:(scenario tangle_tangles_into_all_labels_with_same_name)</span> <span class="muRecipe">def</span> main [ <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">10</span> <label1> <span class="Constant">4</span>:num<span class="Special"> <- </span>copy <span class="Constant">10</span> recipe2 ] <span class="muRecipe">def</span> recipe2 [ <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">11</span> <label1> <span class="Constant">4</span>:num<span class="Special"> <- </span>copy <span class="Constant">11</span> ] <span class="muRecipe">before</span> <label1> [ <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">12</span> ] <span class="muRecipe">after</span> <label1> [ <span class="Constant">3</span>:num<span class="Special"> <- </span>copy <span class="Constant">12</span> ] <span class="traceContains">+mem: storing 10 in location 1</span> <span class="traceContains">+mem: storing 12 in location 2</span> <span class="Comment"># label1</span> <span class="traceContains">+mem: storing 12 in location 3</span> <span class="traceContains">+mem: storing 10 in location 4</span> <span class="Comment"># recipe2</span> <span class="traceContains">+mem: storing 11 in location 1</span> <span class="traceContains">+mem: storing 12 in location 2</span> <span class="Comment"># label1</span> <span class="traceContains">+mem: storing 12 in location 3</span> <span class="traceContains">+mem: storing 11 in location 4</span> <span class="Comment"># nothing else</span> $mem: <span class="Constant">8</span> <span class="Delimiter">:(scenario tangle_tangles_into_all_labels_with_same_name_2)</span> <span class="muRecipe">def</span> main [ <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">10</span> <label1> <label1> <span class="Constant">4</span>:num<span class="Special"> <- </span>copy <span class="Constant">10</span> ] <span class="muRecipe">before</span> <label1> [ <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">12</span> ] <span class="muRecipe">after</span> <label1> [ <span class="Constant">3</span>:num<span class="Special"> <- </span>copy <span class="Constant">12</span> ] <span class="traceContains">+mem: storing 10 in location 1</span> <span class="traceContains">+mem: storing 12 in location 2</span> <span class="Comment"># label1</span> <span class="traceContains">+mem: storing 12 in location 3</span> <span class="traceContains">+mem: storing 12 in location 2</span> <span class="Comment"># label1</span> <span class="traceContains">+mem: storing 12 in location 3</span> <span class="traceContains">+mem: storing 10 in location 4</span> <span class="Comment"># nothing else</span> $mem: <span class="Constant">6</span> <span class="Delimiter">:(scenario tangle_tangles_into_all_labels_with_same_name_3)</span> <span class="muRecipe">def</span> main [ <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">10</span> <label1> <foo> <span class="Constant">4</span>:num<span class="Special"> <- </span>copy <span class="Constant">10</span> ] <span class="muRecipe">before</span> <label1> [ <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">12</span> ] <span class="muRecipe">after</span> <label1> [ <span class="Constant">3</span>:num<span class="Special"> <- </span>copy <span class="Constant">12</span> ] <span class="muRecipe">after</span> <foo> [ <label1> ] <span class="traceContains">+mem: storing 10 in location 1</span> <span class="traceContains">+mem: storing 12 in location 2</span> <span class="Comment"># label1</span> <span class="traceContains">+mem: storing 12 in location 3</span> <span class="traceContains">+mem: storing 12 in location 2</span> <span class="Comment"># foo/label1</span> <span class="traceContains">+mem: storing 12 in location 3</span> <span class="traceContains">+mem: storing 10 in location 4</span> <span class="Comment"># nothing else</span> $mem: <span class="Constant">6</span> <span class="Delimiter">:(scenario tangle_handles_jump_target_inside_fragment)</span> <span class="muRecipe">def</span> main [ <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">10</span> <label1> <span class="Constant">4</span>:num<span class="Special"> <- </span>copy <span class="Constant">10</span> ] <span class="muRecipe">before</span> <label1> [ jump <span class="Constant">+label2:label</span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">12</span> +label2 <span class="Constant">3</span>:num<span class="Special"> <- </span>copy <span class="Constant">12</span> ] <span class="traceContains">+mem: storing 10 in location 1</span> <span class="Comment"># label1</span> <span class="traceContains">+mem: storing 12 in location 3</span> <span class="traceContains">+mem: storing 10 in location 4</span> <span class="Comment"># ignored by jump</span> <span class="traceAbsent">-mem: storing 12 in label 2</span> <span class="Comment"># nothing else</span> $mem: <span class="Constant">3</span> <span class="Delimiter">:(scenario tangle_renames_jump_target)</span> <span class="muRecipe">def</span> main [ <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">10</span> <label1> +label2 <span class="Constant">4</span>:num<span class="Special"> <- </span>copy <span class="Constant">10</span> ] <span class="muRecipe">before</span> <label1> [ jump <span class="Constant">+label2:label</span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">12</span> +label2 <span class="Comment"># renamed</span> <span class="Constant">3</span>:num<span class="Special"> <- </span>copy <span class="Constant">12</span> ] <span class="traceContains">+mem: storing 10 in location 1</span> <span class="Comment"># label1</span> <span class="traceContains">+mem: storing 12 in location 3</span> <span class="traceContains">+mem: storing 10 in location 4</span> <span class="Comment"># ignored by jump</span> <span class="traceAbsent">-mem: storing 12 in label 2</span> <span class="Comment"># nothing else</span> $mem: <span class="Constant">3</span> <span class="Delimiter">:(scenario tangle_jump_to_base_recipe)</span> <span class="muRecipe">def</span> main [ <span class="Constant">1</span>:num<span class="Special"> <- </span>copy <span class="Constant">10</span> <label1> +label2 <span class="Constant">4</span>:num<span class="Special"> <- </span>copy <span class="Constant">10</span> ] <span class="muRecipe">before</span> <label1> [ jump <span class="Constant">+label2:label</span> <span class="Constant">2</span>:num<span class="Special"> <- </span>copy <span class="Constant">12</span> <span class="Constant">3</span>:num<span class="Special"> <- </span>copy <span class="Constant">12</span> ] <span class="traceContains">+mem: storing 10 in location 1</span> <span class="Comment"># label1</span> <span class="traceContains">+mem: storing 10 in location 4</span> <span class="Comment"># ignored by jump</span> <span class="traceAbsent">-mem: storing 12 in label 2</span> <span class="traceAbsent">-mem: storing 12 in location 3</span> <span class="Comment"># nothing else</span> $mem: <span class="Constant">2</span> <span class="Comment">//: ensure that there are no new fragments created for a label after it's already been inserted to</span> <span class="Delimiter">:(code)</span> <span class="Normal">void</span> test_new_fragment_after_tangle<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Comment">// define a recipe</span> load<span class="Delimiter">(</span><span class="Constant">"def foo [</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">" local-scope</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">" <label></span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">"after <label> [</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">" 1:num/raw <- copy 34</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> transform_all<span class="Delimiter">();</span> CHECK_TRACE_DOESNT_CONTAIN_ERROR<span class="Delimiter">();</span> Hide_errors = <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Comment">// try to tangle into recipe foo after transform</span> load<span class="Delimiter">(</span><span class="Constant">"before <label> [</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">" 2:num/raw <- copy 35</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> CHECK_TRACE_CONTAINS_ERROR<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End before Command Handler")</span> <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Fragments_used<span class="Delimiter">,</span> label<span class="Delimiter">))</span> raise << <span class="Constant">"we've already tangled some code at label "</span> << label << <span class="Constant">" in a previous call to transform_all(). Those locations won't be updated.</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Delimiter">:(before "End after Command Handler")</span> <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Fragments_used<span class="Delimiter">,</span> label<span class="Delimiter">))</span> raise << <span class="Constant">"we've already tangled some code at label "</span> << label << <span class="Constant">" in a previous call to transform_all(). Those locations won't be updated.</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> </pre> </body> </html> <!-- vim: set foldmethod=manual : -->