1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-03 07:24:58 +03:00
inform7/docs/imperative-module/3-sf.html
2022-04-30 22:32:10 +01:00

524 lines
88 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Stack Frames</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body class="commentary-font">
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-assets/Inform.png" height=72">
</a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../indocn.html">indoc</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
<li><a href="../inrtpsn.html">inrtps</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=18> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="../../../inweb/index.html">inweb</a></li>
<li><a href="../../../intest/index.html">intest</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Stack Frames' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../inform7n.html">Inform7</a></li><li><a href="index.html">imperative</a></li><li><a href="index.html#3">Chapter 3: Functions</a></li><li><b>Stack Frames</b></li></ul></div>
<p class="purpose">When Inform compiles imperative code, it does so in the context of a "stack frame".</p>
<ul class="toc"><li><a href="3-sf.html#SP1">&#167;1. Introduction</a></li><li><a href="3-sf.html#SP6">&#167;6. Creation</a></li><li><a href="3-sf.html#SP7">&#167;7. Kinds</a></li><li><a href="3-sf.html#SP10">&#167;10. Shared variables</a></li><li><a href="3-sf.html#SP11">&#167;11. Past tense</a></li><li><a href="3-sf.html#SP12">&#167;12. Formal parameters</a></li><li><a href="3-sf.html#SP13">&#167;13. It</a></li><li><a href="3-sf.html#SP16">&#167;16. Local block values</a></li><li><a href="3-sf.html#SP22">&#167;22. Logging</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Introduction. </b>The term "stack frame" is traditional in computer science. The idea is that
there is a stack holding temporary data needed by the functions currently
running. Each function, as it begins, claims a "frame" of memory on the stack,
thus pushing the stack higher; when it ends, the memory in that frame is
given up. It can thus be used only for temporary data.
</p>
<p class="commentary">Our object code, Inter, is designed for use with virtual machines on which the
call stack is not directly addressable, so the term "stack frame" here is used
a little loosely. What we mean is: the collection of everything that is distinctive
about the function currently being compiled. In particular:
</p>
<ul class="items"><li>&#9679; its local variables;
</li><li>&#9679; what shared variables it can see;
</li><li>&#9679; what interpretations to place on the kind variables <span class="extract"><span class="extract-syntax">A</span></span> to <span class="extract"><span class="extract-syntax">Z</span></span>, if any;
</li><li>&#9679; what kind of value we should be returning, if anything.
</li></ul>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>Code can only be compiled "inside" a stack frame, and at any given time
(when code is being compiled, anyway) there is a "current" frame.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">current_frame</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="function-syntax">Frames::current_stack_frame</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Frames::current_stack_frame</span></span>:<br/><a href="3-sf.html#SP7">&#167;7</a>, <a href="3-sf.html#SP8">&#167;8</a>, <a href="3-sf.html#SP10">&#167;10</a>, <a href="3-sf.html#SP11">&#167;11</a>, <a href="3-sf.html#SP12">&#167;12</a>, <a href="3-sf.html#SP16">&#167;16</a><br/>Local Variable Slates - <a href="3-lvs.html#SP17">&#167;17</a><br/>Local Variables - <a href="3-lv.html#SP4">&#167;4</a>, <a href="3-lv.html#SP5">&#167;5</a>, <a href="3-lv.html#SP7">&#167;7</a>, <a href="3-lv.html#SP9">&#167;9</a>, <a href="3-lv.html#SP10">&#167;10</a>, <a href="3-lv.html#SP12">&#167;12</a>, <a href="3-lv.html#SP13">&#167;13</a>, <a href="3-lv.html#SP14">&#167;14</a>, <a href="3-lv.html#SP16">&#167;16</a>, <a href="3-lv.html#SP18">&#167;18</a>, <a href="3-lv.html#SP20">&#167;20</a><br/>Code Blocks - <a href="3-cb.html#SP7">&#167;7</a>, <a href="3-cb.html#SP17">&#167;17</a>, <a href="3-cb.html#SP18">&#167;18</a><br/>Compile Solutions to Equations - <a href="5-cste.html#SP3_3">&#167;3.3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">current_frame</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b>This must be imposed and removed manually:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::make_current</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">Frames::make_current</span></span>:<br/><a href="3-sf.html#SP4">&#167;4</a><br/>Functions - <a href="3-fnc.html#SP5">&#167;5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"can't select null stack frame"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_frame</span><span class="plain-syntax"> = </span><span class="identifier-syntax">frame</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::remove_current</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">Frames::remove_current</span></span>:<br/><a href="3-sf.html#SP4">&#167;4</a><br/>Functions - <a href="3-fnc.html#SP6">&#167;6</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_frame</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>There are three ways to get stack frames. First, every phrase or rule has
one of its own. Second, though, we will also need a stack frame in order to
compile the many functions which aren't directly corresponding to phrases or
rules at all. Such a frame is called "nonphrasal":
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonphrasal_stack_frame_is_current</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonphrasal_stack_frame</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="function-syntax">Frames::new_nonphrasal</span><button class="popup" onclick="togglePopup('usagePopup4')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup4">Usage of <span class="code-font"><span class="function-syntax">Frames::new_nonphrasal</span></span>:<br/>Functions - <a href="3-fnc.html#SP5">&#167;5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">nonphrasal_stack_frame_is_current</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"can't nest nonphrasal stack frames"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nonphrasal_stack_frame</span><span class="plain-syntax"> = </span><a href="3-sf.html#SP6" class="function-link"><span class="function-syntax">Frames::new</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nonphrasal_stack_frame_is_current</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="3-sf.html#SP3" class="function-link"><span class="function-syntax">Frames::make_current</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">nonphrasal_stack_frame</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> &amp;</span><span class="identifier-syntax">nonphrasal_stack_frame</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::remove_nonphrase_stack_frame</span><button class="popup" onclick="togglePopup('usagePopup5')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup5">Usage of <span class="code-font"><span class="function-syntax">Frames::remove_nonphrase_stack_frame</span></span>:<br/>Functions - <a href="3-fnc.html#SP6">&#167;6</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nonphrasal_stack_frame</span><span class="plain-syntax"> = </span><a href="3-sf.html#SP6" class="function-link"><span class="function-syntax">Frames::new</span></a><span class="plain-syntax">(); </span><span class="comment-syntax"> to prevent accidental lucky misuse</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nonphrasal_stack_frame_is_current</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="3-sf.html#SP3" class="function-link"><span class="function-syntax">Frames::remove_current</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. </b><a href="3-sf.html#SP6" class="internal">stack_frame</a> is a small and potentially throwaway structure, and can
sometimes exist only fleetingly in the compiler. If we want to preserve it,
or take a snapshot of its current state, we need to make a "boxed" copy, and
this is the third sort of stack frame which exists.
</p>
<p class="commentary">The following does so. <a href="3-sf.html#SP5" class="internal">stack_frame_box</a> objects provide a convenient permanent
place in memory to stash these; pointers to them otherwise don't exist.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">stack_frame_box</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> </span><span class="identifier-syntax">boxed_phsf</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">stack_frame_box</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="function-syntax">Frames::boxed_frame</span><span class="plain-syntax">(</span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">old_frame</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">old_frame</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">stack_frame_box</span><span class="plain-syntax"> *</span><span class="identifier-syntax">box</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">stack_frame_box</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">new_frame</span><span class="plain-syntax"> = &amp;(</span><span class="identifier-syntax">box</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">boxed_phsf</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> *</span><span class="identifier-syntax">new_frame</span><span class="plain-syntax"> = *</span><span class="identifier-syntax">old_frame</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="3-lvs.html#SP9" class="function-link"><span class="function-syntax">LocalVariableSlates::deep_copy</span></a><span class="plain-syntax">(&amp;(</span><span class="identifier-syntax">new_frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">local_variables</span><span class="plain-syntax">),</span>
<span class="plain-syntax"> &amp;(</span><span class="identifier-syntax">old_frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">local_variables</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">new_frame</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<ul class="endnotetexts"><li>The structure stack_frame_box is private to this section.</li></ul>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. Creation. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">locals_slate</span><span class="plain-syntax"> </span><span class="identifier-syntax">local_variables</span><span class="plain-syntax">; </span><span class="comment-syntax"> those in scope here</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">shared_variable_access_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">shared_variables</span><span class="plain-syntax">; </span><span class="comment-syntax"> those in scope here</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">linked_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">local_block_values</span><span class="plain-syntax">; </span><span class="comment-syntax"> of </span><span class="extract"><span class="extract-syntax">local_block_value</span></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_formal_parameters_needed</span><span class="plain-syntax">; </span><span class="comment-syntax"> usually 0, unless there are ambiguities</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">kind_returned</span><span class="plain-syntax">; </span><span class="comment-syntax"> or </span><span class="extract"><span class="extract-syntax">NULL</span></span><span class="comment-syntax"> for no return value</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> **</span><span class="identifier-syntax">local_kind_variables</span><span class="plain-syntax">; </span><span class="comment-syntax"> points to an array indexed 1 to 26</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">determines_past_conditions</span><span class="plain-syntax">; </span><span class="comment-syntax"> or rather, in the present, but for future use</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::new</span><button class="popup" onclick="togglePopup('usagePopup6')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup6">Usage of <span class="code-font"><span class="function-syntax">Frames::new</span></span>:<br/><a href="3-sf.html#SP4">&#167;4</a><br/>Compile Imperative Definitions - <a href="3-cid.html#SP4">&#167;4</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">.</span><span class="identifier-syntax">local_variables</span><span class="plain-syntax"> = </span><a href="3-lvs.html#SP8" class="function-link"><span class="function-syntax">LocalVariableSlates::new</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">.</span><span class="identifier-syntax">local_kind_variables</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">.</span><span class="identifier-syntax">shared_variables</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">.</span><span class="identifier-syntax">determines_past_conditions</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">.</span><span class="identifier-syntax">local_block_values</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NEW_LINKED_LIST</span><span class="plain-syntax">(</span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">.</span><span class="identifier-syntax">kind_returned</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">.</span><span class="identifier-syntax">no_formal_parameters_needed</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<ul class="endnotetexts"><li>The structure stack_frame is accessed in 3/lvs, 3/lv, 3/fnc and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. Kinds. </b>The kind of value we expect to return from within this stack frame, if any.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::set_kind_returned</span><button class="popup" onclick="togglePopup('usagePopup7')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup7">Usage of <span class="code-font"><span class="function-syntax">Frames::set_kind_returned</span></span>:<br/>Compile Imperative Definitions - <a href="3-cid.html#SP10">&#167;10</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax">, </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">kind_returned</span><span class="plain-syntax"> = </span><span class="identifier-syntax">K</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="function-syntax">Frames::get_kind_returned</span><button class="popup" onclick="togglePopup('usagePopup8')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup8">Usage of <span class="code-font"><span class="function-syntax">Frames::get_kind_returned</span></span>:<br/>Compile Imperative Definitions - <a href="3-cid.html#SP2_3_1">&#167;2.3.1</a><br/>Compile Invocations Inline - <a href="5-cii.html#SP6_1_1_4_7_1">&#167;6.1.1.4.7.1</a>, <a href="5-cii.html#SP9">&#167;9</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> = </span><a href="3-sf.html#SP2" class="function-link"><span class="function-syntax">Frames::current_stack_frame</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_returned</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>&#167;8. </b>And the values of the kind variables A to Z:
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">KIND_VARIABLE_FROM_CONTEXT</span><span class="plain-syntax"> </span><a href="3-sf.html#SP8" class="function-link"><span class="function-syntax">Frames::get_kind_variable</span></a>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::set_kind_variables</span><button class="popup" onclick="togglePopup('usagePopup9')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup9">Usage of <span class="code-font"><span class="function-syntax">Frames::set_kind_variables</span></span>:<br/>Compile Imperative Definitions - <a href="3-cid.html#SP2_2">&#167;2.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax">, </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> **</span><span class="identifier-syntax">vars</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">local_kind_variables</span><span class="plain-syntax"> = </span><span class="identifier-syntax">vars</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="function-syntax">Frames::get_kind_variable</span><button class="popup" onclick="togglePopup('usagePopup10')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup10">Usage of <span class="code-font"><span class="function-syntax">Frames::get_kind_variable</span></span>:<br/>Compile Invocations Inline - <a href="5-cii.html#SP6_1_1_1">&#167;6.1.1.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">N</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> = </span><a href="3-sf.html#SP2" class="function-link"><span class="function-syntax">Frames::current_stack_frame</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">frame</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">local_kind_variables</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">local_kind_variables</span><span class="plain-syntax">[</span><span class="identifier-syntax">N</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="identifier-syntax">kind</span><span class="plain-syntax"> **</span><span class="function-syntax">Frames::temporarily_set_kvs</span><button class="popup" onclick="togglePopup('usagePopup11')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup11">Usage of <span class="code-font"><span class="function-syntax">Frames::temporarily_set_kvs</span></span>:<br/>Compile Invocations Inline - <a href="5-cii.html#SP6_1_1">&#167;6.1.1</a>, <a href="5-cii.html#SP9">&#167;9</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">kind</span><span class="plain-syntax"> **</span><span class="identifier-syntax">vars</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> = </span><a href="3-sf.html#SP2" class="function-link"><span class="function-syntax">Frames::current_stack_frame</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> **</span><span class="identifier-syntax">prev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">local_kind_variables</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">local_kind_variables</span><span class="plain-syntax"> = </span><span class="identifier-syntax">vars</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">prev</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>&#167;9. </b>The "deduced kind" is what the kind of the code in this stack frame would
be, if it were seen as a function from its parameter variables to its return value.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="function-syntax">Frames::deduced_function_kind</span><button class="popup" onclick="togglePopup('usagePopup12')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup12">Usage of <span class="code-font"><span class="function-syntax">Frames::deduced_function_kind</span></span>:<br/>Functions - <a href="3-fnc.html#SP6">&#167;6</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">pc</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">local_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">lvar</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER_LOCALS_IN_FRAME</span><span class="plain-syntax">(</span><span class="identifier-syntax">lvar</span><span class="plain-syntax">, </span><span class="identifier-syntax">frame</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="3-lv.html#SP6" class="function-link"><span class="function-syntax">LocalVariables::is_parameter</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">lvar</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pc</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K_array</span><span class="plain-syntax">[128];</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pc</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER_LOCALS_IN_FRAME</span><span class="plain-syntax">(</span><span class="identifier-syntax">lvar</span><span class="plain-syntax">, </span><span class="identifier-syntax">frame</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="3-lv.html#SP6" class="function-link"><span class="function-syntax">LocalVariables::is_parameter</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">lvar</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pc</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">128</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">OK</span><span class="plain-syntax"> = </span><span class="identifier-syntax">lvar</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">current_usage</span><span class="plain-syntax">.</span><span class="element-syntax">kind_as_declared</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">OK</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">OK</span><span class="plain-syntax"> == </span><span class="identifier-syntax">K_nil</span><span class="plain-syntax">)) </span><span class="identifier-syntax">OK</span><span class="plain-syntax"> = </span><span class="identifier-syntax">K_number</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K_array</span><span class="plain-syntax">[</span><span class="identifier-syntax">pc</span><span class="plain-syntax">++] = </span><span class="identifier-syntax">OK</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::function_kind</span><span class="plain-syntax">(</span><span class="identifier-syntax">pc</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_array</span><span class="plain-syntax">, </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_returned</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP10" class="paragraph-anchor"></a><b>&#167;10. Shared variables. </b>See <a href="../assertions-module/6-sv.html" class="internal">Shared Variables (in assertions)</a> for more on this.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::set_shared_variable_access_list</span><button class="popup" onclick="togglePopup('usagePopup13')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup13">Usage of <span class="code-font"><span class="function-syntax">Frames::set_shared_variable_access_list</span></span>:<br/>Compile Imperative Definitions - <a href="3-cid.html#SP2_2">&#167;2.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">shared_variable_access_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">access</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">shared_variables</span><span class="plain-syntax"> = </span><span class="identifier-syntax">access</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="identifier-syntax">shared_variable_access_list</span><span class="plain-syntax"> *</span><span class="function-syntax">Frames::get_shared_variable_access_list</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> = </span><a href="3-sf.html#SP2" class="function-link"><span class="function-syntax">Frames::current_stack_frame</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">shared_variables</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP11" class="paragraph-anchor"></a><b>&#167;11. Past tense. </b>It turns out to be convenient to remember whether the current function makes
any reference to the past, which we do here:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::determines_the_past</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> = </span><a href="3-sf.html#SP2" class="function-link"><span class="function-syntax">Frames::current_stack_frame</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="string-syntax">"tried to determine past where no stack frame exists"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">determines_past_conditions</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">LOCAL_VARIABLES</span><span class="plain-syntax">, </span><span class="string-syntax">"Stack frame determines past\n"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::used_for_past_tense</span><button class="popup" onclick="togglePopup('usagePopup14')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup14">Usage of <span class="code-font"><span class="function-syntax">Frames::used_for_past_tense</span></span>:<br/>Compile Atoms - <a href="4-ca.html#SP1_1">&#167;1.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> = </span><a href="3-sf.html#SP2" class="function-link"><span class="function-syntax">Frames::current_stack_frame</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">determines_past_conditions</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP12" class="paragraph-anchor"></a><b>&#167;12. Formal parameters. </b>Some stack frames need access to additional Inter function parameters to handle
runtime invocation ambiguities, and this is how they're requested:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::need_at_least_this_many_formals</span><button class="popup" onclick="togglePopup('usagePopup15')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup15">Usage of <span class="code-font"><span class="function-syntax">Frames::need_at_least_this_many_formals</span></span>:<br/>Compile Invocations - <a href="5-ci.html#SP1_3_1_2">&#167;1.3.1.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">N</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> = </span><a href="3-sf.html#SP2" class="function-link"><span class="function-syntax">Frames::current_stack_frame</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"requested formal parameters outside all stack frames"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">N</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_formal_parameters_needed</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_formal_parameters_needed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">N</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP13" class="paragraph-anchor"></a><b>&#167;13. It. </b>In some stack frames, the pronoun "it" (perhaps inflected) is allowed to stand
for the first call parameter to the function being compiled; and in others not.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">local_variable</span><span class="plain-syntax"> *</span><span class="function-syntax">Frames::enable_it</span><span class="plain-syntax">(</span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"no stack frame exists"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">local_variables</span><span class="plain-syntax">.</span><span class="element-syntax">it_variable_exists</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="3-lv.html#SP2" class="function-link"><span class="function-syntax">LocalVariables::new_call_parameter</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">frame</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">K</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP14" class="paragraph-anchor"></a><b>&#167;14. </b>If so, sometimes "its", "his", "her" or "their" are allowed too, but sometimes
not.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::is_its_enabled</span><span class="plain-syntax">(</span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">local_variables</span><span class="plain-syntax">.</span><span class="element-syntax">its_form_allowed</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::enable_its</span><span class="plain-syntax">(</span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"no stack frame exists"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">local_variables</span><span class="plain-syntax">.</span><span class="element-syntax">its_form_allowed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP15" class="paragraph-anchor"></a><b>&#167;15. </b>In addition, a special name can optionally be given to the "it". This is only
likely to be useful if the first call parameter is nameless &mdash; but that does
sometimes happen.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::alias_it</span><span class="plain-syntax">(</span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"no stack frame exists"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">local_variables</span><span class="plain-syntax">.</span><span class="element-syntax">it_pseudonym</span><span class="plain-syntax"> = </span><span class="identifier-syntax">W</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP16" class="paragraph-anchor"></a><b>&#167;16. Local block values. </b>Simple data at runtime, such as values of <span class="extract"><span class="extract-syntax">K_number</span></span> or <span class="extract"><span class="extract-syntax">K_truth_state</span></span>, occupy
a single Inter word. More involved data, such as values of <span class="extract"><span class="extract-syntax">K_text</span></span> or
<span class="extract"><span class="extract-syntax">K_stored_action</span></span>, cannot. Those are called "block values", because they occupy
entire multiple-word blocks of memory to store.
</p>
<p class="commentary">So when such data must be stored in a local variable, or some other memory location,
we will store the data itself if the kind is sufficiently simple, but a pointer
to an appropriate block of memory if not.
</p>
<p class="commentary">This is a particular issue for functions whose local variables need to have
block-value kinds, because that means the function must allocate suitable memory
when called and deallocate it on exit. Each stack frame must therefore track
what local block values it will need:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">local_block_value</span><span class="plain-syntax"> *</span><span class="function-syntax">Frames::allocate_local_block_value</span><button class="popup" onclick="togglePopup('usagePopup16')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup16">Usage of <span class="code-font"><span class="function-syntax">Frames::allocate_local_block_value</span></span>:<br/><a href="3-sf.html#SP21">&#167;21</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> = </span><a href="3-sf.html#SP2" class="function-link"><span class="function-syntax">Frames::current_stack_frame</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to allocate block kind outside all stack frames"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax"> *</span><span class="identifier-syntax">last</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LAST_IN_LINKED_LIST</span><span class="plain-syntax">(</span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">local_block_values</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bv</span><span class="plain-syntax"> = </span><a href="3-sf.html#SP18" class="function-link"><span class="function-syntax">Frames::new_lbv</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">last</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ADD_TO_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">, </span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">local_block_values</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::uses_local_block_values</span><button class="popup" onclick="togglePopup('usagePopup17')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup17">Usage of <span class="code-font"><span class="function-syntax">Frames::uses_local_block_values</span></span>:<br/>Functions - <a href="3-fnc.html#SP6">&#167;6</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">frame</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">LinkedLists::len</span><span class="plain-syntax">(</span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">local_block_values</span><span class="plain-syntax">) &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP17" class="paragraph-anchor"></a><b>&#167;17. </b>Where should temporary block values live, during the perhaps very brief
period while a function is running? We can't put it onto the virtual machine's
call stack, because it doesn't live in the VM's memory at all, and therefore
cannot be written or read. We could put it on the heap, but then allocation
and deallocation would be expensive.
</p>
<p class="commentary">Instead we put just the small blocks on a stack in memory: it fills downwards,
and at runtime the Inter identifier <span class="extract"><span class="extract-syntax">I7SFRAME</span></span> points to the current and therefore
bottom-most frame on this stack. So, for example, if the current stack frame has
just two local block values, a <span class="extract"><span class="extract-syntax">K_text</span></span> and a <span class="extract"><span class="extract-syntax">K_stored_action</span></span>, then we would have:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> ...free space...</span>
<span class="plain-syntax"> I7SFRAME --&gt; 0 } small block 0 (for a K_text), offset index 0</span>
<span class="plain-syntax"> 1 } may then --&gt; more data on the heap offset past 2</span>
<span class="plain-syntax"> 2 } small block 1 (for a K_stored_action) offset index 2</span>
<span class="plain-syntax"> 3 } similarly --&gt; more data on the heap offset past 8</span>
<span class="plain-syntax"> 4 }</span>
<span class="plain-syntax"> 5 }</span>
<span class="plain-syntax"> 6 }</span>
<span class="plain-syntax"> 7 }</span>
<span class="plain-syntax"> ...frames belonging to functions calling this one...</span>
</pre>
<p class="commentary">These small blocks may well point to larger blocks elsewhere on the heap (for
example, to accommodate the actual contents of a text, if they are non-constant).
But small blocks have the virtue of being of a size which is fixed for each
kind, and we can allocate space for them essentially immediately just by raising
the <span class="extract"><span class="extract-syntax">I7SFRAME</span></span> sufficiently.
</p>
<p class="commentary">Each local block value is kept track of with one of these:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">heap_allocation</span><span class="plain-syntax"> </span><span class="identifier-syntax">allocation</span><span class="plain-syntax">; </span><span class="comment-syntax"> needed to compile a function call returning a pointer to a new value</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">to_refer</span><span class="plain-syntax">; </span><span class="comment-syntax"> a schema to access this data</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">offset_index</span><span class="plain-syntax">; </span><span class="comment-syntax"> start of small block wrt current stack frame</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">offset_past</span><span class="plain-syntax">; </span><span class="comment-syntax"> just past the end of the small block</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure local_block_value is private to this section.</li></ul>
<p class="commentary firstcommentary"><a id="SP18" class="paragraph-anchor"></a><b>&#167;18. </b>Note that the schemas below for calculating offset positions from <span class="extract"><span class="extract-syntax">I7SFRAME</span></span>
will end up only as a single addition at runtime, because the multiplication of
<span class="extract"><span class="extract-syntax">WORDSIZE</span></span> by a literal positive integer will be constant-folded in code
generation.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">local_block_value</span><span class="plain-syntax"> *</span><span class="function-syntax">Frames::new_lbv</span><button class="popup" onclick="togglePopup('usagePopup18')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup18">Usage of <span class="code-font"><span class="function-syntax">Frames::new_lbv</span></span>:<br/><a href="3-sf.html#SP16">&#167;16</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax"> *</span><span class="identifier-syntax">last</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bv</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">last</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">bv</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">offset_index</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">offset_index</span><span class="plain-syntax"> = </span><span class="identifier-syntax">last</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">offset_past</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">allocation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TheHeap::make_allocation</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">offset_index</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">offset_past</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bv</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">offset_index</span><span class="plain-syntax"> + </span><span class="identifier-syntax">Kinds::Behaviour::get_small_block_size</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">ref</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">offset_index</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">ref</span><span class="plain-syntax">, </span><span class="string-syntax">"I7SFRAME"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bv</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">offset_index</span><span class="plain-syntax"> == </span><span class="constant-syntax">1</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">ref</span><span class="plain-syntax">, </span><span class="string-syntax">"(I7SFRAME+WORDSIZE)"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">ref</span><span class="plain-syntax">, </span><span class="string-syntax">"(I7SFRAME+WORDSIZE**%d)"</span><span class="plain-syntax">, </span><span class="identifier-syntax">bv</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">offset_index</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">to_refer</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Calculus::Schemas::new</span><span class="plain-syntax">(</span><span class="string-syntax">"%S"</span><span class="plain-syntax">, </span><span class="identifier-syntax">ref</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">ref</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bv</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP19" class="paragraph-anchor"></a><b>&#167;19. </b>The following code is executed when the stack frame is entered: we push the
old value of <span class="extract"><span class="extract-syntax">I7SFRAME_HL</span></span> to the call stack to save it; then call a function
in <a href="../BasicInformKit/S-blc.html" class="internal">BlockValues (in BasicInformKit)</a> to make space for the small
blocks we need, which will move <span class="extract"><span class="extract-syntax">I7SFRAME_HL</span></span> downwards by <span class="extract"><span class="extract-syntax">size</span></span> words; and
then initialise the small blocks one by one to default values.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::compile_lbv_setup</span><button class="popup" onclick="togglePopup('usagePopup19')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup19">Usage of <span class="code-font"><span class="function-syntax">Frames::compile_lbv_setup</span></span>:<br/>Functions - <a href="3-fnc.html#SP6_1_2">&#167;6.1.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::push</span><span class="plain-syntax">(</span><span class="identifier-syntax">Hierarchy::find</span><span class="plain-syntax">(</span><span class="identifier-syntax">I7SFRAME_HL</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">size</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax"> *</span><span class="identifier-syntax">lbv</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">lbv</span><span class="plain-syntax">, </span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">local_block_values</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">lbv</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">offset_past</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">size</span><span class="plain-syntax">) </span><span class="identifier-syntax">size</span><span class="plain-syntax"> = </span><span class="identifier-syntax">lbv</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">offset_past</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::call</span><span class="plain-syntax">(</span><span class="identifier-syntax">Hierarchy::find</span><span class="plain-syntax">(</span><span class="identifier-syntax">STACKFRAMECREATE_HL</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::down</span><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::val_number</span><span class="plain-syntax">((</span><span class="identifier-syntax">inter_ti</span><span class="plain-syntax">) </span><span class="identifier-syntax">size</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::up</span><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">lbv</span><span class="plain-syntax">, </span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">local_block_values</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TheHeap::emit_allocation</span><span class="plain-syntax">(</span><span class="identifier-syntax">lbv</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">allocation</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP20" class="paragraph-anchor"></a><b>&#167;20. </b>Symmetrically, this teardown code is executed when the stack frame is exited.
We deallocate each small block, and then restore <span class="extract"><span class="extract-syntax">I7SFRAME_HL</span></span> by pulling the
value we pushed earlier.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::compile_lbv_teardown</span><button class="popup" onclick="togglePopup('usagePopup20')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup20">Usage of <span class="code-font"><span class="function-syntax">Frames::compile_lbv_teardown</span></span>:<br/>Functions - <a href="3-fnc.html#SP6_1_4">&#167;6.1.4</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax"> *</span><span class="identifier-syntax">lbv</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">lbv</span><span class="plain-syntax">, </span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">local_block_values</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">inter_name</span><span class="plain-syntax"> *</span><span class="identifier-syntax">iname</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Hierarchy::find</span><span class="plain-syntax">(</span><span class="identifier-syntax">BLKVALUEFREEONSTACK_HL</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::call</span><span class="plain-syntax">(</span><span class="identifier-syntax">iname</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::down</span><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::val_number</span><span class="plain-syntax">((</span><span class="identifier-syntax">inter_ti</span><span class="plain-syntax">) </span><span class="identifier-syntax">lbv</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">offset_index</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::up</span><span class="plain-syntax">();</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::pull</span><span class="plain-syntax">(</span><span class="identifier-syntax">Hierarchy::find</span><span class="plain-syntax">(</span><span class="identifier-syntax">I7SFRAME_HL</span><span class="plain-syntax">));</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP21" class="paragraph-anchor"></a><b>&#167;21. </b>The net effect is that when the rest of Inform needs to compile the address
of a newly-allocated value of a block kind <span class="extract"><span class="extract-syntax">K</span></span>, it can simply call the
following, without having to worry about how any of this works:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::emit_new_local_value</span><button class="popup" onclick="togglePopup('usagePopup21')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup21">Usage of <span class="code-font"><span class="function-syntax">Frames::emit_new_local_value</span></span>:<br/>Compile Values - <a href="2-cv.html#SP6_1">&#167;6.1</a><br/>Compile Rvalues - <a href="2-cr.html#SP5">&#167;5</a><br/>Deciding to Defer - <a href="4-dtd.html#SP11">&#167;11</a>, <a href="4-dtd.html#SP17">&#167;17</a><br/>Compile Invocations As Calls - <a href="5-ciac.html#SP2_2">&#167;2.2</a><br/>Compile Invocations Inline - <a href="5-cii.html#SP3_2">&#167;3.2</a>, <a href="5-cii.html#SP6_2_1">&#167;6.2.1</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">local_block_value</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bv</span><span class="plain-syntax"> = </span><a href="3-sf.html#SP16" class="function-link"><span class="function-syntax">Frames::allocate_local_block_value</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-cs.html#SP1" class="function-link"><span class="function-syntax">CompileSchemas::from_terms_in_val_context</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">bv</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">to_refer</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP22" class="paragraph-anchor"></a><b>&#167;22. Logging. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Frames::log</span><span class="plain-syntax">(</span><span class="reserved-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;null stack frame&gt;\n"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Stack frame at %08x: it:%s, dpc:%s\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">frame</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">local_variables</span><span class="plain-syntax">.</span><span class="element-syntax">it_variable_exists</span><span class="plain-syntax">)?</span><span class="string-syntax">"yes"</span><span class="plain-syntax">:</span><span class="string-syntax">"no"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">determines_past_conditions</span><span class="plain-syntax">)?</span><span class="string-syntax">"yes"</span><span class="plain-syntax">:</span><span class="string-syntax">"no"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">local_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">lvar</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER_LOCALS_IN_FRAME</span><span class="plain-syntax">(</span><span class="identifier-syntax">lvar</span><span class="plain-syntax">, </span><span class="identifier-syntax">frame</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">lvar</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">lv_purpose</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">LET_VALUE_LV:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Let/loop value: "</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">TOKEN_CALL_PARAMETER_LV:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Call value: "</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">INTERNAL_USE_LV:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Internal use: "</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Other: "</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"%~L: "</span><span class="plain-syntax">, </span><span class="identifier-syntax">lvar</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="3-lv.html#SP26" class="function-link"><span class="function-syntax">LocalVariables::log</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">lvar</span><span class="plain-syntax">); </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"\n"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="2-mgap.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-im.html">1</a></li><li class="progresschapter"><a href="2-cv.html">2</a></li><li class="progresscurrentchapter">3</li><li class="progresscurrent">sf</li><li class="progresssection"><a href="3-lvs.html">lvs</a></li><li class="progresssection"><a href="3-lv.html">lv</a></li><li class="progresssection"><a href="3-tv.html">tv</a></li><li class="progresssection"><a href="3-lp.html">lp</a></li><li class="progresssection"><a href="3-cb.html">cb</a></li><li class="progresssection"><a href="3-fnc.html">fnc</a></li><li class="progresssection"><a href="3-jl.html">jl</a></li><li class="progresssection"><a href="3-pr.html">pr</a></li><li class="progresssection"><a href="3-cls.html">cls</a></li><li class="progresssection"><a href="3-cid.html">cid</a></li><li class="progresschapter"><a href="4-cs.html">4</a></li><li class="progresschapter"><a href="5-cbal.html">5</a></li><li class="progressnext"><a href="3-lvs.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>