<!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 : -->