summary refs log tree commit diff stats
path: root/doc/pydoc/ranger.fsobject.html
blob: 1993e46706057b78c0246b42f6564c1cfc590d58 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Python: package ranger.fsobject</title>
</head><body bgcolor="#f0f0f8">

<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#7799ee">
<td valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="ranger.html"><font color="#ffffff">ranger</font></a>.fsobject</strong></big></big></font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/hut/ranger/ranger/fsobject/__init__.py">/home/hut/ranger/ranger/fsobject/__init__.py</a></font></td></tr></table>
    <p><tt>FileSystemObjects&nbsp;are&nbsp;representation&nbsp;of&nbsp;files&nbsp;and&nbsp;directories<br>
with&nbsp;fast&nbsp;access&nbsp;to&nbsp;their&nbsp;properties&nbsp;through&nbsp;caching</tt></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#aa55cc">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Package Contents</strong></big></font></td></tr>
    
<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="ranger.fsobject.directory.html">directory</a><br>
</td><td width="25%" valign=top><a href="ranger.fsobject.file.html">file</a><br>
</td><td width="25%" valign=top><a href="ranger.fsobject.fsobject.html">fsobject</a><br>
</td><td width="25%" valign=top><a href="ranger.fsobject.loader.html">loader</a><br>
</td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ee77aa">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
    
<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl>
<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>(<a href="exceptions.html#BaseException">exceptions.BaseException</a>)
</font></dt><dd>
<dl>
<dt><font face="helvetica, arial"><a href="ranger.fsobject.html#NotLoadedYet">NotLoadedYet</a>
</font></dt></dl>
</dd>
</dl>
 <p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ffc8d8">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#000000" face="helvetica, arial"><a name="NotLoadedYet">class <strong>NotLoadedYet</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
    
<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl><dt>Method resolution order:</dt>
<dd><a href="ranger.fsobject.html#NotLoadedYet">NotLoadedYet</a></dd>
<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
</dl>
<hr>
Data descriptors defined here:<br>
<dl><dt><strong>__weakref__</strong></dt>
<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
</dl>
<hr>
Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
<dl><dt><a name="NotLoadedYet-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#NotLoadedYet-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;x.__class__.__doc__&nbsp;for&nbsp;signature</tt></dd></dl>

<hr>
Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object at 0x2ae9659f6000&gt;<dd><tt>T.<a href="#NotLoadedYet-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;object&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>

<hr>
Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
<dl><dt><a name="NotLoadedYet-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#NotLoadedYet-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>

<dl><dt><a name="NotLoadedYet-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#NotLoadedYet-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>

<dl><dt><a name="NotLoadedYet-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#NotLoadedYet-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>

<dl><dt><a name="NotLoadedYet-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#NotLoadedYet-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
&nbsp;<br>
Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>

<dl><dt><a name="NotLoadedYet-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>

<dl><dt><a name="NotLoadedYet-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#NotLoadedYet-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>

<dl><dt><a name="NotLoadedYet-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#NotLoadedYet-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>

<dl><dt><a name="NotLoadedYet-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>

<dl><dt><a name="NotLoadedYet-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#NotLoadedYet-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>

<dl><dt><a name="NotLoadedYet-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>

<hr>
Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
<dl><dt><strong>__dict__</strong></dt>
</dl>
<dl><dt><strong>args</strong></dt>
</dl>
<dl><dt><strong>message</strong></dt>
</dl>
</td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#55aa55">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
    
<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><strong>BAD_INFO</strong> = None<br>
<strong>T_DIRECTORY</strong> = 'directory'<br>
<strong>T_FILE</strong> = 'file'<br>
<strong>T_NONEXISTANT</strong> = 'nonexistant'<br>
<strong>T_UNKNOWN</strong> = 'unknown'</td></tr></table>
</body></html>
ddress&quot; &quot;number&quot;)} &lt;- copy {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- copy {0: &quot;literal&quot;}</span> <span class="traceContains">+mem: decrementing refcount of 1000: 2 -&gt; 1</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;number&quot;)} &lt;- copy {0: &quot;literal&quot;}</span> <span class="traceContains">+mem: decrementing refcount of 1000: 1 -&gt; 0</span> <span class="Delimiter">:(before &quot;End Globals&quot;)</span> <span class="Comment">//: escape hatch for a later layer</span> <span class="Normal">bool</span> Update_refcounts_in_write_memory = <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">:(before &quot;End write_memory(x) Special-cases&quot;)</span> <span class="Normal">if</span> <span class="Delimiter">(</span>Update_refcounts_in_write_memory<span class="Delimiter">)</span> update_any_refcounts<span class="Delimiter">(</span>x<span class="Delimiter">,</span> data<span class="Delimiter">);</span> <span class="Delimiter">:(code)</span> <span class="Normal">void</span> update_any_refcounts<span class="Delimiter">(</span><span class="Normal">const</span> reagent&amp; canonized_x<span class="Delimiter">,</span> <span class="Normal">const</span> vector&lt;<span class="Normal">double</span>&gt;&amp; data<span class="Delimiter">)</span> <span class="Delimiter">{</span> increment_any_refcounts<span class="Delimiter">(</span>canonized_x<span class="Delimiter">,</span> data<span class="Delimiter">);</span> <span class="Comment">// increment first so we don't reclaim on x &lt;- copy x</span> decrement_any_refcounts<span class="Delimiter">(</span>canonized_x<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">void</span> increment_any_refcounts<span class="Delimiter">(</span><span class="Normal">const</span> reagent&amp; canonized_x<span class="Delimiter">,</span> <span class="Normal">const</span> vector&lt;<span class="Normal">double</span>&gt;&amp; data<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>canonized_x<span class="Delimiter">))</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>data<span class="Delimiter">));</span> assert<span class="Delimiter">(</span>!canonized_x<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>size<span class="Delimiter">);</span> increment_refcount<span class="Delimiter">(</span>data<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Comment">// End Increment Refcounts(canonized_x)</span> <span class="Delimiter">}</span> <span class="Normal">void</span> increment_refcount<span class="Delimiter">(</span><span class="Normal">int</span> new_address<span class="Delimiter">)</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>new_address &gt;= <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>new_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Normal">int</span> new_refcount = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> new_address<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;incrementing refcount of &quot;</span> &lt;&lt; new_address &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; new_refcount &lt;&lt; <span class="Constant">&quot; -&gt; &quot;</span> &lt;&lt; new_refcount+<span class="Constant">1</span> &lt;&lt; end<span class="Delimiter">();</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> new_address<span class="Delimiter">,</span> new_refcount+<span class="Constant">1</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">void</span> decrement_any_refcounts<span class="Delimiter">(</span><span class="Normal">const</span> reagent&amp; canonized_x<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>canonized_x<span class="Delimiter">))</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>canonized_x<span class="Delimiter">.</span>value<span class="Delimiter">);</span> assert<span class="Delimiter">(</span>!canonized_x<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>size<span class="Delimiter">);</span> decrement_refcount<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> canonized_x<span class="Delimiter">.</span>value<span class="Delimiter">),</span> canonized_x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> payload_size<span class="Delimiter">(</span>canonized_x<span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Comment">// End Decrement Refcounts(canonized_x)</span> <span class="Delimiter">}</span> <span class="Normal">void</span> decrement_refcount<span class="Delimiter">(</span><span class="Normal">int</span> old_address<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* payload_type<span class="Delimiter">,</span> <span class="Normal">int</span> payload_size<span class="Delimiter">)</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>old_address &gt;= <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>old_address<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">int</span> old_refcount = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> old_address<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;decrementing refcount of &quot;</span> &lt;&lt; old_address &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; old_refcount &lt;&lt; <span class="Constant">&quot; -&gt; &quot;</span> &lt;&lt; old_refcount-<span class="Constant">1</span> &lt;&lt; end<span class="Delimiter">();</span> --old_refcount<span class="Delimiter">;</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> old_address<span class="Delimiter">,</span> old_refcount<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>old_refcount &lt; <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> tb_shutdown<span class="Delimiter">();</span> cerr &lt;&lt; <span class="Constant">&quot;Negative refcount!!! &quot;</span> &lt;&lt; old_address &lt;&lt; <span class="Constant">' '</span> &lt;&lt; old_refcount &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span> cerr &lt;&lt; <span class="Constant">&quot;Saving trace to last_trace.</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span> ofstream fout<span class="Delimiter">(</span><span class="Constant">&quot;last_trace&quot;</span><span class="Delimiter">);</span> fout &lt;&lt; Trace_stream<span class="Delimiter">-&gt;</span>readable_contents<span class="Delimiter">(</span><span class="Constant">&quot;&quot;</span><span class="Delimiter">);</span> fout<span class="Delimiter">.</span>close<span class="Delimiter">();</span> <span class="Delimiter">}</span> exit<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Comment">// End Decrement Refcount(old_address, payload_type, payload_size)</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Normal">int</span> payload_size<span class="Delimiter">(</span>reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> x<span class="Delimiter">)</span> <span class="Delimiter">{</span> x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> string_tree*&gt;<span class="Delimiter">(</span><span class="Constant">&quot;lookup&quot;</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> lookup_memory_core<span class="Delimiter">(</span>x<span class="Delimiter">);</span> <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>x<span class="Delimiter">)</span> + <span class="Comment">/*</span><span class="Comment">refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario refcounts_reflexive)</span> def main [ <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Comment"># idempotent copies leave refcount unchanged</span> <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:num ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- copy {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="traceContains">+mem: decrementing refcount of 1000: 2 -&gt; 1</span> <span class="Delimiter">:(scenario refcounts_call)</span> def main [ <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Comment"># passing in addresses to recipes increments refcount</span> foo <span class="Constant">1</span>:address:num <span class="Comment"># return does NOT yet decrement refcount; memory must be explicitly managed</span> <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type ] def foo [ <span class="Constant">2</span>:address:num<span class="Special"> &lt;- </span>next-ingredient ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="traceContains">+run: foo {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="Comment"># leave ambiguous precisely when the next increment happens; a later layer</span> <span class="Comment"># will mess with that</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: decrementing refcount of 1000: 2 -&gt; 1</span> <span class="Comment">//: fix up any instructions that don't follow the usual flow of read_memory</span> <span class="Comment">//: before the RUN switch, and write_memory after</span> <span class="Delimiter">:(scenario refcounts_put)</span> container foo [ <span class="Normal">x</span>:address:num ] def main [ <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">2</span>:address:foo<span class="Special"> &lt;- </span><span class="Normal">new</span> foo:type *<span class="Constant">2</span>:address:foo<span class="Special"> &lt;- </span>put *<span class="Constant">2</span>:address:foo<span class="Delimiter">,</span> x:offset<span class="Delimiter">,</span> <span class="Constant">1</span>:address:num ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;foo&quot;)} &lt;- new {foo: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1002: 0 -&gt; 1</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;foo&quot;), &quot;lookup&quot;: ()} &lt;- put {2: (&quot;address&quot; &quot;foo&quot;), &quot;lookup&quot;: ()}, {x: &quot;offset&quot;}, {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="Comment"># put increments refcount</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="Delimiter">:(after &quot;Write Memory in PUT in Run&quot;)</span> reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> element = element_type<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">,</span> offset<span class="Delimiter">);</span> assert<span class="Delimiter">(</span>!has_property<span class="Delimiter">(</span>element<span class="Delimiter">,</span> <span class="Constant">&quot;lookup&quot;</span><span class="Delimiter">));</span> element<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>address<span class="Delimiter">);</span> update_any_refcounts<span class="Delimiter">(</span>element<span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">));</span> <span class="Delimiter">:(scenario refcounts_put_index)</span> def main [ <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">2</span>:address:array:address:num<span class="Special"> &lt;- </span><span class="Normal">new</span> <span class="Delimiter">{(</span>address number<span class="Delimiter">)</span>: type<span class="Delimiter">},</span> <span class="Constant">3</span> *<span class="Constant">2</span>:address:array:address:num<span class="Special"> &lt;- </span>put-index *<span class="Constant">2</span>:address:array:address:num<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">1</span>:address:num ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;array&quot; &quot;address&quot; &quot;number&quot;)} &lt;- new {(address number): &quot;type&quot;}, {3: &quot;literal&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1002: 0 -&gt; 1</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;array&quot; &quot;address&quot; &quot;number&quot;), &quot;lookup&quot;: ()} &lt;- put-index {2: (&quot;address&quot; &quot;array&quot; &quot;address&quot; &quot;number&quot;), &quot;lookup&quot;: ()}, {0: &quot;literal&quot;}, {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="Comment"># put-index increments refcount</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="Delimiter">:(after &quot;Write Memory in PUT_INDEX in Run&quot;)</span> update_any_refcounts<span class="Delimiter">(</span>element<span class="Delimiter">,</span> value<span class="Delimiter">);</span> <span class="Delimiter">:(scenario refcounts_maybe_convert)</span> exclusive-container foo [ <span class="Normal">x</span>:num <span class="Normal">p</span>:address:num ] def main [ <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">2</span>:foo<span class="Special"> &lt;- </span>merge <span class="Constant">1</span>/p<span class="Delimiter">,</span> <span class="Constant">1</span>:address:num <span class="Constant">4</span>:address:num<span class="Delimiter">,</span> <span class="Constant">5</span>:<span class="Normal">bool</span><span class="Special"> &lt;- </span>maybe-convert <span class="Constant">2</span>:foo<span class="Delimiter">,</span> <span class="Constant">1</span>:variant/p ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="Comment"># merging in an address increments refcount</span> <span class="traceContains">+run: {2: &quot;foo&quot;} &lt;- merge {1: &quot;literal&quot;, &quot;p&quot;: ()}, {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="traceContains">+run: {4: (&quot;address&quot; &quot;number&quot;)}, {5: &quot;boolean&quot;} &lt;- maybe-convert {2: &quot;foo&quot;}, {1: &quot;variant&quot;, &quot;p&quot;: ()}</span> <span class="Comment"># maybe-convert increments refcount on success</span> <span class="traceContains">+mem: incrementing refcount of 1000: 2 -&gt; 3</span> <span class="Delimiter">:(after &quot;Write Memory in Successful MAYBE_CONVERT&quot;)</span> <span class="Comment">// </span><span class="Todo">TODO</span><span class="Comment">: double-check data here as well</span> vector&lt;<span class="Normal">double</span>&gt; data<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 &lt; size_of<span class="Delimiter">(</span>product<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> data<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address+<span class="Comment">/*</span><span class="Comment">skip tag</span><span class="Comment">*/</span><span class="Constant">1</span>+i<span class="Delimiter">));</span> update_any_refcounts<span class="Delimiter">(</span>product<span class="Delimiter">,</span> data<span class="Delimiter">);</span> <span class="SalientComment">//:: manage refcounts in instructions that copy multiple locations at a time</span> <span class="Delimiter">:(scenario refcounts_copy_nested)</span> container foo [ <span class="Normal">x</span>:address:num <span class="Comment"># address inside container</span> ] def main [ <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">2</span>:address:foo<span class="Special"> &lt;- </span><span class="Normal">new</span> foo:type *<span class="Constant">2</span>:address:foo<span class="Special"> &lt;- </span>put *<span class="Constant">2</span>:address:foo<span class="Delimiter">,</span> x:offset<span class="Delimiter">,</span> <span class="Constant">1</span>:address:num <span class="Constant">3</span>:foo<span class="Special"> &lt;- </span>copy *<span class="Constant">2</span>:address:foo ] <span class="traceContains">+transform: compute address offsets for container foo</span> <span class="traceContains">+transform: checking container foo, element 0</span> <span class="traceContains">+transform: address at offset 0</span> <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;foo&quot;), &quot;lookup&quot;: ()} &lt;- put {2: (&quot;address&quot; &quot;foo&quot;), &quot;lookup&quot;: ()}, {x: &quot;offset&quot;}, {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="Comment"># copying a container increments refcounts of any contained addresses</span> <span class="traceContains">+run: {3: &quot;foo&quot;} &lt;- copy {2: (&quot;address&quot; &quot;foo&quot;), &quot;lookup&quot;: ()}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 2 -&gt; 3</span> <span class="Delimiter">:(after &quot;End type_tree Definition&quot;)</span> <span class="Normal">struct</span> address_element_info <span class="Delimiter">{</span> <span class="Normal">int</span> offset<span class="Delimiter">;</span> <span class="Comment">// where inside a container type (after flattening nested containers!) the address lies</span> <span class="Normal">const</span> type_tree* payload_type<span class="Delimiter">;</span> <span class="Comment">// all the information we need to compute sizes of items inside an address inside a container. Doesn't need to be a full-scale reagent, since an address inside a container can never be an array, and arrays are the only type that need to know their location to compute their size.</span> address_element_info<span class="Delimiter">(</span><span class="Normal">int</span> o<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* p<span class="Delimiter">)</span> <span class="Delimiter">{</span> offset = o<span class="Delimiter">;</span> payload_type = p<span class="Delimiter">;</span> <span class="Delimiter">}</span> address_element_info<span class="Delimiter">(</span><span class="Normal">const</span> address_element_info&amp; other<span class="Delimiter">)</span> <span class="Delimiter">{</span> offset = other<span class="Delimiter">.</span>offset<span class="Delimiter">;</span> payload_type = other<span class="Delimiter">.</span>payload_type ? <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*other<span class="Delimiter">.</span>payload_type<span class="Delimiter">)</span> : <span class="Constant">NULL</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> ~address_element_info<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>payload_type<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">delete</span> payload_type<span class="Delimiter">;</span> payload_type = <span class="Constant">NULL</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> address_element_info&amp; <span class="Normal">operator</span>=<span class="Delimiter">(</span><span class="Normal">const</span> address_element_info&amp; other<span class="Delimiter">)</span> <span class="Delimiter">{</span> offset = other<span class="Delimiter">.</span>offset<span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>payload_type<span class="Delimiter">)</span> <span class="Normal">delete</span> payload_type<span class="Delimiter">;</span> payload_type = other<span class="Delimiter">.</span>payload_type ? <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*other<span class="Delimiter">.</span>payload_type<span class="Delimiter">)</span> : <span class="Constant">NULL</span><span class="Delimiter">;</span> <span class="Identifier">return</span> *<span class="Normal">this</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">};</span> <span class="Comment">// For exclusive containers we might sometimes have an address at some offset</span> <span class="Comment">// if some other offset has a specific tag. This struct encapsulates such</span> <span class="Comment">// guards.</span> <span class="Normal">struct</span> tag_condition_info <span class="Delimiter">{</span> <span class="Normal">int</span> offset<span class="Delimiter">;</span> <span class="Normal">int</span> tag<span class="Delimiter">;</span> tag_condition_info<span class="Delimiter">(</span><span class="Normal">int</span> o<span class="Delimiter">,</span> <span class="Normal">int</span> t<span class="Delimiter">)</span> :offset<span class="Delimiter">(</span>o<span class="Delimiter">),</span> tag<span class="Delimiter">(</span>t<span class="Delimiter">)</span> <span class="Delimiter">{}</span> <span class="Delimiter">};</span> <span class="Delimiter">:(before &quot;End container_metadata Fields&quot;)</span> <span class="Comment">// a list of facts of the form:</span> <span class="Comment">//</span> <span class="Comment">// IF offset o1 has tag t2 AND offset o2 has tag t2 AND .., THEN</span> <span class="Comment">// for all address_element_infos:</span> <span class="Comment">// you need to update refcounts for the address at offset pointing to a payload of type payload_type (just in case we need to abandon something in the process)</span> map&lt;set&lt;tag_condition_info&gt;<span class="Delimiter">,</span> set&lt;address_element_info&gt; &gt; address<span class="Delimiter">;</span> <span class="Delimiter">:(code)</span> <span class="Normal">bool</span> <span class="Normal">operator</span>&lt;<span class="Delimiter">(</span><span class="Normal">const</span> set&lt;tag_condition_info&gt;&amp; a<span class="Delimiter">,</span> <span class="Normal">const</span> set&lt;tag_condition_info&gt;&amp; b<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">.</span>size<span class="Delimiter">()</span> != b<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Identifier">return</span> a<span class="Delimiter">.</span>size<span class="Delimiter">()</span> &lt; b<span class="Delimiter">.</span>size<span class="Delimiter">();</span> <span class="Normal">for</span> <span class="Delimiter">(</span>set&lt;tag_condition_info&gt;::const_iterator pa = a<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> pb = b<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> pa != a<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++pa<span class="Delimiter">,</span> ++pb<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>pa<span class="Delimiter">-&gt;</span>offset != pb<span class="Delimiter">-&gt;</span>offset<span class="Delimiter">)</span> <span class="Identifier">return</span> pa<span class="Delimiter">-&gt;</span>offset &lt; pb<span class="Delimiter">-&gt;</span>offset<span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>pa<span class="Delimiter">-&gt;</span>tag != pb<span class="Delimiter">-&gt;</span>tag<span class="Delimiter">)</span> <span class="Identifier">return</span> pa<span class="Delimiter">-&gt;</span>tag &lt; pb<span class="Delimiter">-&gt;</span>tag<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// equal</span> <span class="Delimiter">}</span> <span class="Normal">bool</span> <span class="Normal">operator</span>&lt;<span class="Delimiter">(</span><span class="Normal">const</span> tag_condition_info&amp; a<span class="Delimiter">,</span> <span class="Normal">const</span> tag_condition_info&amp; b<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">.</span>offset != b<span class="Delimiter">.</span>offset<span class="Delimiter">)</span> <span class="Identifier">return</span> a<span class="Delimiter">.</span>offset &lt; b<span class="Delimiter">.</span>offset<span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">.</span>tag != b<span class="Delimiter">.</span>tag<span class="Delimiter">)</span> <span class="Identifier">return</span> a<span class="Delimiter">.</span>tag &lt; b<span class="Delimiter">.</span>tag<span class="Delimiter">;</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// equal</span> <span class="Delimiter">}</span> <span class="Normal">bool</span> <span class="Normal">operator</span>&lt;<span class="Delimiter">(</span><span class="Normal">const</span> set&lt;address_element_info&gt;&amp; a<span class="Delimiter">,</span> <span class="Normal">const</span> set&lt;address_element_info&gt;&amp; b<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">.</span>size<span class="Delimiter">()</span> != b<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Identifier">return</span> a<span class="Delimiter">.</span>size<span class="Delimiter">()</span> &lt; b<span class="Delimiter">.</span>size<span class="Delimiter">();</span> <span class="Normal">for</span> <span class="Delimiter">(</span>set&lt;address_element_info&gt;::const_iterator pa = a<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> pb = b<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> pa != a<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++pa<span class="Delimiter">,</span> ++pb<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>pa<span class="Delimiter">-&gt;</span>offset != pb<span class="Delimiter">-&gt;</span>offset<span class="Delimiter">)</span> <span class="Identifier">return</span> pa<span class="Delimiter">-&gt;</span>offset &lt; pb<span class="Delimiter">-&gt;</span>offset<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// equal</span> <span class="Delimiter">}</span> <span class="Normal">bool</span> <span class="Normal">operator</span>&lt;<span class="Delimiter">(</span><span class="Normal">const</span> address_element_info&amp; a<span class="Delimiter">,</span> <span class="Normal">const</span> address_element_info&amp; b<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">.</span>offset != b<span class="Delimiter">.</span>offset<span class="Delimiter">)</span> <span class="Identifier">return</span> a<span class="Delimiter">.</span>offset &lt; b<span class="Delimiter">.</span>offset<span class="Delimiter">;</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// equal</span> <span class="Delimiter">}</span> <span class="Comment">//: populate metadata.address in a separate transform, because it requires</span> <span class="Comment">//: already knowing the sizes of all types</span> <span class="Delimiter">:(after &quot;Transform.push_back(compute_container_sizes)&quot;)</span> Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>compute_container_address_offsets<span class="Delimiter">);</span> <span class="Delimiter">:(code)</span> <span class="Normal">void</span> compute_container_address_offsets<span class="Delimiter">(</span><span class="Normal">const</span> recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> recipe&amp; caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- compute address offsets for &quot;</span> &lt;&lt; caller<span class="Delimiter">.</span>name &lt;&lt; end<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 &lt; SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> instruction&amp; inst = caller<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;- compute address offsets for &quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> &lt;&lt; end<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 &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> compute_container_address_offsets<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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 &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> compute_container_address_offsets<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Normal">void</span> compute_container_address_offsets<span class="Delimiter">(</span>reagent&amp; r<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>r<span class="Delimiter">)</span> || is_dummy<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">))</span> r<span class="Delimiter">.</span>metadata = get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Comment">// the recursive structure of this function needs to exactly match</span> <span class="Comment">// compute_container_sizes</span> <span class="Normal">void</span> compute_container_address_offsets<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">-&gt;</span>name == <span class="Constant">&quot;address&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> compute_container_address_offsets<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">-&gt;</span>name == <span class="Constant">&quot;array&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">const</span> type_tree* element_type = type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">;</span> <span class="Comment">// hack: support both array:num:3 and array:address:num</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!element_type<span class="Delimiter">-&gt;</span>atom &amp;&amp; element_type<span class="Delimiter">-&gt;</span>right &amp;&amp; element_type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>atom &amp;&amp; is_integer<span class="Delimiter">(</span>element_type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>name<span class="Delimiter">))</span> element_type = element_type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">;</span> compute_container_address_offsets<span class="Delimiter">(</span>element_type<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Comment">// End compute_container_address_offsets Non-atom Cases</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> root_type<span class="Delimiter">(</span>type<span class="Delimiter">)-&gt;</span>value<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// error raised elsewhere</span> type_info&amp; info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> root_type<span class="Delimiter">(</span>type<span class="Delimiter">)-&gt;</span>value<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> compute_container_address_offsets<span class="Delimiter">(</span>info<span class="Delimiter">,</span> type<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == EXCLUSIVE_CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> compute_exclusive_container_address_offsets<span class="Delimiter">(</span>info<span class="Delimiter">,</span> type<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Normal">void</span> compute_container_address_offsets<span class="Delimiter">(</span><span class="Normal">const</span> type_info&amp; container_info<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* full_type<span class="Delimiter">)</span> <span class="Delimiter">{</span> container_metadata&amp; metadata = get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> full_type<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!metadata<span class="Delimiter">.</span>address<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> trace<span class="Delimiter">(</span><span class="Constant">9994</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;compute address offsets for container &quot;</span> &lt;&lt; container_info<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span> append_addresses<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> full_type<span class="Delimiter">,</span> metadata<span class="Delimiter">.</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">());</span> <span class="Delimiter">}</span> <span class="Normal">void</span> compute_exclusive_container_address_offsets<span class="Delimiter">(</span><span class="Normal">const</span> type_info&amp; exclusive_container_info<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* full_type<span class="Delimiter">)</span> <span class="Delimiter">{</span> container_metadata&amp; metadata = get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> full_type<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">9994</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;compute address offsets for exclusive container &quot;</span> &lt;&lt; exclusive_container_info<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> tag = <span class="Constant">0</span><span class="Delimiter">;</span> tag &lt; SIZE<span class="Delimiter">(</span>exclusive_container_info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++tag<span class="Delimiter">)</span> <span class="Delimiter">{</span> set&lt;tag_condition_info&gt; key<span class="Delimiter">;</span> key<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>tag_condition_info<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">tag is at offset</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">,</span> tag<span class="Delimiter">));</span> append_addresses<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">skip tag offset</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> variant_type<span class="Delimiter">(</span>full_type<span class="Delimiter">,</span> tag<span class="Delimiter">).</span>type<span class="Delimiter">,</span> metadata<span class="Delimiter">.</span>address<span class="Delimiter">,</span> key<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Normal">void</span> append_addresses<span class="Delimiter">(</span><span class="Normal">int</span> base_offset<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* type<span class="Delimiter">,</span> map&lt;set&lt;tag_condition_info&gt;<span class="Delimiter">,</span> set&lt;address_element_info&gt; &gt;&amp; out<span class="Delimiter">,</span> <span class="Normal">const</span> set&lt;tag_condition_info&gt;&amp; key<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>type<span class="Delimiter">))</span> <span class="Delimiter">{</span> get_or_insert<span class="Delimiter">(</span>out<span class="Delimiter">,</span> key<span class="Delimiter">).</span>insert<span class="Delimiter">(</span>address_element_info<span class="Delimiter">(</span>base_offset<span class="Delimiter">,</span> <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)));</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">const</span> type_tree* root = root_type<span class="Delimiter">(</span>type<span class="Delimiter">);</span> <span class="Normal">const</span> type_info&amp; info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> root<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> curr_index = <span class="Constant">0</span><span class="Delimiter">,</span> curr_offset = base_offset<span class="Delimiter">;</span> curr_index &lt; SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++curr_index<span class="Delimiter">)</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;checking container &quot;</span> &lt;&lt; root<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;, element &quot;</span> &lt;&lt; curr_index &lt;&lt; end<span class="Delimiter">();</span> reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> element = element_type<span class="Delimiter">(</span>type<span class="Delimiter">,</span> curr_index<span class="Delimiter">);</span> <span class="Comment">// not root</span> <span class="Comment">// Compute Container Address Offset(element)</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;address at offset &quot;</span> &lt;&lt; curr_offset &lt;&lt; end<span class="Delimiter">();</span> get_or_insert<span class="Delimiter">(</span>out<span class="Delimiter">,</span> key<span class="Delimiter">).</span>insert<span class="Delimiter">(</span>address_element_info<span class="Delimiter">(</span>curr_offset<span class="Delimiter">,</span> <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*element<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)));</span> ++curr_offset<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_container<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> append_addresses<span class="Delimiter">(</span>curr_offset<span class="Delimiter">,</span> element<span class="Delimiter">.</span>type<span class="Delimiter">,</span> out<span class="Delimiter">,</span> key<span class="Delimiter">);</span> curr_offset += size_of<span class="Delimiter">(</span>element<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_exclusive_container<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Normal">const</span> type_tree* element_root_type = root_type<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">);</span> <span class="Normal">const</span> type_info&amp; element_info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> element_root_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> tag = <span class="Constant">0</span><span class="Delimiter">;</span> tag &lt; SIZE<span class="Delimiter">(</span>element_info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++tag<span class="Delimiter">)</span> <span class="Delimiter">{</span> set&lt;tag_condition_info&gt; new_key = key<span class="Delimiter">;</span> new_key<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>tag_condition_info<span class="Delimiter">(</span>curr_offset<span class="Delimiter">,</span> tag<span class="Delimiter">));</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>out<span class="Delimiter">,</span> new_key<span class="Delimiter">))</span> append_addresses<span class="Delimiter">(</span>curr_offset+<span class="Comment">/*</span><span class="Comment">skip tag</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> variant_type<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">,</span> tag<span class="Delimiter">).</span>type<span class="Delimiter">,</span> out<span class="Delimiter">,</span> new_key<span class="Delimiter">);</span> <span class="Delimiter">}</span> curr_offset += size_of<span class="Delimiter">(</span>element<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">else</span> <span class="Delimiter">{</span> <span class="Comment">// non-address primitive</span> ++curr_offset<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == EXCLUSIVE_CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> tag = <span class="Constant">0</span><span class="Delimiter">;</span> tag &lt; SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++tag<span class="Delimiter">)</span> <span class="Delimiter">{</span> set&lt;tag_condition_info&gt; new_key = key<span class="Delimiter">;</span> new_key<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>tag_condition_info<span class="Delimiter">(</span>base_offset<span class="Delimiter">,</span> tag<span class="Delimiter">));</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>out<span class="Delimiter">,</span> new_key<span class="Delimiter">))</span> append_addresses<span class="Delimiter">(</span>base_offset+<span class="Comment">/*</span><span class="Comment">skip tag</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> variant_type<span class="Delimiter">(</span>type<span class="Delimiter">,</span> tag<span class="Delimiter">).</span>type<span class="Delimiter">,</span> out<span class="Delimiter">,</span> new_key<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Normal">int</span> payload_size<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>name == <span class="Constant">&quot;address&quot;</span><span class="Delimiter">);</span> assert<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>name != <span class="Constant">&quot;array&quot;</span><span class="Delimiter">);</span> <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> + <span class="Comment">/*</span><span class="Comment">refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Comment">//: for the following unit tests we'll do the work of the transform by hand</span> <span class="Delimiter">:(before &quot;End Unit Tests&quot;)</span> <span class="Normal">void</span> test_container_address_offsets_empty<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Normal">int</span> old_size = SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> <span class="Comment">// define a container with no addresses</span> reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:point&quot;</span><span class="Delimiter">);</span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> <span class="Comment">// scan</span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// global metadata contains just the entry for foo</span> <span class="Comment">// no entries for non-container types or other junk</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// the reagent we scanned knows it has no addresses</span> CHECK<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>address<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> <span class="Comment">// the global table contains an identical entry</span> CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">));</span> CHECK<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">).</span>address<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">void</span> test_container_address_offsets<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Normal">int</span> old_size = SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> <span class="Comment">// define a container with an address at offset 0 that we have the size for</span> run<span class="Delimiter">(</span><span class="Constant">&quot;container foo [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot; x:address:num</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span> reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:foo&quot;</span><span class="Delimiter">);</span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> <span class="Comment">// scan</span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// global metadata contains just the entry for foo</span> <span class="Comment">// no entries for non-container types or other junk</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// the reagent we scanned knows it has an address at offset 0</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>address<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">()));</span> <span class="Normal">const</span> set&lt;address_element_info&gt;&amp; address_offsets = get<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">());</span> <span class="Comment">// unconditional for containers</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>address_offsets<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">,</span> <span class="Constant">&quot;number&quot;</span><span class="Delimiter">);</span> <span class="Comment">// the global table contains an identical entry</span> CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">));</span> <span class="Normal">const</span> set&lt;address_element_info&gt;&amp; address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">).</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">());</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">,</span> <span class="Constant">&quot;number&quot;</span><span class="Delimiter">);</span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">void</span> test_container_address_offsets_2<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Normal">int</span> old_size = SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> <span class="Comment">// define a container with an address at offset 1 that we have the size for</span> run<span class="Delimiter">(</span><span class="Constant">&quot;container foo [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot; x:num</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot; y:address:num</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span> reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:foo&quot;</span><span class="Delimiter">);</span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> <span class="Comment">// global metadata contains just the entry for foo</span> <span class="Comment">// no entries for non-container types or other junk</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// scan</span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// the reagent we scanned knows it has an address at offset 1</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>address<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">()));</span> <span class="Normal">const</span> set&lt;address_element_info&gt;&amp; address_offsets = get<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">());</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>address_offsets<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>offset<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">//</span> CHECK<span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">,</span> <span class="Constant">&quot;number&quot;</span><span class="Delimiter">);</span> <span class="Comment">// the global table contains an identical entry</span> CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">));</span> <span class="Normal">const</span> set&lt;address_element_info&gt;&amp; address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">).</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">());</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>offset<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">//</span> CHECK<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">,</span> <span class="Constant">&quot;number&quot;</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">void</span> test_container_address_offsets_nested<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Normal">int</span> old_size = SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> <span class="Comment">// define a container with a nested container containing an address</span> run<span class="Delimiter">(</span><span class="Constant">&quot;container foo [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot; x:address:num</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot; y:num</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot;container bar [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot; p:point</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot; f:foo</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Comment">// nested container containing address</span> <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span> reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:bar&quot;</span><span class="Delimiter">);</span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> <span class="Comment">// global metadata contains entries for bar and included types: point and foo</span> <span class="Comment">// no entries for non-container types or other junk</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">3</span><span class="Delimiter">);</span> <span class="Comment">// scan</span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// the reagent we scanned knows it has an address at offset 2</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>address<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">()));</span> <span class="Normal">const</span> set&lt;address_element_info&gt;&amp; address_offsets = get<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">());</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>address_offsets<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>offset<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">);</span> <span class="Comment">//</span> CHECK<span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">,</span> <span class="Constant">&quot;number&quot;</span><span class="Delimiter">);</span> <span class="Comment">// the global table also knows its address offset</span> CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">));</span> <span class="Normal">const</span> set&lt;address_element_info&gt;&amp; address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">).</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">());</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>offset<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">);</span> <span class="Comment">//</span> CHECK<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">,</span> <span class="Constant">&quot;number&quot;</span><span class="Delimiter">);</span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">3</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">void</span> test_container_address_offsets_from_address<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Normal">int</span> old_size = SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> <span class="Comment">// define a container with an address at offset 0</span> run<span class="Delimiter">(</span><span class="Constant">&quot;container foo [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot; x:address:num</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span> reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:address:foo&quot;</span><span class="Delimiter">);</span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> <span class="Comment">// global metadata contains just the entry for foo</span> <span class="Comment">// no entries for non-container types or other junk</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// scan an address to the container</span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// scanning precomputed metadata for the container</span> reagent container<span class="Delimiter">(</span><span class="Constant">&quot;x:foo&quot;</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span> <span class="Normal">const</span> set&lt;address_element_info&gt;&amp; address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">).</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">());</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">,</span> <span class="Constant">&quot;number&quot;</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">void</span> test_container_address_offsets_from_array<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Normal">int</span> old_size = SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> <span class="Comment">// define a container with an address at offset 0</span> run<span class="Delimiter">(</span><span class="Constant">&quot;container foo [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot; x:address:num</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span> reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:array:foo&quot;</span><span class="Delimiter">);</span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> <span class="Comment">// global metadata contains just the entry for foo</span> <span class="Comment">// no entries for non-container types or other junk</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// scan an array of the container</span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// scanning precomputed metadata for the container</span> reagent container<span class="Delimiter">(</span><span class="Constant">&quot;x:foo&quot;</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span> <span class="Normal">const</span> set&lt;address_element_info&gt;&amp; address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">).</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">());</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">,</span> <span class="Constant">&quot;number&quot;</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">void</span> test_container_address_offsets_from_address_to_array<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Normal">int</span> old_size = SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> <span class="Comment">// define a container with an address at offset 0</span> run<span class="Delimiter">(</span><span class="Constant">&quot;container foo [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot; x:address:num</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span> reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:address:array:foo&quot;</span><span class="Delimiter">);</span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> <span class="Comment">// global metadata contains just the entry for foo</span> <span class="Comment">// no entries for non-container types or other junk</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// scan an address to an array of the container</span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// scanning precomputed metadata for the container</span> reagent container<span class="Delimiter">(</span><span class="Constant">&quot;x:foo&quot;</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span> <span class="Normal">const</span> set&lt;address_element_info&gt;&amp; address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">).</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">());</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">,</span> <span class="Constant">&quot;number&quot;</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">void</span> test_container_address_offsets_from_static_array<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Normal">int</span> old_size = SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> <span class="Comment">// define a container with an address at offset 0</span> run<span class="Delimiter">(</span><span class="Constant">&quot;container foo [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot; x:address:num</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span> reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:array:foo:10&quot;</span><span class="Delimiter">);</span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> <span class="Comment">// global metadata contains just the entry for foo</span> <span class="Comment">// no entries for non-container types or other junk</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// scan a static array of the container</span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// scanning precomputed metadata for the container</span> reagent container<span class="Delimiter">(</span><span class="Constant">&quot;x:foo&quot;</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span> <span class="Normal">const</span> set&lt;address_element_info&gt;&amp; address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">).</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">());</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">,</span> <span class="Constant">&quot;number&quot;</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">void</span> test_container_address_offsets_from_address_to_static_array<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Normal">int</span> old_size = SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> <span class="Comment">// define a container with an address at offset 0</span> run<span class="Delimiter">(</span><span class="Constant">&quot;container foo [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot; x:address:num</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span> reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:address:array:foo:10&quot;</span><span class="Delimiter">);</span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> <span class="Comment">// global metadata contains just the entry for foo</span> <span class="Comment">// no entries for non-container types or other junk</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// scan an address to a static array of the container</span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// scanning precomputed metadata for the container</span> reagent container<span class="Delimiter">(</span><span class="Constant">&quot;x:foo&quot;</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span> <span class="Normal">const</span> set&lt;address_element_info&gt;&amp; address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">).</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">());</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">,</span> <span class="Constant">&quot;number&quot;</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">void</span> test_container_address_offsets_from_repeated_address_and_array_types<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Normal">int</span> old_size = SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> <span class="Comment">// define a container with an address at offset 0</span> run<span class="Delimiter">(</span><span class="Constant">&quot;container foo [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot; x:address:num</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span> <span class="Comment">// scan a deep nest of 'address' and 'array' types modifying a container</span> reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:address:array:address:address:array:foo:10&quot;</span><span class="Delimiter">);</span> compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// need to first pre-populate the metadata</span> <span class="Comment">// global metadata contains just the entry for foo</span> <span class="Comment">// no entries for non-container types or other junk</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> compute_container_address_offsets<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// compute_container_address_offsets creates no new entries</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">)</span>-old_size<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// scanning precomputed metadata for the container</span> reagent container<span class="Delimiter">(</span><span class="Constant">&quot;x:foo&quot;</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span> <span class="Normal">const</span> set&lt;address_element_info&gt;&amp; address_offsets2 = get<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">).</span>address<span class="Delimiter">,</span> set&lt;tag_condition_info&gt;<span class="Delimiter">());</span> CHECK_EQ<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">),</span> <span class="Constant">1</span><span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>offset<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> CHECK<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span> CHECK_EQ<span class="Delimiter">(</span>address_offsets2<span class="Delimiter">.</span>begin<span class="Delimiter">()-&gt;</span>payload_type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">,</span> <span class="Constant">&quot;number&quot;</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Comment">//: use metadata.address to update refcounts within containers, arrays and</span> <span class="Comment">//: exclusive containers</span> <span class="Delimiter">:(before &quot;End Increment Refcounts(canonized_x)&quot;)</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_container<span class="Delimiter">(</span>canonized_x<span class="Delimiter">)</span> || is_mu_exclusive_container<span class="Delimiter">(</span>canonized_x<span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Normal">const</span> container_metadata&amp; metadata = get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> canonized_x<span class="Delimiter">.</span>type<span class="Delimiter">);</span> <span class="Normal">for</span> <span class="Delimiter">(</span>map&lt;set&lt;tag_condition_info&gt;<span class="Delimiter">,</span> set&lt;address_element_info&gt; &gt;::const_iterator p = metadata<span class="Delimiter">.</span>address<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != metadata<span class="Delimiter">.</span>address<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>!all_match<span class="Delimiter">(</span>data<span class="Delimiter">,</span> p<span class="Delimiter">-&gt;</span>first<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Normal">for</span> <span class="Delimiter">(</span>set&lt;address_element_info&gt;::const_iterator info = p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> info != p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++info<span class="Delimiter">)</span> increment_refcount<span class="Delimiter">(</span>data<span class="Delimiter">.</span>at<span class="Delimiter">(</span>info<span class="Delimiter">-&gt;</span>offset<span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Decrement Refcounts(canonized_x)&quot;)</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_container<span class="Delimiter">(</span>canonized_x<span class="Delimiter">)</span> || is_mu_exclusive_container<span class="Delimiter">(</span>canonized_x<span class="Delimiter">))</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;need to read old value of '&quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>canonized_x<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;' to figure out what refcounts to decrement&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Comment">// read from canonized_x but without canonizing again</span> <span class="Comment">// todo: inline without running canonize all over again</span> reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> tmp = canonized_x<span class="Delimiter">;</span> tmp<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;string<span class="Delimiter">,</span> string_tree*&gt;<span class="Delimiter">(</span><span class="Constant">&quot;raw&quot;</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> vector&lt;<span class="Normal">double</span>&gt; data = read_memory<span class="Delimiter">(</span>tmp<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;done reading old value of '&quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>canonized_x<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Normal">const</span> container_metadata&amp; metadata = get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> canonized_x<span class="Delimiter">.</span>type<span class="Delimiter">);</span> <span class="Normal">for</span> <span class="Delimiter">(</span>map&lt;set&lt;tag_condition_info&gt;<span class="Delimiter">,</span> set&lt;address_element_info&gt; &gt;::const_iterator p = metadata<span class="Delimiter">.</span>address<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != metadata<span class="Delimiter">.</span>address<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>!all_match<span class="Delimiter">(</span>data<span class="Delimiter">,</span> p<span class="Delimiter">-&gt;</span>first<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Normal">for</span> <span class="Delimiter">(</span>set&lt;address_element_info&gt;::const_iterator info = p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> info != p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++info<span class="Delimiter">)</span> decrement_refcount<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> canonized_x<span class="Delimiter">.</span>value + info<span class="Delimiter">-&gt;</span>offset<span class="Delimiter">),</span> info<span class="Delimiter">-&gt;</span>payload_type<span class="Delimiter">,</span> size_of<span class="Delimiter">(</span>info<span class="Delimiter">-&gt;</span>payload_type<span class="Delimiter">)</span>+<span class="Comment">/*</span><span class="Comment">refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> <span class="Normal">bool</span> all_match<span class="Delimiter">(</span><span class="Normal">const</span> vector&lt;<span class="Normal">double</span>&gt;&amp; data<span class="Delimiter">,</span> <span class="Normal">const</span> set&lt;tag_condition_info&gt;&amp; conditions<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">for</span> <span class="Delimiter">(</span>set&lt;tag_condition_info&gt;::const_iterator p = conditions<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != conditions<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>data<span class="Delimiter">.</span>at<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>offset<span class="Delimiter">)</span> != p<span class="Delimiter">-&gt;</span>tag<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario refcounts_put_container)</span> container foo [ <span class="Normal">a</span>:bar <span class="Comment"># contains an address</span> ] container bar [ <span class="Normal">x</span>:address:num ] def main [ <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">2</span>:bar<span class="Special"> &lt;- </span>merge <span class="Constant">1</span>:address:num <span class="Constant">3</span>:address:foo<span class="Special"> &lt;- </span><span class="Normal">new</span> foo:type *<span class="Constant">3</span>:address:foo<span class="Special"> &lt;- </span>put *<span class="Constant">3</span>:address:foo<span class="Delimiter">,</span> a:offset<span class="Delimiter">,</span> <span class="Constant">2</span>:bar ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="traceContains">+run: {2: &quot;bar&quot;} &lt;- merge {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="traceContains">+run: {3: (&quot;address&quot; &quot;foo&quot;), &quot;lookup&quot;: ()} &lt;- put {3: (&quot;address&quot; &quot;foo&quot;), &quot;lookup&quot;: ()}, {a: &quot;offset&quot;}, {2: &quot;bar&quot;}</span> <span class="Comment"># put increments refcount inside container</span> <span class="traceContains">+mem: incrementing refcount of 1000: 2 -&gt; 3</span> <span class="Delimiter">:(scenario refcounts_put_index_array)</span> container bar [ <span class="Normal">x</span>:address:num ] def main [ <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">2</span>:bar<span class="Special"> &lt;- </span>merge <span class="Constant">1</span>:address:num <span class="Constant">3</span>:address:array:bar<span class="Special"> &lt;- </span><span class="Normal">new</span> bar:type<span class="Delimiter">,</span> <span class="Constant">3</span> *<span class="Constant">3</span>:address:array:bar<span class="Special"> &lt;- </span>put-index *<span class="Constant">3</span>:address:array:bar<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">2</span>:bar ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="traceContains">+run: {2: &quot;bar&quot;} &lt;- merge {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="traceContains">+run: {3: (&quot;address&quot; &quot;array&quot; &quot;bar&quot;), &quot;lookup&quot;: ()} &lt;- put-index {3: (&quot;address&quot; &quot;array&quot; &quot;bar&quot;), &quot;lookup&quot;: ()}, {0: &quot;literal&quot;}, {2: &quot;bar&quot;}</span> <span class="Comment"># put-index increments refcount inside container</span> <span class="traceContains">+mem: incrementing refcount of 1000: 2 -&gt; 3</span> <span class="Delimiter">:(scenario refcounts_maybe_convert_container)</span> exclusive-container foo [ <span class="Normal">a</span>:num <span class="Normal">b</span>:bar <span class="Comment"># contains an address</span> ] container bar [ <span class="Normal">x</span>:address:num ] def main [ <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">2</span>:bar<span class="Special"> &lt;- </span>merge <span class="Constant">1</span>:address:num <span class="Constant">3</span>:foo<span class="Special"> &lt;- </span>merge <span class="Constant">1</span>/b<span class="Delimiter">,</span> <span class="Constant">2</span>:bar <span class="Constant">5</span>:bar<span class="Delimiter">,</span> <span class="Constant">6</span>:<span class="Normal">bool</span><span class="Special"> &lt;- </span>maybe-convert <span class="Constant">3</span>:foo<span class="Delimiter">,</span> <span class="Constant">1</span>:variant/b ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="traceContains">+run: {2: &quot;bar&quot;} &lt;- merge {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="traceContains">+run: {3: &quot;foo&quot;} &lt;- merge {1: &quot;literal&quot;, &quot;b&quot;: ()}, {2: &quot;bar&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 2 -&gt; 3</span> <span class="traceContains">+run: {5: &quot;bar&quot;}, {6: &quot;boolean&quot;} &lt;- maybe-convert {3: &quot;foo&quot;}, {1: &quot;variant&quot;, &quot;b&quot;: ()}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 3 -&gt; 4</span> <span class="Delimiter">:(scenario refcounts_copy_doubly_nested)</span> container foo [ <span class="Normal">a</span>:bar <span class="Comment"># no addresses</span> <span class="Normal">b</span>:curr <span class="Comment"># contains addresses</span> ] container bar [ <span class="Normal">x</span>:num <span class="Normal">y</span>:num ] container curr [ <span class="Normal">x</span>:num <span class="Normal">y</span>:address:num <span class="Comment"># address inside container inside container</span> ] def main [ <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">2</span>:address:curr<span class="Special"> &lt;- </span><span class="Normal">new</span> curr:type *<span class="Constant">2</span>:address:curr<span class="Special"> &lt;- </span>put *<span class="Constant">2</span>:address:curr<span class="Delimiter">,</span> <span class="Constant">1</span>:offset/y<span class="Delimiter">,</span> <span class="Constant">1</span>:address:num <span class="Constant">3</span>:address:foo<span class="Special"> &lt;- </span><span class="Normal">new</span> foo:type *<span class="Constant">3</span>:address:foo<span class="Special"> &lt;- </span>put *<span class="Constant">3</span>:address:foo<span class="Delimiter">,</span> <span class="Constant">1</span>:offset/b<span class="Delimiter">,</span> *<span class="Constant">2</span>:address:curr <span class="Constant">4</span>:foo<span class="Special"> &lt;- </span>copy *<span class="Constant">3</span>:address:foo ] <span class="traceContains">+transform: compute address offsets for container foo</span> <span class="traceContains">+transform: checking container foo, element 1</span> <span class="traceContains">+transform: address at offset 3</span> <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="Comment"># storing an address in a container updates its refcount</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;curr&quot;), &quot;lookup&quot;: ()} &lt;- put {2: (&quot;address&quot; &quot;curr&quot;), &quot;lookup&quot;: ()}, {1: &quot;offset&quot;, &quot;y&quot;: ()}, {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="Comment"># storing a container in a container updates refcounts of any contained addresses</span> <span class="traceContains">+run: {3: (&quot;address&quot; &quot;foo&quot;), &quot;lookup&quot;: ()} &lt;- put {3: (&quot;address&quot; &quot;foo&quot;), &quot;lookup&quot;: ()}, {1: &quot;offset&quot;, &quot;b&quot;: ()}, {2: (&quot;address&quot; &quot;curr&quot;), &quot;lookup&quot;: ()}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 2 -&gt; 3</span> <span class="Comment"># copying a container containing a container containing an address updates refcount</span> <span class="traceContains">+run: {4: &quot;foo&quot;} &lt;- copy {3: (&quot;address&quot; &quot;foo&quot;), &quot;lookup&quot;: ()}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 3 -&gt; 4</span> <span class="Delimiter">:(scenario refcounts_copy_exclusive_container_within_container)</span> container foo [ <span class="Normal">a</span>:num <span class="Normal">b</span>:bar ] exclusive-container bar [ <span class="Normal">x</span>:num <span class="Normal">y</span>:num <span class="Normal">z</span>:address:num ] def main [ <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">2</span>:bar<span class="Special"> &lt;- </span>merge <span class="Constant">0</span>/x<span class="Delimiter">,</span> <span class="Constant">34</span> <span class="Constant">3</span>:foo<span class="Special"> &lt;- </span>merge <span class="Constant">12</span><span class="Delimiter">,</span> <span class="Constant">2</span>:bar <span class="Constant">5</span>:bar<span class="Special"> &lt;- </span>merge <span class="Constant">1</span>/y<span class="Delimiter">,</span> <span class="Constant">35</span> <span class="Constant">6</span>:foo<span class="Special"> &lt;- </span>merge <span class="Constant">13</span><span class="Delimiter">,</span> <span class="Constant">5</span>:bar <span class="Constant">8</span>:bar<span class="Special"> &lt;- </span>merge <span class="Constant">2</span>/z<span class="Delimiter">,</span> <span class="Constant">1</span>:address:num <span class="Constant">9</span>:foo<span class="Special"> &lt;- </span>merge <span class="Constant">14</span><span class="Delimiter">,</span> <span class="Constant">8</span>:bar <span class="Constant">11</span>:foo<span class="Special"> &lt;- </span>copy <span class="Constant">9</span>:foo ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="Comment"># no change while merging items of other types</span> <span class="traceContains">+run: {8: &quot;bar&quot;} &lt;- merge {2: &quot;literal&quot;, &quot;z&quot;: ()}, {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="traceContains">+run: {9: &quot;foo&quot;} &lt;- merge {14: &quot;literal&quot;}, {8: &quot;bar&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 2 -&gt; 3</span> <span class="traceContains">+run: {11: &quot;foo&quot;} &lt;- copy {9: &quot;foo&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 3 -&gt; 4</span> <span class="Delimiter">:(scenario refcounts_copy_container_within_exclusive_container)</span> exclusive-container foo [ <span class="Normal">a</span>:num <span class="Normal">b</span>:bar ] container bar [ <span class="Normal">x</span>:num <span class="Normal">y</span>:num <span class="Normal">z</span>:address:num ] def main [ <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">2</span>:foo<span class="Special"> &lt;- </span>merge <span class="Constant">0</span>/a<span class="Delimiter">,</span> <span class="Constant">34</span> <span class="Constant">6</span>:foo<span class="Special"> &lt;- </span>merge <span class="Constant">0</span>/a<span class="Delimiter">,</span> <span class="Constant">35</span> <span class="Constant">10</span>:bar<span class="Special"> &lt;- </span>merge <span class="Constant">2</span>/x<span class="Delimiter">,</span> <span class="Constant">15</span>/y<span class="Delimiter">,</span> <span class="Constant">1</span>:address:num <span class="Constant">13</span>:foo<span class="Special"> &lt;- </span>merge <span class="Constant">1</span>/b<span class="Delimiter">,</span> <span class="Constant">10</span>:bar <span class="Constant">17</span>:foo<span class="Special"> &lt;- </span>copy <span class="Constant">13</span>:foo ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="Comment"># no change while merging items of other types</span> <span class="traceContains">+run: {10: &quot;bar&quot;} &lt;- merge {2: &quot;literal&quot;, &quot;x&quot;: ()}, {15: &quot;literal&quot;, &quot;y&quot;: ()}, {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="traceContains">+run: {13: &quot;foo&quot;} &lt;- merge {1: &quot;literal&quot;, &quot;b&quot;: ()}, {10: &quot;bar&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 2 -&gt; 3</span> <span class="traceContains">+run: {17: &quot;foo&quot;} &lt;- copy {13: &quot;foo&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 3 -&gt; 4</span> <span class="Delimiter">:(scenario refcounts_copy_exclusive_container_within_exclusive_container)</span> exclusive-container foo [ <span class="Normal">a</span>:num <span class="Normal">b</span>:bar ] exclusive-container bar [ <span class="Normal">x</span>:num <span class="Normal">y</span>:address:num ] def main [ <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">10</span>:foo<span class="Special"> &lt;- </span>merge <span class="Constant">1</span>/b<span class="Delimiter">,</span> <span class="Constant">1</span>/y<span class="Delimiter">,</span> <span class="Constant">1</span>:address:num <span class="Constant">20</span>:foo<span class="Special"> &lt;- </span>copy <span class="Constant">10</span>:foo ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="Comment"># no change while merging items of other types</span> <span class="traceContains">+run: {10: &quot;foo&quot;} &lt;- merge {1: &quot;literal&quot;, &quot;b&quot;: ()}, {1: &quot;literal&quot;, &quot;y&quot;: ()}, {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="traceContains">+run: {20: &quot;foo&quot;} &lt;- copy {10: &quot;foo&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 2 -&gt; 3</span> <span class="Delimiter">:(scenario refcounts_copy_array_within_container)</span> container foo [ <span class="Normal">x</span>:address:array:num ] def main [ <span class="Constant">1</span>:address:array:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">3</span> <span class="Constant">2</span>:foo<span class="Special"> &lt;- </span>merge <span class="Constant">1</span>:address:array:num <span class="Constant">3</span>:address:array:num<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">5</span> <span class="Constant">2</span>:foo<span class="Special"> &lt;- </span>merge <span class="Constant">3</span>:address:array:num ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;array&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}, {3: &quot;literal&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="traceContains">+run: {2: &quot;foo&quot;} &lt;- merge {1: (&quot;address&quot; &quot;array&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="traceContains">+run: {2: &quot;foo&quot;} &lt;- merge {3: (&quot;address&quot; &quot;array&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: decrementing refcount of 1000: 2 -&gt; 1</span> <span class="Delimiter">:(scenario refcounts_handle_exclusive_containers_with_different_tags)</span> container foo1 [ <span class="Normal">x</span>:address:num <span class="Normal">y</span>:num ] container foo2 [ <span class="Normal">x</span>:num <span class="Normal">y</span>:address:num ] exclusive-container bar [ <span class="Normal">a</span>:foo1 <span class="Normal">b</span>:foo2 ] def main [ <span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span>copy <span class="Constant">12000</span>/unsafe <span class="Comment"># pretend allocation</span> *<span class="Constant">1</span>:address:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span> <span class="Constant">2</span>:bar<span class="Special"> &lt;- </span>merge <span class="Constant">0</span>/foo1<span class="Delimiter">,</span> <span class="Constant">1</span>:address:num<span class="Delimiter">,</span> <span class="Constant">97</span> <span class="Constant">5</span>:address:num<span class="Special"> &lt;- </span>copy <span class="Constant">13000</span>/unsafe <span class="Comment"># pretend allocation</span> *<span class="Constant">5</span>:address:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span> <span class="Constant">6</span>:bar<span class="Special"> &lt;- </span>merge <span class="Constant">1</span>/foo2<span class="Delimiter">,</span> <span class="Constant">98</span><span class="Delimiter">,</span> <span class="Constant">5</span>:address:num <span class="Constant">2</span>:bar<span class="Special"> &lt;- </span>copy <span class="Constant">6</span>:bar ] <span class="traceContains">+run: {2: &quot;bar&quot;} &lt;- merge {0: &quot;literal&quot;, &quot;foo1&quot;: ()}, {1: (&quot;address&quot; &quot;number&quot;)}, {97: &quot;literal&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 12000: 1 -&gt; 2</span> <span class="traceContains">+run: {6: &quot;bar&quot;} &lt;- merge {1: &quot;literal&quot;, &quot;foo2&quot;: ()}, {98: &quot;literal&quot;}, {5: (&quot;address&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 13000: 1 -&gt; 2</span> <span class="traceContains">+run: {2: &quot;bar&quot;} &lt;- copy {6: &quot;bar&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 13000: 2 -&gt; 3</span> <span class="traceContains">+mem: decrementing refcount of 12000: 2 -&gt; 1</span> <span class="Delimiter">:(code)</span> <span class="Normal">bool</span> is_mu_container<span class="Delimiter">(</span><span class="Normal">const</span> reagent&amp; r<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Identifier">return</span> is_mu_container<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">bool</span> is_mu_container<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// End is_mu_container(type) Special-cases</span> <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> type_info&amp; info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span> <span class="Identifier">return</span> info<span class="Delimiter">.</span>kind == CONTAINER<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">bool</span> is_mu_exclusive_container<span class="Delimiter">(</span><span class="Normal">const</span> reagent&amp; r<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Identifier">return</span> is_mu_exclusive_container<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">bool</span> is_mu_exclusive_container<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// End is_mu_exclusive_container(type) Special-cases</span> <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> type_info&amp; info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span> <span class="Identifier">return</span> info<span class="Delimiter">.</span>kind == EXCLUSIVE_CONTAINER<span class="Delimiter">;</span> <span class="Delimiter">}</span> </pre> </body> </html> <!-- vim: set foldmethod=manual : -->