1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 00:24:22 +03:00
inform7/docs/imperative-module/3-fnc.html
2023-07-19 23:46:39 +01:00

434 lines
64 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Functions</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 'Functions' 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>Functions</b></li></ul></div>
<p class="purpose">To compile Inter functions.</p>
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. </b>The code in this section is used throughout the <a href="index.html" class="internal">imperative</a> and <a href="../runtime-module/index.html" class="internal">runtime</a>
modules whenever an Inter function needs to be compiled. This will often not be
a function corresponding to a definition in the source text; more often, it will
be a support function needed to implement some feature at runtime.
</p>
<p class="commentary">However it happens, every function is compiled using code like so:
</p>
<pre class="displayed-code all-displayed-code code-font">
<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="comment-syntax">/* work something out here */</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">packaging_state</span><span class="plain-syntax"> </span><span class="identifier-syntax">save</span><span class="plain-syntax"> = </span><span class="function-syntax">Functions::begin</span><span class="plain-syntax">(</span><span class="identifier-syntax">iname</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> declare some call parameters</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> now compile the code in the function</span>
<span class="plain-syntax"> </span><span class="function-syntax">Functions::end</span><span class="plain-syntax">(</span><span class="identifier-syntax">save</span><span class="plain-syntax">);</span>
</pre>
<p class="commentary">This will create a new stack frame for the function, which is usually what is
wanted. If we want to compile it using an existing frame <span class="extract"><span class="extract-syntax">frame</span></span>, then instead
call <span class="extract"><span class="extract-syntax">Functions::begin_framed(iname, frame)</span></span>, not <span class="extract"><span class="extract-syntax">Functions::begin(iname)</span></span>;
and a third version, <span class="extract"><span class="extract-syntax">Functions::begin_from_idb(iname, frame, idb)</span></span> exists
if we are compiling from an imperative definition <span class="extract"><span class="extract-syntax">idb</span></span>.
</p>
<p class="commentary">There are nearly 100 examples of this simple API being used in Inform, so
it's not hard to find code to imitate if you want to compile a new function.
</p>
<p class="commentary">Note that only one function can be compiled at a time: <a href="3-fnc.html#SP6" class="internal">Functions::end</a>
must be called before <a href="3-fnc.html#SP2" class="internal">Functions::begin</a> (or similar) can be called again.
</p>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>There aren't really three different methods, because:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">packaging_state</span><span class="plain-syntax"> </span><span class="function-syntax">Functions::begin</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">Functions::begin</span></span>:<br/>Phrase Requests - <a href="3-pr.html#SP5">&#167;5</a><br/>Closures - <a href="3-cls.html#SP5_1">&#167;5.1</a><br/>Compile Deferred Propositions - <a href="4-cdp.html#SP3">&#167;3</a></span></button><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="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="3-fnc.html#SP5" class="function-link"><span class="function-syntax">Functions::begin_from_idb</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">iname</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>
<span class="identifier-syntax">packaging_state</span><span class="plain-syntax"> </span><span class="function-syntax">Functions::begin_framed</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="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">return</span><span class="plain-syntax"> </span><a href="3-fnc.html#SP5" class="function-link"><span class="function-syntax">Functions::begin_from_idb</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">iname</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>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b>Between the beginning and the end, we need to keep track of:
</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">function_under_compilation</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">id_body</span><span class="plain-syntax"> *</span><span class="identifier-syntax">from_idb</span><span class="plain-syntax">; </span><span class="comment-syntax"> if any &mdash; many functions do not arise this way</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">function_stack_frame</span><span class="plain-syntax">; </span><span class="comment-syntax"> the stack frame for this function</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">currently_compiling_nnp</span><span class="plain-syntax">; </span><span class="comment-syntax"> is this a nonphrasal stack frame we made ourselves?</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">inter_package</span><span class="plain-syntax"> *</span><span class="identifier-syntax">into_package</span><span class="plain-syntax">; </span><span class="comment-syntax"> where Inter is being emitted to</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">inter_name</span><span class="plain-syntax"> *</span><span class="identifier-syntax">currently_compiling_iname</span><span class="plain-syntax">; </span><span class="comment-syntax"> function we end up with</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">label_namespaces</span><span class="plain-syntax">; </span><span class="comment-syntax"> of </span><span class="extract"><span class="extract-syntax">label_namespace</span></span>
<span class="plain-syntax">} </span><span class="reserved-syntax">function_under_compilation</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">function_compilation_is_happening_now</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">function_under_compilation</span><span class="plain-syntax"> </span><span class="identifier-syntax">current_function</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure function_under_compilation is accessed in 3/jl, 3/cid and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b></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">Functions::a_function_is_being_compiled</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">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">function_compilation_is_happening_now</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="identifier-syntax">id_body</span><span class="plain-syntax"> *</span><span class="function-syntax">Functions::defn_being_compiled</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">Functions::defn_being_compiled</span></span>:<br/>Compile Blocks and Lines - <a href="5-cbal.html#SP4_4_3">&#167;4.4.3</a><br/>Compile Invocations - <a href="5-ci.html#SP2_1">&#167;2.1</a>, <a href="5-ci.html#SP2_1_1">&#167;2.1.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></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">function_compilation_is_happening_now</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_function</span><span class="plain-syntax">.</span><span class="element-syntax">from_idb</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">parse_node</span><span class="plain-syntax"> *</span><span class="function-syntax">Functions::line_being_compiled</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">Functions::line_being_compiled</span></span>:<br/>Compile Rvalues - <a href="2-cr.html#SP1_3">&#167;1.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">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">function_compilation_is_happening_now</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_sentence</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">inter_package</span><span class="plain-syntax"> *</span><span class="function-syntax">Functions::package_being_compiled</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">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">function_compilation_is_happening_now</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_function</span><span class="plain-syntax">.</span><span class="element-syntax">into_package</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">linked_list</span><span class="plain-syntax"> *</span><span class="function-syntax">Functions::current_label_namespaces</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">Functions::current_label_namespaces</span></span>:<br/>Jump Labels - <a href="3-jl.html#SP3">&#167;3</a>, <a href="3-jl.html#SP7">&#167;7</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">function_compilation_is_happening_now</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">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">from_idb</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_function</span><span class="plain-syntax">.</span><span class="element-syntax">from_idb</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">compilation_data</span><span class="plain-syntax">.</span><span class="element-syntax">label_namespaces</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_function</span><span class="plain-syntax">.</span><span class="element-syntax">label_namespaces</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">NULL</span><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>If the <span class="extract"><span class="extract-syntax">frame</span></span> argument is set, then we'll use that; otherwise we will
create a new nonphrasal stack frame.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">packaging_state</span><span class="plain-syntax"> </span><span class="function-syntax">Functions::begin_from_idb</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">Functions::begin_from_idb</span></span>:<br/><a href="3-fnc.html#SP2">&#167;2</a><br/>Compile Imperative Definitions - <a href="3-cid.html#SP2">&#167;2</a></span></button><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="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">id_body</span><span class="plain-syntax"> *</span><span class="identifier-syntax">idb</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">iname</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 iname for function"</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">function_compilation_is_happening_now</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">"functions cannot be compiled simultaneously"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">function_compilation_is_happening_now</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">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">frame</span><span class="plain-syntax"> = </span><a href="3-sf.html#SP4" class="function-link"><span class="function-syntax">Frames::new_nonphrasal</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">currently_compiling_nnp</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">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">currently_compiling_nnp</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">function_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">packaging_state</span><span class="plain-syntax"> </span><span class="identifier-syntax">save</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Emit::new_packaging_state</span><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">into_package</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Produce::function_body</span><span class="plain-syntax">(</span><span class="identifier-syntax">Emit::tree</span><span class="plain-syntax">(), &amp;</span><span class="identifier-syntax">save</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">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">currently_compiling_iname</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">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">from_idb</span><span class="plain-syntax"> = </span><span class="identifier-syntax">idb</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">idb</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="3-jl.html#SP4" class="function-link"><span class="function-syntax">JumpLabels::restart_counters</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">idb</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">label_namespaces</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">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">label_namespaces</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NEW_LINKED_LIST</span><span class="plain-syntax">(</span><span class="reserved-syntax">label_namespace</span><span class="plain-syntax">);</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">(</span><span class="identifier-syntax">frame</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="3-cb.html#SP7" class="function-link"><span class="function-syntax">CodeBlocks::begin_code_blocks</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><a href="3-lvs.html#SP18" class="function-link"><span class="function-syntax">LocalVariableSlates::declare_all</span></a><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">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">save</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. </b>The real work comes at the end. At this point, we have compiled the body of
the code into the Inter package created above, but it is not yet part of an
Inter function.
</p>
<p class="commentary">What we do with this depends on whether any block values were used in the
function, because it they were then we need to worry about memory allocation.
The following pseudocode gives the general idea. Suppose we want to create
a function called <span class="extract"><span class="extract-syntax">public_name</span></span>. If no block values were needed, we do the
obvious thing:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> public_name(t1, t2, ..., tn) {</span>
<span class="plain-syntax"> ... package code here ...</span>
<span class="plain-syntax"> }</span>
</pre>
<p class="commentary">But if block values are involved, we make two functions, a "shell" with the
outward-facing name, and a "kernel" which does the actual work. If we suppose
that the kernel returns an ordinary value, then this happens:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> public_name(t1, t2, ..., tn) {</span>
<span class="plain-syntax"> ...allocate memory...</span>
<span class="plain-syntax"> RV = kernel_name(t1, t2, ..., tn)</span>
<span class="plain-syntax"> ...deallocate...</span>
<span class="plain-syntax"> return RV</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> kernel_name(I7RBLK, t1, t2, ..., tn) {</span>
<span class="plain-syntax"> ... package code here ...</span>
<span class="plain-syntax"> }</span>
</pre>
<p class="commentary">Since we do not support exceptions in the Inter VM, it follows that whatever
<span class="extract"><span class="extract-syntax">kernel_name</span></span> does &mdash; even if it fails in some way at runtime &mdash; all
allocated memory will safely be deallocated.
</p>
<p class="commentary">A slight variation is needed if the kernel returns a block value, as follows:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> public_name(t1, t2, ..., tn) {</span>
<span class="plain-syntax"> ...allocate memory...</span>
<span class="plain-syntax"> BlkValueCopy(BRV, kernel_name(t1, t2, ..., tn))</span>
<span class="plain-syntax"> ...deallocate...</span>
<span class="plain-syntax"> return BRV</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> kernel_name(BRV, t1, t2, ..., tn) {</span>
<span class="plain-syntax"> ... package code here ...</span>
<span class="plain-syntax"> }</span>
</pre>
<p class="commentary">Here <span class="extract"><span class="extract-syntax">BRV</span></span> is a pointer to memory in which to write the return value: note that
we copy it before we deallocate any of the memory which was likely used to
generate it.
</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">Functions::end</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">Functions::end</span></span>:<br/>Phrase Requests - <a href="3-pr.html#SP5">&#167;5</a><br/>Closures - <a href="3-cls.html#SP5_1">&#167;5.1</a><br/>Compile Imperative Definitions - <a href="3-cid.html#SP2">&#167;2</a><br/>Compile Deferred Propositions - <a href="4-cdp.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">packaging_state</span><span class="plain-syntax"> </span><span class="identifier-syntax">save</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">function_compilation_is_happening_now</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">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"function compilation has not started, so cannot end"</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="identifier-syntax">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">function_stack_frame</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">kernel_name</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">inter_name</span><span class="plain-syntax"> *</span><span class="identifier-syntax">public_name</span><span class="plain-syntax"> = </span><span class="identifier-syntax">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">currently_compiling_iname</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-sf.html#SP16" class="function-link"><span class="function-syntax">Frames::uses_local_block_values</span></a><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">Kinds::Behaviour::uses_block_values</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><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"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">kernel_name</span><span class="plain-syntax"> = </span><a href="3-fnc.html#SP7" class="function-link"><span class="function-syntax">Functions::function_kernel</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">Emit::tree</span><span class="plain-syntax">(), </span><span class="identifier-syntax">public_name</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">F_kind</span><span class="plain-syntax"> = </span><a href="3-sf.html#SP9" class="function-link"><span class="function-syntax">Frames::deduced_function_kind</span></a><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">needed</span><span class="plain-syntax"> = </span><a href="3-lvs.html#SP7" class="function-link"><span class="function-syntax">LocalVariableSlates::size</span></a><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">kernel_name</span><span class="plain-syntax">) </span><span class="identifier-syntax">needed</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">TargetVMs::allow_this_many_locals</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::vm</span><span class="plain-syntax">(), </span><span class="identifier-syntax">needed</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="3-fnc.html#SP6_2" class="named-paragraph-link"><span class="named-paragraph">Issue a problem for too many locals</span><span class="named-paragraph-number">6.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="3-lvs.html#SP18" class="function-link"><span class="function-syntax">LocalVariableSlates::declare_all</span></a><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">Produce::end_function_body</span><span class="plain-syntax">(</span><span class="identifier-syntax">Emit::tree</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">kernel_name</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="3-fnc.html#SP6_1" class="named-paragraph-link"><span class="named-paragraph">Compile an outer shell function with the public-facing name</span><span class="named-paragraph-number">6.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="3-cb.html#SP8" class="function-link"><span class="function-syntax">CodeBlocks::end_code_blocks</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">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">currently_compiling_nnp</span><span class="plain-syntax">) </span><a href="3-sf.html#SP4" class="function-link"><span class="function-syntax">Frames::remove_nonphrase_stack_frame</span></a><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><span class="identifier-syntax">Packaging::exit</span><span class="plain-syntax">(</span><span class="identifier-syntax">Emit::tree</span><span class="plain-syntax">(), </span><span class="identifier-syntax">save</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="3-jl.html#SP7" class="function-link"><span class="function-syntax">JumpLabels::compile_necessary_storage</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">function_compilation_is_happening_now</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">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">currently_compiling_nnp</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">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">function_stack_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">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">into_package</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">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">currently_compiling_iname</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">current_function</span><span class="plain-syntax">.</span><span class="element-syntax">from_idb</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="SP6_1" class="paragraph-anchor"></a><b>&#167;6.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile an outer shell function with the public-facing name</span><span class="named-paragraph-number">6.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">returns_block_value</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::Behaviour::uses_block_values</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><span class="identifier-syntax">inter_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">kernel_s</span><span class="plain-syntax"> = </span><span class="identifier-syntax">InterNames::to_symbol</span><span class="plain-syntax">(</span><span class="identifier-syntax">kernel_name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">inter_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">public_s</span><span class="plain-syntax"> = </span><span class="identifier-syntax">InterNames::to_symbol</span><span class="plain-syntax">(</span><span class="identifier-syntax">public_name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">inter_package</span><span class="plain-syntax"> *</span><span class="identifier-syntax">kernel_package</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PackageInstruction::which</span><span class="plain-syntax">(</span><span class="identifier-syntax">public_s</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PackageInstruction::set_name_symbol</span><span class="plain-syntax">(</span><span class="identifier-syntax">kernel_package</span><span class="plain-syntax">, </span><span class="identifier-syntax">kernel_s</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PackageInstruction::set_data_type</span><span class="plain-syntax">(</span><span class="identifier-syntax">kernel_package</span><span class="plain-syntax">, </span><span class="identifier-syntax">InterTypes::unchecked</span><span class="plain-syntax">());</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">inter_package</span><span class="plain-syntax"> *</span><span class="identifier-syntax">shell_package</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Produce::function_body</span><span class="plain-syntax">(</span><span class="identifier-syntax">Emit::tree</span><span class="plain-syntax">(), </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">public_name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">inter_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">rv_symbol</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="3-fnc.html#SP6_1_1" class="named-paragraph-link"><span class="named-paragraph">Compile I6 locals for the outer shell</span><span class="named-paragraph-number">6.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="3-fnc.html#SP6_1_2" class="named-paragraph-link"><span class="named-paragraph">Compile some setup code to make ready for the kernel</span><span class="named-paragraph-number">6.1.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="3-fnc.html#SP6_1_3" class="named-paragraph-link"><span class="named-paragraph">Compile a call to the kernel</span><span class="named-paragraph-number">6.1.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="3-fnc.html#SP6_1_4" class="named-paragraph-link"><span class="named-paragraph">Compile some teardown code now that the kernel has finished</span><span class="named-paragraph-number">6.1.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="3-fnc.html#SP6_1_5" class="named-paragraph-link"><span class="named-paragraph">Compile a return from the outer shell</span><span class="named-paragraph-number">6.1.5</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Produce::end_function_body</span><span class="plain-syntax">(</span><span class="identifier-syntax">Emit::tree</span><span class="plain-syntax">());</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PackageInstruction::set_name_symbol</span><span class="plain-syntax">(</span><span class="identifier-syntax">shell_package</span><span class="plain-syntax">, </span><span class="identifier-syntax">public_s</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PackageInstruction::set_data_type</span><span class="plain-syntax">(</span><span class="identifier-syntax">shell_package</span><span class="plain-syntax">, </span><span class="identifier-syntax">Produce::kind_to_type</span><span class="plain-syntax">(</span><span class="identifier-syntax">F_kind</span><span class="plain-syntax">));</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-fnc.html#SP6">&#167;6</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP6_1_1" class="paragraph-anchor"></a><b>&#167;6.1.1. </b>Suppose the function has to return a list. Then the function is compiled
with an extra first parameter (called <span class="extract"><span class="extract-syntax">I7RBLK</span></span>), which is a pointer to the
block value in which to write the answer. After that come all of the call
parameters of the phrase (but none of the "let" or scratch-use locals). If,
on the other hand, the function returns a word value, <span class="extract"><span class="extract-syntax">I7RBLK</span></span> is placed
after the call parameters, and is used only as a scratch variable.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile I6 locals for the outer shell</span><span class="named-paragraph-number">6.1.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">returns_block_value</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">rv_symbol</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Produce::local</span><span class="plain-syntax">(</span><span class="identifier-syntax">Emit::tree</span><span class="plain-syntax">(), </span><span class="identifier-syntax">K_number</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"BRV"</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"block return value"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="3-lvs.html#SP18" class="function-link"><span class="function-syntax">LocalVariableSlates::declare_all_parameters</span></a><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">returns_block_value</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">rv_symbol</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Produce::local</span><span class="plain-syntax">(</span><span class="identifier-syntax">Emit::tree</span><span class="plain-syntax">(), </span><span class="identifier-syntax">K_number</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"RV"</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"return value"</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-fnc.html#SP6_1">&#167;6.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP6_1_2" class="paragraph-anchor"></a><b>&#167;6.1.2. </b>We allocate memory for each pointer value used in the stack frame:
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile some setup code to make ready for the kernel</span><span class="named-paragraph-number">6.1.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><a href="3-sf.html#SP19" class="function-link"><span class="function-syntax">Frames::compile_lbv_setup</span></a><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">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="function-syntax">&lt;frame-&gt;</span><span class="element-syntax">no_formal_parameters_needed</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nonlocal_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nlv</span><span class="plain-syntax"> = </span><a href="3-tv.html#SP2" class="function-link"><span class="function-syntax">TemporaryVariables::formal_parameter</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">i</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">RTVariables::iname</span><span class="plain-syntax">(</span><span class="identifier-syntax">nlv</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-fnc.html#SP6_1">&#167;6.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP6_1_3" class="paragraph-anchor"></a><b>&#167;6.1.3. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile a call to the kernel</span><span class="named-paragraph-number">6.1.3</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">returns_block_value</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">BLKVALUECOPY_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_symbol</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_number</span><span class="plain-syntax">, </span><span class="identifier-syntax">rv_symbol</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">kernel_name</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><a href="3-lvs.html#SP19" class="function-link"><span class="function-syntax">LocalVariableSlates::emit_all_parameters</span></a><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::up</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="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::inv</span><span class="plain-syntax">(</span><span class="identifier-syntax">STORE_BIP</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::ref_symbol</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">rv_symbol</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">kernel_name</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><a href="3-lvs.html#SP19" class="function-link"><span class="function-syntax">LocalVariableSlates::emit_all_parameters</span></a><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::up</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>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-fnc.html#SP6_1">&#167;6.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP6_1_4" class="paragraph-anchor"></a><b>&#167;6.1.4. </b>Here we deallocate all the memory allocated earlier.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile some teardown code now that the kernel has finished</span><span class="named-paragraph-number">6.1.4</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</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">-1; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&gt;=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">--) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nonlocal_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nlv</span><span class="plain-syntax"> = </span><a href="3-tv.html#SP2" class="function-link"><span class="function-syntax">TemporaryVariables::formal_parameter</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">i</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">RTVariables::iname</span><span class="plain-syntax">(</span><span class="identifier-syntax">nlv</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><a href="3-sf.html#SP20" class="function-link"><span class="function-syntax">Frames::compile_lbv_teardown</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">frame</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-fnc.html#SP6_1">&#167;6.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP6_1_5" class="paragraph-anchor"></a><b>&#167;6.1.5. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile a return from the outer shell</span><span class="named-paragraph-number">6.1.5</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::inv</span><span class="plain-syntax">(</span><span class="identifier-syntax">RETURN_BIP</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_symbol</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">rv_symbol</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::up</span><span class="plain-syntax">();</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-fnc.html#SP6_1">&#167;6.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP6_2" class="paragraph-anchor"></a><b>&#167;6.2. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Issue a problem for too many locals</span><span class="named-paragraph-number">6.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::sentence_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(), </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_TooManyLocals</span><span class="plain-syntax">),</span>
<span class="plain-syntax"> </span><span class="string-syntax">"there are too many temporarily-named values in this phrase"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"which may be a sign that it is complicated enough to need breaking up "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"into smaller phrases making use of each other. "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"The limit is 15 at a time for a Z-machine project (see the Settings) "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"and 256 at a time for Glulx. That has to include both values created in the "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"declaration of a phrase (e.g. the 'N' in 'To deduct (N - a number) points: "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"...', or the 'watcher' in 'Instead of taking something in the presence of "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"a man (called the watcher): ...'), and also values created with 'let' or "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"'repeat' (each 'repeat' loop claiming two such values) - not to mention "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"one or two values occasionally needed to work with Tables. Because of all "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"this, it's best to keep the complexity to a minimum within any single phrase."</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-fnc.html#SP6">&#167;6</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. </b>Here is the name for a kernel, if it is needed:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">inter_name</span><span class="plain-syntax"> *</span><span class="function-syntax">Functions::function_kernel</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">Functions::function_kernel</span></span>:<br/><a href="3-fnc.html#SP6">&#167;6</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">inter_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">I</span><span class="plain-syntax">, </span><span class="identifier-syntax">inter_name</span><span class="plain-syntax"> *</span><span class="identifier-syntax">public_name</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">Packaging::housed_in_function</span><span class="plain-syntax">(</span><span class="identifier-syntax">I</span><span class="plain-syntax">, </span><span class="identifier-syntax">public_name</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">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"routine not housed in function"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">package_request</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><span class="identifier-syntax">InterNames::location</span><span class="plain-syntax">(</span><span class="identifier-syntax">public_name</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">kernel_name</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Packaging::make_iname_within</span><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"kernel"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">InterNames::set_flag</span><span class="plain-syntax">(</span><span class="identifier-syntax">kernel_name</span><span class="plain-syntax">, </span><span class="identifier-syntax">MAKE_NAME_UNIQUE_ISYMF</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">kernel_name</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="3-cb.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="progresssection"><a href="3-sf.html">sf</a></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="progresscurrent">fnc</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-jl.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>