1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/core-module/24-sf.html
2019-04-22 15:42:10 +01:00

489 lines
55 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>24/pb</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<!--Weave of '24/sf' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">core</a></li><li><a href="index.html#24">Chapter 24: Compilation Context</a></li><li><b>Stack Frames</b></li></ul><p class="purpose">When Inform compiles phrase invocations, or implied forms of these such as text substitutions, it does so in the context of a "stack frame". This provides for local "let" values, manages loop blocks, and in general looks after any information shared between a whole sequence of invocations.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP5">&#167;5. Creation</a></li><li><a href="#SP8">&#167;8. The current stack frame</a></li><li><a href="#SP9">&#167;9. Kinds</a></li><li><a href="#SP11">&#167;11. Stacked variables</a></li><li><a href="#SP12">&#167;12. Past tense</a></li><li><a href="#SP13">&#167;13. Logging</a></li><li><a href="#SP14">&#167;14. Formal parameter allocation</a></li><li><a href="#SP15">&#167;15. Pointer value allocation</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Definitions. </b></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>As we've seen, each phrase has its own stack frame, which is a structure
inside the <code class="display"><span class="extract">phrase</span></code> structure. But they can also exist independently, for
other occasions when compilation occurs. They keep track of which variables
are visible, and also of the current values of the kind variables A to Z,
if any, and the consequent return kind.
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">ph_stack_frame</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">locals_slate</span><span class="plain"> </span><span class="identifier">local_value_variables</span><span class="plain">; </span> <span class="comment">those in scope here</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">stacked_variable_owner_list</span><span class="plain"> *</span><span class="identifier">local_stvol</span><span class="plain">; </span> <span class="comment">those in scope here</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">pointer_allocation</span><span class="plain"> *</span><span class="identifier">allocated_pointers</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_formal_parameters_needed</span><span class="plain">; </span> <span class="comment">usually 0, unless there are ambiguities</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_returned</span><span class="plain">; </span> <span class="comment">or <code class="display"><span class="extract">NULL</span></code> for no return value</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">kind</span><span class="plain"> **</span><span class="identifier">local_kind_variables</span><span class="plain">; </span> <span class="comment">points to an array indexed 1 to 26</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">determines_past_conditions</span><span class="plain">; </span> <span class="comment">or rather, in the present, but for future use</span>
<span class="plain">} </span><span class="reserved">ph_stack_frame</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure ph_stack_frame is accessed in 24/lv, 26/rt and here.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Stack frames are often made fleetingly and then thrown away, but sometimes
we need to make one and keep it around. For this, we have the ability to box
up a stack frame: by allocating an instance of the following structure, we
can have a permanently valid pointer to a unique new PHSF.
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">ph_stack_frame_box</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">ph_stack_frame</span><span class="plain"> </span><span class="identifier">boxed_phsf</span><span class="plain">;</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">ph_stack_frame_box</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure ph_stack_frame_box is private to this section.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>Within each stack frame is a linked list of notes about pointer values
for which memory allocation and deallocation will be needed:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">pointer_allocation</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">heap_allocation</span><span class="plain"> </span><span class="identifier">allocation</span><span class="plain">; </span> <span class="comment">needed to compile a function call returning a pointer to a new value</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">local_reference_code</span><span class="plain">; </span> <span class="comment">an I6 lvalue for the storage holding the pointer</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">escaped_local_reference_code</span><span class="plain">; </span> <span class="comment">the same, but suitable for schema use</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">schema_for_promotion</span><span class="plain">; </span> <span class="comment">an I6 schema for promoting this value</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">offset_index</span><span class="plain">; </span> <span class="comment">start of small block wrt current stack frame</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">offset_past</span><span class="plain">; </span> <span class="comment">just past the end of the small block</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">pointer_allocation</span><span class="plain"> *</span><span class="identifier">next_in_frame</span><span class="plain">; </span> <span class="comment">within the linked list</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">pointer_allocation</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure pointer_allocation is accessed in 26/rt and here.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Creation. </b>A completely black stack frame...
</p>
<pre class="display">
<span class="reserved">ph_stack_frame</span><span class="plain"> </span><span class="functiontext">Frames::new</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">ph_stack_frame</span><span class="plain"> </span><span class="identifier">phsf</span><span class="plain">;</span>
<span class="identifier">phsf</span><span class="element">.local_value_variables</span><span class="plain"> = </span><span class="functiontext">LocalVariables::blank_slate</span><span class="plain">();</span>
<span class="identifier">phsf</span><span class="element">.local_kind_variables</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">phsf</span><span class="element">.local_stvol</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">phsf</span><span class="element">.determines_past_conditions</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">phsf</span><span class="element">.allocated_pointers</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">phsf</span><span class="element">.kind_returned</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">phsf</span><span class="element">.no_formal_parameters_needed</span><span class="plain"> = 0;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">phsf</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Frames::new is used in <a href="#SP6">&#167;6</a>, 17/ts (<a href="17-ts.html#SP5">&#167;5</a>), 22/ph (<a href="22-ph.html#SP6_5">&#167;6.5</a>).</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>...can be useful all by itself. The following is used to make a temporary
stack frame suitable for "nonphrasal" compilation, that is, for when Inform
wants to compile an I6 routine for some purpose other than to define a phrase.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">nonphrasal_stack_frame_is_current</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">ph_stack_frame</span><span class="plain"> </span><span class="identifier">nonphrasal_stack_frame</span><span class="plain">;</span>
<span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="functiontext">Frames::new_nonphrasal</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nonphrasal_stack_frame_is_current</span><span class="plain">)</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"can't nest nonphrasal stack frames"</span><span class="plain">);</span>
<span class="identifier">nonphrasal_stack_frame</span><span class="plain"> = </span><span class="functiontext">Frames::new</span><span class="plain">();</span>
<span class="identifier">nonphrasal_stack_frame_is_current</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="functiontext">Frames::make_current</span><span class="plain">(&amp;</span><span class="identifier">nonphrasal_stack_frame</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> &amp;</span><span class="identifier">nonphrasal_stack_frame</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::remove_nonphrase_stack_frame</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">nonphrasal_stack_frame</span><span class="plain"> = </span><span class="functiontext">Frames::new</span><span class="plain">(); </span> <span class="comment">to prevent accidental lucky misuse</span>
<span class="identifier">nonphrasal_stack_frame_is_current</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="functiontext">Frames::remove_current</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Frames::new_nonphrasal is used in 26/rt (<a href="26-rt.html#SP3_1">&#167;3.1</a>).</p>
<p class="endnote">The function Frames::remove_nonphrase_stack_frame is used in 22/pu (<a href="22-pu.html#SP20_1_1">&#167;20.1.1</a>), 26/rt (<a href="26-rt.html#SP4">&#167;4</a>).</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>Another way to get hold of a PHSF is to request a boxed one, as noted above:
</p>
<pre class="display">
<span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="functiontext">Frames::boxed_frame</span><span class="plain">(</span><span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">phsf</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phsf</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">ph_stack_frame_box</span><span class="plain"> *</span><span class="identifier">phsfb</span><span class="plain">;</span>
<span class="identifier">phsfb</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">ph_stack_frame_box</span><span class="plain">);</span>
<span class="identifier">phsfb</span><span class="plain">-</span><span class="element">&gt;boxed_phsf</span><span class="plain"> = *</span><span class="identifier">phsf</span><span class="plain">;</span>
<span class="functiontext">LocalVariables::deep_copy_locals_slate</span><span class="plain">(&amp;(</span><span class="identifier">phsfb</span><span class="plain">-</span><span class="element">&gt;boxed_phsf.local_value_variables</span><span class="plain">),</span>
<span class="plain">&amp;(</span><span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;local_value_variables</span><span class="plain">));</span>
<span class="reserved">return</span><span class="plain"> &amp;(</span><span class="identifier">phsfb</span><span class="plain">-</span><span class="element">&gt;boxed_phsf</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Frames::boxed_frame is used in 17/ts (<a href="17-ts.html#SP5">&#167;5</a>, <a href="17-ts.html#SP8">&#167;8</a>), 17/rs (<a href="17-rs.html#SP5">&#167;5</a>, <a href="17-rs.html#SP12_1_1">&#167;12.1.1</a>).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. The current stack frame. </b>At any given time, a single stack frame is valid for local variable names
and phrase option names used as conditions. It will be the nonphrasal one
if that's active, and otherwise must be set as needed.
</p>
<pre class="display">
<span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">current_frame</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="functiontext">Frames::current_stack_frame</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">current_frame</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::make_current</span><span class="plain">(</span><span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">phsf</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phsf</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"can't select null stack frame"</span><span class="plain">);</span>
<span class="identifier">current_frame</span><span class="plain"> = </span><span class="identifier">phsf</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::remove_current</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">current_frame</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Frames::current_stack_frame is used in <a href="#SP9">&#167;9</a>, <a href="#SP10">&#167;10</a>, <a href="#SP11">&#167;11</a>, <a href="#SP12">&#167;12</a>, <a href="#SP14">&#167;14</a>, <a href="#SP15">&#167;15</a>, 4/am (<a href="4-am.html#SP34_2">&#167;34.2</a>, <a href="4-am.html#SP34_2_1">&#167;34.2.1</a>), 6/rlt (<a href="6-rlt.html#SP30">&#167;30</a>), 10/cad (<a href="10-cad.html#SP19_2">&#167;19.2</a>), 10/teav (<a href="10-teav.html#SP15">&#167;15</a>, <a href="10-teav.html#SP16">&#167;16</a>), 15/ma (<a href="15-ma.html#SP13">&#167;13</a>), 17/ts (<a href="17-ts.html#SP5">&#167;5</a>, <a href="17-ts.html#SP8">&#167;8</a>, <a href="17-ts.html#SP9">&#167;9</a>, <a href="17-ts.html#SP11">&#167;11</a>), 17/rs (<a href="17-rs.html#SP12_1_1">&#167;12.1.1</a>), 20/eq (<a href="20-eq.html#SP47_3">&#167;47.3</a>), 22/pu (<a href="22-pu.html#SP20_1_1">&#167;20.1.1</a>), 24/lv (<a href="24-lv.html#SP10">&#167;10</a>, <a href="24-lv.html#SP11">&#167;11</a>, <a href="24-lv.html#SP20">&#167;20</a>, <a href="24-lv.html#SP21">&#167;21</a>, <a href="24-lv.html#SP22">&#167;22</a>, <a href="24-lv.html#SP23">&#167;23</a>, <a href="24-lv.html#SP26">&#167;26</a>, <a href="24-lv.html#SP27">&#167;27</a>, <a href="24-lv.html#SP30">&#167;30</a>, <a href="24-lv.html#SP31">&#167;31</a>, <a href="24-lv.html#SP33">&#167;33</a>, <a href="24-lv.html#SP33_3">&#167;33.3</a>, <a href="24-lv.html#SP41">&#167;41</a>, <a href="24-lv.html#SP42">&#167;42</a>), 24/pb (<a href="24-pb.html#SP8">&#167;8</a>, <a href="24-pb.html#SP18">&#167;18</a>, <a href="24-pb.html#SP19">&#167;19</a>).</p>
<p class="endnote">The function Frames::make_current is used in <a href="#SP6">&#167;6</a>, 22/cs (<a href="22-cs.html#SP7">&#167;7</a>), 22/prcd (<a href="22-prcd.html#SP9">&#167;9</a>), 25/cp (<a href="25-cp.html#SP3_2">&#167;3.2</a>), 26/rt (<a href="26-rt.html#SP3_1">&#167;3.1</a>).</p>
<p class="endnote">The function Frames::remove_current is used in <a href="#SP6">&#167;6</a>, 22/cs (<a href="22-cs.html#SP7">&#167;7</a>), 26/rt (<a href="26-rt.html#SP4">&#167;4</a>).</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. Kinds. </b>The kind of value we expect to return from within this stack frame, if any.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::set_kind_returned</span><span class="plain">(</span><span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">phsf</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;kind_returned</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">Frames::get_kind_returned</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">phsf</span><span class="plain"> = </span><span class="functiontext">Frames::current_stack_frame</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phsf</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;kind_returned</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Frames::set_kind_returned is used in 22/ptd (<a href="22-ptd.html#SP20">&#167;20</a>).</p>
<p class="endnote">The function Frames::get_kind_returned is used in 25/cii (<a href="25-cii.html#SP3_1_1_4_7_1">&#167;3.1.1.4.7.1</a>, <a href="25-cii.html#SP7">&#167;7</a>), 25/cp (<a href="25-cp.html#SP3_3_1">&#167;3.3.1</a>).</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>And the values of the kind variables A to Z:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">KIND_VARIABLE_FROM_CONTEXT</span><span class="plain"> </span><span class="functiontext">Frames::get_kind_variable</span>
</pre>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::set_kind_variables</span><span class="plain">(</span><span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">phsf</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> **</span><span class="identifier">vars</span><span class="plain">) {</span>
<span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;local_kind_variables</span><span class="plain"> = </span><span class="identifier">vars</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">Frames::get_kind_variable</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">) {</span>
<span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">phsf</span><span class="plain"> = </span><span class="functiontext">Frames::current_stack_frame</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">phsf</span><span class="plain">) &amp;&amp; (</span><span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;local_kind_variables</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;local_kind_variables</span><span class="plain">[</span><span class="identifier">N</span><span class="plain">];</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">kind</span><span class="plain"> **</span><span class="functiontext">Frames::temporarily_set_kvs</span><span class="plain">(</span><span class="identifier">kind</span><span class="plain"> **</span><span class="identifier">vars</span><span class="plain">) {</span>
<span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">phsf</span><span class="plain"> = </span><span class="functiontext">Frames::current_stack_frame</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phsf</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> **</span><span class="identifier">prev</span><span class="plain"> = </span><span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;local_kind_variables</span><span class="plain">;</span>
<span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;local_kind_variables</span><span class="plain"> = </span><span class="identifier">vars</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">prev</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Frames::set_kind_variables is used in 25/cp (<a href="25-cp.html#SP3_2">&#167;3.2</a>).</p>
<p class="endnote">The function Frames::get_kind_variable is used in 25/cii (<a href="25-cii.html#SP3_1_1_1">&#167;3.1.1.1</a>).</p>
<p class="endnote">The function Frames::temporarily_set_kvs is used in 25/cii (<a href="25-cii.html#SP3_1_1">&#167;3.1.1</a>, <a href="25-cii.html#SP7">&#167;7</a>).</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. Stacked variables. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::set_stvol</span><span class="plain">(</span><span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">phsf</span><span class="plain">, </span><span class="reserved">stacked_variable_owner_list</span><span class="plain"> *</span><span class="identifier">stvol</span><span class="plain">) {</span>
<span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;local_stvol</span><span class="plain"> = </span><span class="identifier">stvol</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">stacked_variable_owner_list</span><span class="plain"> *</span><span class="functiontext">Frames::get_stvol</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">phsf</span><span class="plain"> = </span><span class="functiontext">Frames::current_stack_frame</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phsf</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;local_stvol</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Frames::set_stvol is used in 22/pu (<a href="22-pu.html#SP20_1_1">&#167;20.1.1</a>), 22/prcd (<a href="22-prcd.html#SP9">&#167;9</a>), 25/cp (<a href="25-cp.html#SP3_2">&#167;3.2</a>).</p>
<p class="endnote">The function Frames::get_stvol is used in 10/teav (<a href="10-teav.html#SP16">&#167;16</a>).</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. Past tense. </b>All we do here is to make a note if anything compiled in this context makes
reference to the past.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::determines_the_past</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">phsf</span><span class="plain"> = </span><span class="functiontext">Frames::current_stack_frame</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phsf</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span>
<span class="string">"tried to determine past where no stack frame exists"</span><span class="plain">);</span>
<span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;determines_past_conditions</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">LOCAL_VARIABLES</span><span class="plain">, </span><span class="string">"Stack frame determines past\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Frames::used_for_past_tense</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">phsf</span><span class="plain"> = </span><span class="functiontext">Frames::current_stack_frame</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phsf</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;determines_past_conditions</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Frames::determines_the_past is used in 24/ch (<a href="24-ch.html#SP7">&#167;7</a>).</p>
<p class="endnote">The function Frames::used_for_past_tense is used in 12/ca (<a href="12-ca.html#SP5_1_2">&#167;5.1.2</a>).</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. Logging. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::log</span><span class="plain">(</span><span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">phsf</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phsf</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;null stack frame&gt;\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Stack frame at %08x: it:%s, dpc:%s\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">phsf</span><span class="plain">,</span>
<span class="plain">(</span><span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;local_value_variables.it_variable_exists</span><span class="plain">)?</span><span class="string">"yes"</span><span class="plain">:</span><span class="string">"no"</span><span class="plain">,</span>
<span class="plain">(</span><span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;determines_past_conditions</span><span class="plain">)?</span><span class="string">"yes"</span><span class="plain">:</span><span class="string">"no"</span><span class="plain">);</span>
<span class="reserved">local_variable</span><span class="plain"> *</span><span class="identifier">lvar</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">lvar</span><span class="plain"> = </span><span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;local_value_variables.local_variable_allocation</span><span class="plain">; </span><span class="identifier">lvar</span><span class="plain">; </span><span class="identifier">lvar</span><span class="plain"> = </span><span class="identifier">lvar</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">lvar</span><span class="plain">-</span><span class="element">&gt;lv_purpose</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">LET_VALUE_LV</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Let/loop value: "</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">TOKEN_CALL_PARAMETER_LV</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Call value: "</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INTERNAL_USE_LV</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Internal use: "</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Other: "</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%~L: "</span><span class="plain">, </span><span class="identifier">lvar</span><span class="plain">);</span>
<span class="functiontext">LocalVariables::log</span><span class="plain">(</span><span class="identifier">lvar</span><span class="plain">); </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Frames::log is used in 17/ts (<a href="17-ts.html#SP9">&#167;9</a>).</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. Formal parameter allocation. </b>Some stack frames need access to additional variables to handle run-time
invocation ambiguities, and this is how they're requested:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::need_at_least_this_many_formals</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">) {</span>
<span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">phsf</span><span class="plain"> = </span><span class="functiontext">Frames::current_stack_frame</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phsf</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"requested formal parameters outside all stack frames"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> &gt; </span><span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;no_formal_parameters_needed</span><span class="plain">)</span>
<span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;no_formal_parameters_needed</span><span class="plain"> = </span><span class="identifier">N</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Frames::need_at_least_this_many_formals is used in 25/ci (<a href="25-ci.html#SP3_2">&#167;3.2</a>).</p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. Pointer value allocation. </b>Values such as lists, which have to stored in whole blocks rather than single
words of memory, are sometimes called pointer values because all we can
immediately handle is a pointer to the block. When these arise in the
compilation of a routine, we have to make a note of this, because special
code will be needed to allocate and deallocate the memory storing the block.
The following is the routine called to make this note.
</p>
<pre class="display">
<span class="reserved">pointer_allocation</span><span class="plain"> *</span><span class="functiontext">Frames::add_allocation</span><span class="plain">(</span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">proto</span><span class="plain">) {</span>
<span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">phsf</span><span class="plain"> = </span><span class="functiontext">Frames::current_stack_frame</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phsf</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Tried to allocate: $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to allocate block kind outside all stack frames"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">pointer_allocation</span><span class="plain"> *</span><span class="identifier">pall</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">pointer_allocation</span><span class="plain">);</span>
<span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;next_in_frame</span><span class="plain"> = </span><span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;allocated_pointers</span><span class="plain">;</span>
<span class="identifier">phsf</span><span class="plain">-</span><span class="element">&gt;allocated_pointers</span><span class="plain"> = </span><span class="identifier">pall</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;next_in_frame</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;offset_index</span><span class="plain"> = 0;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;offset_index</span><span class="plain"> = </span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;next_in_frame</span><span class="plain">-</span><span class="element">&gt;offset_past</span><span class="plain">;</span>
<span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;offset_past</span><span class="plain"> = </span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;offset_index</span><span class="plain"> + </span><span class="identifier">Kinds::Behaviour::get_small_block_size</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Work out heap allocation code for this pointer value</span> <span class="cwebmacronumber">15.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Work out local reference code for this pointer value</span> <span class="cwebmacronumber">15.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Work out promotion schema for this pointer value</span> <span class="cwebmacronumber">15.3</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">pall</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::compile_allocation</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">pointer_allocation</span><span class="plain"> *</span><span class="identifier">pall</span><span class="plain"> = </span><span class="functiontext">Frames::add_allocation</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="functiontext">Frames::pall_get_local_reference</span><span class="plain">(</span><span class="identifier">pall</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::emit_allocation</span><span class="plain">(</span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">pointer_allocation</span><span class="plain"> *</span><span class="identifier">pall</span><span class="plain"> = </span><span class="functiontext">Frames::add_allocation</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="reserved">i6_schema</span><span class="plain"> *</span><span class="identifier">all_sch</span><span class="plain"> = </span><span class="functiontext">Calculus::Schemas::new</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;escaped_local_reference_code</span><span class="plain">);</span>
<span class="functiontext">Calculus::Schemas::emit_expand_from_terms</span><span class="plain">(</span><span class="identifier">all_sch</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Frames::add_allocation is used in 13/rsfk (<a href="13-rsfk.html#SP6">&#167;6</a>).</p>
<p class="endnote">The function Frames::compile_allocation is used in 13/rsfk (<a href="13-rsfk.html#SP7">&#167;7</a>).</p>
<p class="endnote">The function Frames::emit_allocation is used in 12/dtd (<a href="12-dtd.html#SP16">&#167;16</a>, <a href="12-dtd.html#SP17">&#167;17</a>), 13/rsfk (<a href="13-rsfk.html#SP7">&#167;7</a>), 14/cfs (<a href="14-cfs.html#SP7">&#167;7</a>), 17/ts (<a href="17-ts.html#SP8">&#167;8</a>), 25/ciac (<a href="25-ciac.html#SP2_1">&#167;2.1</a>), 25/cii (<a href="25-cii.html#SP1_2_1">&#167;1.2.1</a>, <a href="25-cii.html#SP3_2_1">&#167;3.2.1</a>).</p>
<p class="inwebparagraph"><a id="SP15_1"></a><b>&#167;15.1. </b>The following works out a call to <code class="display"><span class="extract">BlkValueCreate</span></code> which will return a
default value of the given kind.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Work out heap allocation code for this pointer value</span> <span class="cwebmacronumber">15.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;allocation</span><span class="plain"> = </span><span class="functiontext">Kinds::RunTime::make_heap_allocation</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, 0, </span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;offset_index</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_2"></a><b>&#167;15.2. </b>This is the storage used to hold the pointer. For each frame, we have
a subarray of short blocks, indexed by the offset.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Work out local reference code for this pointer value</span> <span class="cwebmacronumber">15.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;local_reference_code</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;escaped_local_reference_code</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;offset_index</span><span class="plain"> == 0) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;local_reference_code</span><span class="plain">, </span><span class="string">"I7SFRAME"</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;escaped_local_reference_code</span><span class="plain">, </span><span class="string">"I7SFRAME"</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;offset_index</span><span class="plain"> == 1) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;local_reference_code</span><span class="plain">, </span><span class="string">"(I7SFRAME+WORDSIZE)"</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;escaped_local_reference_code</span><span class="plain">, </span><span class="string">"(I7SFRAME+WORDSIZE)"</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;local_reference_code</span><span class="plain">, </span><span class="string">"(I7SFRAME+WORDSIZE*%d)"</span><span class="plain">, </span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;offset_index</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;escaped_local_reference_code</span><span class="plain">, </span><span class="string">"(I7SFRAME+WORDSIZE**%d)"</span><span class="plain">, </span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;offset_index</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_3"></a><b>&#167;15.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Work out promotion schema for this pointer value</span> <span class="cwebmacronumber">15.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;schema_for_promotion</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">proto</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">proto</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">proto</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == </span><span class="character">'*'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">proto</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1] == </span><span class="character">'#'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">proto</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+2] == </span><span class="character">'#'</span><span class="plain">)) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;schema_for_promotion</span><span class="plain">, </span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;escaped_local_reference_code</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain">+=2;</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;schema_for_promotion</span><span class="plain">, </span><span class="identifier">proto</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. </b></p>
<pre class="display">
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="functiontext">Frames::pall_get_local_reference</span><span class="plain">(</span><span class="reserved">pointer_allocation</span><span class="plain"> *</span><span class="identifier">pall</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;local_reference_code</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="functiontext">Frames::pall_get_expanded_schema</span><span class="plain">(</span><span class="reserved">pointer_allocation</span><span class="plain"> *</span><span class="identifier">pall</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">pall</span><span class="plain">-</span><span class="element">&gt;schema_for_promotion</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Frames::pall_get_local_reference is used in <a href="#SP15">&#167;15</a>.</p>
<p class="endnote">The function Frames::pall_get_expanded_schema is used in 13/rsfk (<a href="13-rsfk.html#SP6">&#167;6</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="24-pb.html">Back to 'Phrase Blocks'</a></li><li><a href="24-ch.html">Continue with 'Chronology'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>