mirror of
https://github.com/ganelson/inform.git
synced 2024-07-16 22:14:23 +03:00
434 lines
65 KiB
HTML
434 lines
65 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>§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="identifier-syntax">work</span><span class="plain-syntax"> </span><span class="identifier-syntax">something</span><span class="plain-syntax"> </span><span class="identifier-syntax">out</span><span class="plain-syntax"> </span><span class="identifier-syntax">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>§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">§5</a><br/>Closures - <a href="3-cls.html#SP5_1">§5.1</a><br/>Compile Deferred Propositions - <a href="4-cdp.html#SP3">§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>§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 — 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>§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">§4.4.3</a><br/>Compile Invocations - <a href="5-ci.html#SP2_1">§2.1</a>, <a href="5-ci.html#SP2_1_1">§2.1.1</a><br/>Compile Invocations Inline - <a href="5-cii.html#SP6_1_1_4_7_1">§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">§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">§3</a>, <a href="3-jl.html#SP7">§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">-></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>§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">§2</a><br/>Compile Imperative Definitions - <a href="3-cid.html#SP2">§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">(), &</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>§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 — even if it fails in some way at runtime — 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">§5</a><br/>Closures - <a href="3-cls.html#SP5_1">§5.1</a><br/>Compile Imperative Definitions - <a href="3-cid.html#SP2">§2</a><br/>Compile Deferred Propositions - <a href="4-cdp.html#SP3">§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">-></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">-></span><span class="element-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="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>§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">-></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">§6</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP6_1_1" class="paragraph-anchor"></a><b>§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">§6.1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP6_1_2" class="paragraph-anchor"></a><b>§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"><frame-></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">§6.1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP6_1_3" class="paragraph-anchor"></a><b>§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">§6.1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP6_1_4" class="paragraph-anchor"></a><b>§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">-></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">>=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">§6.1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP6_1_5" class="paragraph-anchor"></a><b>§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">§6.1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP6_2" class="paragraph-anchor"></a><b>§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">§6</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>§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">§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">❮</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">❯</a></li></ul></div>
|
|
</nav><!--End of weave-->
|
|
|
|
</main>
|
|
</body>
|
|
</html>
|
|
|