mirror of
https://github.com/ganelson/inform.git
synced 2024-07-16 22:14:23 +03:00
779 lines
123 KiB
HTML
779 lines
123 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>Compile Invocations</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="../overview.html">
|
|
<img src="../docs-assets/Inform.png" height=72">
|
|
</a></h1>
|
|
<ul><li><a href="../overview.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 'Compile Invocations' generated by Inweb-->
|
|
<div class="breadcrumbs">
|
|
<ul class="crumbs"><li><a href="../overview.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#5">Chapter 5: Invocations</a></li><li><b>Compile Invocations</b></li></ul></div>
|
|
<p class="purpose">Generating code to perform an invocation.</p>
|
|
|
|
<ul class="toc"><li><a href="5-ci.html#SP1">§1. Upper level: compiling from whole lists</a></li><li><a href="5-ci.html#SP2">§2. Lower level: compiling single invocations</a></li><li><a href="5-ci.html#SP3">§3. Tokens packets</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>§1. Upper level: compiling from whole lists. </b>Here, we are given an invocation list <span class="extract"><span class="extract-syntax">invl</span></span>, and we must generate Inter code
|
|
to carry it out. The code in this section does some complicated things; the
|
|
test group <span class="extract"><span class="extract-syntax">:invocations</span></span> may be helpful when maintaining 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">CompileInvocations::list</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">CompileInvocations::list</span></span>:<br/>Compile Rvalues - <a href="2-cr.html#SP1">§1</a><br/>Compile Blocks and Lines - <a href="5-cbal.html#SP5">§5</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">value_holster</span><span class="plain-syntax"> *</span><span class="identifier-syntax">VH</span><span class="plain-syntax">, </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">invl</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">,</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">allow_implied_newlines</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_1" class="named-paragraph-link"><span class="named-paragraph">Check that the list is in canonical form</span><span class="named-paragraph-number">1.1</span></a></span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_2" class="named-paragraph-link"><span class="named-paragraph">Tell the holster we intend to generate Inter code</span><span class="named-paragraph-number">1.2</span></a></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">InvocationLists::length</span><span class="plain-syntax">(</span><span class="identifier-syntax">invl</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">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">MATCHING</span><span class="plain-syntax">, </span><span class="string-syntax">"Compiling from %d invocation(s)\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">InvocationLists::length</span><span class="plain-syntax">(</span><span class="identifier-syntax">invl</span><span class="plain-syntax">));</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">source_location</span><span class="plain-syntax"> </span><span class="identifier-syntax">sl</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lexer::word_location</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</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="identifier-syntax">first_inv</span><span class="plain-syntax"> = </span><span class="identifier-syntax">InvocationLists::first_reading</span><span class="plain-syntax">(</span><span class="identifier-syntax">invl</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3" class="named-paragraph-link"><span class="named-paragraph">Use runtime resolution only if necessary</span><span class="named-paragraph-number">1.3</span></a></span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP1_1" class="paragraph-anchor"></a><b>§1.1. </b>The invocation list has already been typechecked by <a href="../values-module/5-dsh.html" class="internal">Dash (in values)</a>. This
|
|
means that any invocation which could be disproved has been removed, and what's
|
|
left is either "proven" — i.e., certain to be applicable — or "unproven" —
|
|
i.e., only applicable if certain runtime checks are performed.
|
|
</p>
|
|
|
|
<p class="commentary">Here we check that the list does indeed contain 0 or more unproven invocations
|
|
followed by 0 or 1 proven ones, and that all invocations have the same number
|
|
of tokens.
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Check that the list is in canonical form</span><span class="named-paragraph-number">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">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_proven</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">no_unproven</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">common_token_count</span><span class="plain-syntax"> = -1, </span><span class="identifier-syntax">noncanonical</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">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">inv</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_THROUGH_INVOCATION_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">, </span><span class="identifier-syntax">invl</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">N</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Invocations::get_no_tokens</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</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">common_token_count</span><span class="plain-syntax"> == -1) </span><span class="identifier-syntax">common_token_count</span><span class="plain-syntax"> = </span><span class="identifier-syntax">N</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">common_token_count</span><span class="plain-syntax"> != </span><span class="identifier-syntax">N</span><span class="plain-syntax">) </span><span class="identifier-syntax">noncanonical</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">Invocations::is_marked_unproven</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">)) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">no_unproven</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">no_proven</span><span class="plain-syntax"> > </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">noncanonical</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">no_proven</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">no_proven</span><span class="plain-syntax"> > </span><span class="constant-syntax">1</span><span class="plain-syntax">) </span><span class="identifier-syntax">noncanonical</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</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">noncanonical</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_THROUGH_INVOCATION_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">, </span><span class="identifier-syntax">invl</span><span class="plain-syntax">) </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"$e\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">inv</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">"invocation list not in canonical form"</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> }</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP1">§1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_2" class="paragraph-anchor"></a><b>§1.2. </b>In fact it is impossible for this to be called with <span class="extract"><span class="extract-syntax">VH->vhmode_wanted</span></span> set to
|
|
anything other than <span class="extract"><span class="extract-syntax">INTER_VAL_VHMODE</span></span> or <span class="extract"><span class="extract-syntax">INTER_VOID_VHMODE</span></span>.
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Tell the holster we intend to generate Inter code</span><span class="named-paragraph-number">1.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="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">VH</span><span class="plain-syntax">-></span><span class="identifier-syntax">vhmode_wanted</span><span class="plain-syntax"> == </span><span class="identifier-syntax">INTER_VAL_VHMODE</span><span class="plain-syntax">) </span><span class="identifier-syntax">VH</span><span class="plain-syntax">-></span><span class="identifier-syntax">vhmode_provided</span><span class="plain-syntax"> = </span><span class="identifier-syntax">INTER_VAL_VHMODE</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">VH</span><span class="plain-syntax">-></span><span class="identifier-syntax">vhmode_provided</span><span class="plain-syntax"> = </span><span class="identifier-syntax">INTER_VOID_VHMODE</span><span class="plain-syntax">;</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP1">§1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_3" class="paragraph-anchor"></a><b>§1.3. </b>Our task is to compile code which executes the first applicable invocation. If
|
|
there is any possibility that none are, we must generate code to produce a
|
|
runtime problem message in that case.
|
|
</p>
|
|
|
|
<p class="commentary">Since the list is in canonical form, if the first invocation is proven then it
|
|
is the only one, and therefore no runtime resolution will be needed.
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Use runtime resolution only if necessary</span><span class="named-paragraph-number">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">Invocations::is_marked_unproven</span><span class="plain-syntax">(</span><span class="identifier-syntax">first_inv</span><span class="plain-syntax">)) {</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1" class="named-paragraph-link"><span class="named-paragraph">Compile using runtime resolution to choose between invocations</span><span class="named-paragraph-number">1.3.1</span></a></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="reserved-syntax">tokens_packet</span><span class="plain-syntax"> </span><span class="identifier-syntax">tokens</span><span class="plain-syntax"> = </span><a href="5-ci.html#SP4" class="function-link"><span class="function-syntax">CompileInvocations::new_tokens_packet</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">first_inv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><a href="5-ci.html#SP2" class="function-link"><span class="function-syntax">CompileInvocations::single</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">VH</span><span class="plain-syntax">, </span><span class="identifier-syntax">first_inv</span><span class="plain-syntax">, &</span><span class="identifier-syntax">sl</span><span class="plain-syntax">, &</span><span class="identifier-syntax">tokens</span><span class="plain-syntax">, </span><span class="identifier-syntax">allow_implied_newlines</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> }</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP1">§1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_3_1" class="paragraph-anchor"></a><b>§1.3.1. </b>We get to here if the first invocation is unproven, meaning that at compile
|
|
time it was impossible to determine whether it was type-safe to execute. We must
|
|
therefore compile code to determine this at runtime.
|
|
</p>
|
|
|
|
<p class="commentary">There are two basic forms of this: "void mode", where the phrases are going to
|
|
be Inform 6 statements in a void context, and "value mode", where the phrases
|
|
will be expressions being evaluated.
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile using runtime resolution to choose between invocations</span><span class="named-paragraph-number">1.3.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="identifier-syntax">id_body</span><span class="plain-syntax"> *</span><span class="identifier-syntax">idb</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::get_phrase_invoked</span><span class="plain-syntax">(</span><span class="identifier-syntax">first_inv</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">void_mode</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">idb</span><span class="plain-syntax">-></span><span class="identifier-syntax">type_data</span><span class="plain-syntax">.</span><span class="identifier-syntax">manner_of_return</span><span class="plain-syntax"> == </span><span class="identifier-syntax">DECIDES_NOTHING_MOR</span><span class="plain-syntax">) </span><span class="identifier-syntax">void_mode</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2" class="named-paragraph-link"><span class="named-paragraph">Compile the resolution</span><span class="named-paragraph-number">1.3.1.2</span></a></span><span class="plain-syntax">;</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP1_3">§1.3</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_3_1_1" class="paragraph-anchor"></a><b>§1.3.1.1. </b>Our basic idea is best explained in void mode, where it's much simpler to
|
|
carry out. Suppose we have invocations I1, ..., In, and tokens T1, ..., Tm.
|
|
(In a group like this, every invocation will have the same number of tokens.)
|
|
We want each invocation in turn to try to handle the situation, and to stop
|
|
as soon as one of them does. The first thought is this:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> if (condition for I1 to be valid) invoke I1(T1, ..., Tm);</span>
|
|
<span class="plain-syntax"> else if (condition for I2 to be valid) invoke I2(T1, ..., Tm);</span>
|
|
<span class="plain-syntax"> ...</span>
|
|
<span class="plain-syntax"> else runtime-error-message();</span>
|
|
</pre>
|
|
<p class="commentary">where the chain of execution runs into the error message code only if none
|
|
of I1, ..., In can be applied. In the case where the final invocation is
|
|
proven, we can more simply do this:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> if (condition for I1 to be valid) invoke I1(T1, ..., Tm);</span>
|
|
<span class="plain-syntax"> else if (condition for I2 to be valid) invoke I2(T1, ..., Tm);</span>
|
|
<span class="plain-syntax"> else invoke In(T1, ..., Tm);</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP1_3_1_2" class="paragraph-anchor"></a><b>§1.3.1.2. </b>That's almost what we do, but not quite. The problem lies in the fact that
|
|
the tokens <span class="extract"><span class="extract-syntax">T1</span></span>, ..., <span class="extract"><span class="extract-syntax">Tm</span></span> are evaluated multiple times - not in the invocations
|
|
(since only one is reached in execution) but in the condition tests. This
|
|
multiple evaluation would be incorrect if token evaluation had side-effects,
|
|
as it easily might, and would also waste time if the tokens were slow to evaluate.
|
|
So in fact we modify our scheme like so:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> F1 = T1;</span>
|
|
<span class="plain-syntax"> F2 = T2;</span>
|
|
<span class="plain-syntax"> ...</span>
|
|
<span class="plain-syntax"> if (condition for I1 to be valid) invoke I1(F1, ..., Fm);</span>
|
|
<span class="plain-syntax"> else if (condition for I2 to be valid) invoke I2(F1, ..., Fm);</span>
|
|
<span class="plain-syntax"> ...</span>
|
|
<span class="plain-syntax"> else runtime-error-message();</span>
|
|
</pre>
|
|
<p class="commentary">Here <span class="extract"><span class="extract-syntax">F1, ..., Fn</span></span> are called the "formal parameters". But now we have a tricky
|
|
issue to contend with: where can they be stored?
|
|
</p>
|
|
|
|
<p class="commentary">Here are the answers I thought of in turn:
|
|
</p>
|
|
|
|
<ul class="items"><li>● Make <span class="extract"><span class="extract-syntax">F1, ..., Fn</span></span> local variables for the current function. Often works
|
|
but not always, since some of our eventual target VMs have low upper limits
|
|
on the number of locals in any one function.
|
|
</li><li>● Put <span class="extract"><span class="extract-syntax">F1, ..., Fn</span></span> on the call stack for the current function. Impossible
|
|
because the Inter VM has no memory access to its call stack, a restriction
|
|
forced on Inter by the nature of the Z-machine and Glulx VMs it is a bridge to.
|
|
</li><li>● Have <span class="extract"><span class="extract-syntax">F1, ..., Fn</span></span> be global variables. Impossible because they have to be
|
|
local in scope since evaluation of <span class="extract"><span class="extract-syntax">T2</span></span>, say, might itself involve a call to
|
|
another phrase which needs to make a resolution itself.
|
|
</li><li>● Have <span class="extract"><span class="extract-syntax">F1, ..., Fn</span></span> be global variables, but push copies to the call stack
|
|
before the resolution, and pull them back afterwards, thus using only saved
|
|
copies. This sometimes works in void context (if we are careful to avoid cases
|
|
where the phrase invoked might perform a jump or return), but is impossible
|
|
in value context, where the Inter <span class="extract"><span class="extract-syntax">PUSH_BIP</span></span> and <span class="extract"><span class="extract-syntax">PULL_BIP</span></span> opcodes are illegal.
|
|
</li><li>● Force the current function to be a kernel function inside an outer shell
|
|
function, and then allocate <span class="extract"><span class="extract-syntax">F1, ..., Fn</span></span> as memory in the <span class="extract"><span class="extract-syntax">I7SFRAME</span></span> space
|
|
provided by the shell function. This works, but is slower to access, and forces
|
|
us to have a memory stack, which can be a problem if we are compiling for a
|
|
very tight Z-machine memory.
|
|
</li><li>● Force the current function to be a kernel function inside an outer shell
|
|
function, but have <span class="extract"><span class="extract-syntax">F1, ..., Fn</span></span> be global variables anyway. In the shell
|
|
function, push copies of <span class="extract"><span class="extract-syntax">F1, ..., Fn</span></span> to the call stack before calling the
|
|
kernel, and then pull these saved values back afterwards. This one, finally,
|
|
works in all cases, and is what we do.
|
|
</li></ul>
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile the resolution</span><span class="named-paragraph-number">1.3.1.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="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">N</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Invocations::get_no_tokens</span><span class="plain-syntax">(</span><span class="identifier-syntax">first_inv</span><span class="plain-syntax">); </span><span class="comment-syntax"> must be > 0, or we would be proven</span>
|
|
<span class="plain-syntax"> </span><a href="3-sf.html#SP12" class="function-link"><span class="function-syntax">Frames::need_at_least_this_many_formals</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">N</span><span class="plain-syntax">); </span><span class="comment-syntax"> forces the existence of a shell function</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">void_mode</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_1" class="named-paragraph-link"><span class="named-paragraph">Compile the resolution in void mode</span><span class="named-paragraph-number">1.3.1.2.1</span></a></span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_2" class="named-paragraph-link"><span class="named-paragraph">Compile the resolution in value mode</span><span class="named-paragraph-number">1.3.1.2.2</span></a></span><span class="plain-syntax">;</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP1_3_1">§1.3.1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_3_1_2_1" class="paragraph-anchor"></a><b>§1.3.1.2.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile the resolution in void mode</span><span class="named-paragraph-number">1.3.1.2.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">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="plain-syntax"><</span><span class="identifier-syntax">N</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++)</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_1_2" class="named-paragraph-link"><span class="named-paragraph">Set the ith formal parameter to the ith token value</span><span class="named-paragraph-number">1.3.1.2.1.2</span></a></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">pos</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">if_depth</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">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">inv</span><span class="plain-syntax">, *</span><span class="identifier-syntax">last_inv</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">LOOP_THROUGH_INVOCATION_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">, </span><span class="identifier-syntax">invl</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">MATCHING</span><span class="plain-syntax">, </span><span class="string-syntax">"RC%d: $e\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="identifier-syntax">inv</span><span class="plain-syntax">); </span><span class="identifier-syntax">pos</span><span class="plain-syntax">++;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">last_inv</span><span class="plain-syntax"> = </span><span class="identifier-syntax">inv</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">if_depth</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">EmitCode::up</span><span class="plain-syntax">();</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::code</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="plain-syntax"> </span><span class="reserved-syntax">tokens_packet</span><span class="plain-syntax"> </span><span class="identifier-syntax">tokens</span><span class="plain-syntax"> = </span><a href="5-ci.html#SP4" class="function-link"><span class="function-syntax">CompileInvocations::new_tokens_packet</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_1_3" class="named-paragraph-link"><span class="named-paragraph">Substitute the formal parameters into the tokens packet</span><span class="named-paragraph-number">1.3.1.2.1.3</span></a></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">Invocations::is_marked_unproven</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</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">IFELSE_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="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_1_1" class="named-paragraph-link"><span class="named-paragraph">Put the condition check here</span><span class="named-paragraph-number">1.3.1.2.1.1</span></a></span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::code</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">if_depth</span><span class="plain-syntax">++;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><a href="5-ci.html#SP2" class="function-link"><span class="function-syntax">CompileInvocations::single</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">VH</span><span class="plain-syntax">, </span><span class="identifier-syntax">inv</span><span class="plain-syntax">, &</span><span class="identifier-syntax">sl</span><span class="plain-syntax">, &</span><span class="identifier-syntax">tokens</span><span class="plain-syntax">, </span><span class="identifier-syntax">allow_implied_newlines</span><span class="plain-syntax">);</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">Invocations::is_marked_unproven</span><span class="plain-syntax">(</span><span class="identifier-syntax">last_inv</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::code</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="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_1_4" class="named-paragraph-link"><span class="named-paragraph">Compile call to function throwing an RTP</span><span class="named-paragraph-number">1.3.1.2.1.4</span></a></span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">if_depth</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">EmitCode::up</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">if_depth</span><span class="plain-syntax">--;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP1_3_1_2">§1.3.1.2</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_3_1_2_1_1" class="paragraph-anchor"></a><b>§1.3.1.2.1.1. </b>There may be checks needed on several tokens, so we accumulate these into
|
|
a list divided by logical-and <span class="extract"><span class="extract-syntax">&&</span></span> operators.
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Put the condition check here</span><span class="named-paragraph-number">1.3.1.2.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">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">check_needed</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">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="plain-syntax"><</span><span class="identifier-syntax">Invocations::get_no_tokens</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</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">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">check_against</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Invocations::get_token_check_to_do</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</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">check_against</span><span class="plain-syntax">) </span><span class="identifier-syntax">check_needed</span><span class="plain-syntax">++;</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">check_count</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">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="plain-syntax"><</span><span class="identifier-syntax">Invocations::get_no_tokens</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</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">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">check_against</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Invocations::get_token_check_to_do</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</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">check_against</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">check_count</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">check_count</span><span class="plain-syntax"> < </span><span class="identifier-syntax">check_needed</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">AND_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="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_1_1_1" class="named-paragraph-link"><span class="named-paragraph">Compile a check that this formal variable matches the token</span><span class="named-paragraph-number">1.3.1.2.1.1.1</span></a></span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</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">check_count</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"this should not be marked unproven"</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"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax"> <= </span><span class="identifier-syntax">check_count</span><span class="plain-syntax"> - </span><span class="constant-syntax">1</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</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="5-ci.html#SP1_3_1_2_1">§1.3.1.2.1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_3_1_2_1_1_1" class="paragraph-anchor"></a><b>§1.3.1.2.1.1.1. </b>The check is either against a general description, such as "even number", or
|
|
a specific value, such as "10".
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile a check that this formal variable matches the token</span><span class="named-paragraph-number">1.3.1.2.1.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="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">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">spec</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lvalues::new_actual_NONLOCAL_VARIABLE</span><span class="plain-syntax">(</span><span class="identifier-syntax">nlv</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">Specifications::is_description</span><span class="plain-syntax">(</span><span class="identifier-syntax">check_against</span><span class="plain-syntax">)) {</span>
|
|
<span class="plain-syntax"> </span><a href="4-cp.html#SP3" class="function-link"><span class="function-syntax">CompilePropositions::to_test_if_variable_matches</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">spec</span><span class="plain-syntax">, </span><span class="identifier-syntax">check_against</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Specifications::is_value</span><span class="plain-syntax">(</span><span class="identifier-syntax">check_against</span><span class="plain-syntax">)) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">pcalc_prop</span><span class="plain-syntax"> *</span><span class="identifier-syntax">prop</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Propositions::Abstract::to_set_relation</span><span class="plain-syntax">(</span><span class="identifier-syntax">R_equality</span><span class="plain-syntax">,</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">spec</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">check_against</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><a href="4-cp.html#SP1" class="function-link"><span class="function-syntax">CompilePropositions::to_test_as_condition</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">prop</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">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Error on: $T"</span><span class="plain-syntax">, </span><span class="identifier-syntax">check_against</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">"bad check-against in runtime type check"</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> }</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP1_3_1_2_1_1">§1.3.1.2.1.1</a>, <a href="5-ci.html#SP1_3_1_2_2_2_1_1_1">§1.3.1.2.2.2.1.1.1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_3_1_2_1_2" class="paragraph-anchor"></a><b>§1.3.1.2.1.2. </b>A parameter corresponding to the name of a kind has no meaningful value
|
|
at runtime; we assign 0 to it for the sake of tidiness.
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Set the ith formal parameter to the ith token value</span><span class="named-paragraph-number">1.3.1.2.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-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::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_iname</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_value</span><span class="plain-syntax">,</span>
|
|
<span class="plain-syntax"> </span><a href="3-tv.html#SP2" class="function-link"><span class="function-syntax">TemporaryVariables::iname_of_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="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">idb</span><span class="plain-syntax">-></span><span class="identifier-syntax">type_data</span><span class="plain-syntax">.</span><span class="identifier-syntax">token_sequence</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">].</span><span class="identifier-syntax">construct</span><span class="plain-syntax"> == </span><span class="identifier-syntax">KIND_NAME_IDTC</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::val_number</span><span class="plain-syntax">(0);</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">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">value</span><span class="plain-syntax"> =</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">Invocations::get_token_as_parsed</span><span class="plain-syntax">(</span><span class="identifier-syntax">first_inv</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">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">to_be_used_as</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Specifications::to_kind</span><span class="plain-syntax">(</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">idb</span><span class="plain-syntax">-></span><span class="identifier-syntax">type_data</span><span class="plain-syntax">.</span><span class="identifier-syntax">token_sequence</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">].</span><span class="identifier-syntax">to_match</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><a href="2-cv.html#SP5" class="function-link"><span class="function-syntax">CompileValues::to_fresh_code_val_of_kind</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">value</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_be_used_as</span><span class="plain-syntax">);</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="5-ci.html#SP1_3_1_2_1">§1.3.1.2.1</a>, <a href="5-ci.html#SP1_3_1_2_2_1">§1.3.1.2.2.1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_3_1_2_1_3" class="paragraph-anchor"></a><b>§1.3.1.2.1.3. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Substitute the formal parameters into the tokens packet</span><span class="named-paragraph-number">1.3.1.2.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">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="plain-syntax"><</span><span class="identifier-syntax">tokens</span><span class="plain-syntax">.</span><span class="element-syntax">tokens_count</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">NonlocalVariables::set_kind</span><span class="plain-syntax">(</span><span class="identifier-syntax">nlv</span><span class="plain-syntax">, </span><span class="identifier-syntax">tokens</span><span class="plain-syntax">.</span><span class="element-syntax">token_kinds</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">tokens</span><span class="plain-syntax">.</span><span class="element-syntax">token_vals</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="identifier-syntax">Lvalues::new_actual_NONLOCAL_VARIABLE</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="5-ci.html#SP1_3_1_2_1">§1.3.1.2.1</a>, <a href="5-ci.html#SP1_3_1_2_2_2_1">§1.3.1.2.2.2.1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_3_1_2_1_4" class="paragraph-anchor"></a><b>§1.3.1.2.1.4. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile call to function throwing an RTP</span><span class="named-paragraph-number">1.3.1.2.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="identifier-syntax">EmitCode::call</span><span class="plain-syntax">(</span><span class="identifier-syntax">Hierarchy::find</span><span class="plain-syntax">(</span><span class="identifier-syntax">ARGUMENTTYPEFAILED_HL</span><span class="plain-syntax">));</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::down</span><span class="plain-syntax">();</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::val_number</span><span class="plain-syntax">((</span><span class="identifier-syntax">inter_ti</span><span class="plain-syntax">) </span><span class="identifier-syntax">sl</span><span class="plain-syntax">.</span><span class="identifier-syntax">line_number</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">inform_extension</span><span class="plain-syntax"> *</span><span class="identifier-syntax">E</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Extensions::corresponding_to</span><span class="plain-syntax">(</span><span class="identifier-syntax">sl</span><span class="plain-syntax">.</span><span class="identifier-syntax">file_of_origin</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">E</span><span class="plain-syntax">) </span><span class="identifier-syntax">EmitCode::val_number</span><span class="plain-syntax">((</span><span class="identifier-syntax">inter_ti</span><span class="plain-syntax">) </span><span class="identifier-syntax">E</span><span class="plain-syntax">-></span><span class="identifier-syntax">allocation_id</span><span class="plain-syntax"> + </span><span class="constant-syntax">1</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::up</span><span class="plain-syntax">();</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP1_3_1_2_1">§1.3.1.2.1</a>, <a href="5-ci.html#SP1_3_1_2_2_2">§1.3.1.2.2.2</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_3_1_2_2" class="paragraph-anchor"></a><b>§1.3.1.2.2. </b>In value mode we want the same strategy and code paths, but all in the context
|
|
of a value. This means we can only use Inter opcodes which are legal in a value
|
|
context, making everything harder.
|
|
</p>
|
|
|
|
<p class="commentary">The <span class="extract"><span class="extract-syntax">TERNARYSEQUENTIAL_BIP</span></span> opcode is similar to evaluating <span class="extract"><span class="extract-syntax">x, y, z</span></span> in C: it
|
|
evaluates <span class="extract"><span class="extract-syntax">x</span></span>, throws that away, evaluates <span class="extract"><span class="extract-syntax">y</span></span>, ditto, then evaluates <span class="extract"><span class="extract-syntax">z</span></span> as
|
|
its answer. <span class="extract"><span class="extract-syntax">x</span></span> and <span class="extract"><span class="extract-syntax">y</span></span> are thus evaluated only for and side-effects that has.
|
|
Here <span class="extract"><span class="extract-syntax">x</span></span> is going to be code to set the formal parameters; <span class="extract"><span class="extract-syntax">y</span></span> will be code
|
|
to test the conditions for invocation and invoke one of them into a dummy
|
|
variable called <span class="extract"><span class="extract-syntax">formal_rv</span></span>; and <span class="extract"><span class="extract-syntax">z</span></span> will simply evaluate <span class="extract"><span class="extract-syntax">formal_rv</span></span>, thus
|
|
producing the answer.
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile the resolution in value mode</span><span class="named-paragraph-number">1.3.1.2.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">EmitCode::inv</span><span class="plain-syntax">(</span><span class="identifier-syntax">TERNARYSEQUENTIAL_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="comment-syntax"> Here is x:</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_2_1" class="named-paragraph-link"><span class="named-paragraph">Set the formal parameters in value mode</span><span class="named-paragraph-number">1.3.1.2.2.1</span></a></span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="comment-syntax"> Here is y:</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_2_2" class="named-paragraph-link"><span class="named-paragraph">Perform the tests and invocations in value mode</span><span class="named-paragraph-number">1.3.1.2.2.2</span></a></span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="comment-syntax"> Here is z:</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::val_iname</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">Hierarchy::find</span><span class="plain-syntax">(</span><span class="identifier-syntax">FORMAL_RV_HL</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="5-ci.html#SP1_3_1_2">§1.3.1.2</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_3_1_2_2_1" class="paragraph-anchor"></a><b>§1.3.1.2.2.1. </b>In Inter, as in C, assignments return a value and are therefore legal here.
|
|
But because Inter does not provide a binary sequential opcode, we will fold
|
|
our run of assignments into a single value by adding them up — the result
|
|
doesn't matter, since it will be thrown away anyway. So if there are, say,
|
|
four formal parameters then our <span class="extract"><span class="extract-syntax">x</span></span> will be:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> (F4 = T4) + ((F3 = T3) + ((F2 = T2) + (F1 = T1)))</span>
|
|
</pre>
|
|
<p class="commentary">It isn't really important that we count downwards from 4 to 1 here, but we do
|
|
it because the Inform 6 compiler happens to evaluate operands of <span class="extract"><span class="extract-syntax">+</span></span> in the
|
|
order right then left. So this actually causes <span class="extract"><span class="extract-syntax">T1</span></span> to evaluate first, then <span class="extract"><span class="extract-syntax">T2</span></span>
|
|
and so on, provided Inform 6 is the eventual code generator.
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Set the formal parameters in value mode</span><span class="named-paragraph-number">1.3.1.2.2.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">L</span><span class="plain-syntax"> = </span><span class="identifier-syntax">EmitCode::level</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"> = </span><span class="identifier-syntax">N</span><span class="plain-syntax">-1; </span><span class="identifier-syntax">i</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</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">i</span><span class="plain-syntax"> > </span><span class="constant-syntax">0</span><span class="plain-syntax">) { </span><span class="identifier-syntax">EmitCode::inv</span><span class="plain-syntax">(</span><span class="identifier-syntax">PLUS_BIP</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="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_1_2" class="named-paragraph-link"><span class="named-paragraph">Set the ith formal parameter to the ith token value</span><span class="named-paragraph-number">1.3.1.2.1.2</span></a></span><span class="plain-syntax">;</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"> = </span><span class="identifier-syntax">N</span><span class="plain-syntax">-1; </span><span class="identifier-syntax">i</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</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">i</span><span class="plain-syntax"> > </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">EmitCode::up</span><span class="plain-syntax">();</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">L</span><span class="plain-syntax"> != </span><span class="identifier-syntax">EmitCode::level</span><span class="plain-syntax">()) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"misimplemented"</span><span class="plain-syntax">);</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP1_3_1_2_2">§1.3.1.2.2</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_3_1_2_2_2" class="paragraph-anchor"></a><b>§1.3.1.2.2.2. </b>Now the fun really begins. We compile <span class="extract"><span class="extract-syntax">y</span></span> to an expression like so:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> ((condition for I1 to be valid) && ((formal_rv = I1) bitwise-or 1)) ||</span>
|
|
<span class="plain-syntax"> ((condition for I2 to be valid) && ((formal_rv = I2) bitwise-or 1)) ||</span>
|
|
<span class="plain-syntax"> ...</span>
|
|
<span class="plain-syntax"> ((condition for In to be valid) && ((formal_rv = In) bitwise-or 1)) ||</span>
|
|
<span class="plain-syntax"> (issue run-time-problem)</span>
|
|
</pre>
|
|
<p class="commentary">The key here is that Inter, like C, evaluates operands of <span class="extract"><span class="extract-syntax">&&</span></span> left to right
|
|
and short-circuits: if the left operand is false, the right is never evaluated,
|
|
and its side-effect (of invoking a phrase and setting <span class="extract"><span class="extract-syntax">formal_rv</span></span>) never
|
|
happens; and similarly for logical-or.
|
|
</p>
|
|
|
|
<p class="commentary">Bitwise-or does not short-circuit, so the faintly ridiculous trick of
|
|
bitwise-or-ing with 1 ensures that any value is made non-zero, so that the
|
|
assignment is always regarded by Inter as "true". This all means that if
|
|
any condition is valid, no subsequent conditions will even be tested.
|
|
</p>
|
|
|
|
<p class="commentary">Note that all functions return values in Inter, so the function call to issue
|
|
the run-time problem is indeed legal in a value context.
|
|
</p>
|
|
|
|
<p class="commentary">Matters are a little simpler if the final invocation is proven:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> ((condition for I1 to be valid) && ((formal_rv = I1) bitwise-or 1)) ||</span>
|
|
<span class="plain-syntax"> ((condition for I2 to be valid) && ((formal_rv = I2) bitwise-or 1)) ||</span>
|
|
<span class="plain-syntax"> ...</span>
|
|
<span class="plain-syntax"> ((formal_rv = In) bitwise-or 1)</span>
|
|
</pre>
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Perform the tests and invocations in value mode</span><span class="named-paragraph-number">1.3.1.2.2.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="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">L</span><span class="plain-syntax"> = </span><span class="identifier-syntax">EmitCode::level</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">number_unproven</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">last_is_unproven</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">inv</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_THROUGH_INVOCATION_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">, </span><span class="identifier-syntax">invl</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">Invocations::is_marked_unproven</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">)) </span><span class="identifier-syntax">number_unproven</span><span class="plain-syntax">++;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">last_is_unproven</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">last_is_unproven</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">OR_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="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_2_2_1" class="named-paragraph-link"><span class="named-paragraph">Perform the tests and invocations without RTP in value mode</span><span class="named-paragraph-number">1.3.1.2.2.2.1</span></a></span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">last_is_unproven</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_1_4" class="named-paragraph-link"><span class="named-paragraph">Compile call to function throwing an RTP</span><span class="named-paragraph-number">1.3.1.2.1.4</span></a></span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::up</span><span class="plain-syntax">();</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">L</span><span class="plain-syntax"> != </span><span class="identifier-syntax">EmitCode::level</span><span class="plain-syntax">()) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"misimplemented"</span><span class="plain-syntax">);</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP1_3_1_2_2">§1.3.1.2.2</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_3_1_2_2_2_1" class="paragraph-anchor"></a><b>§1.3.1.2.2.2.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Perform the tests and invocations without RTP in value mode</span><span class="named-paragraph-number">1.3.1.2.2.2.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">L</span><span class="plain-syntax"> = </span><span class="identifier-syntax">EmitCode::level</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">pos</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_THROUGH_INVOCATION_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">, </span><span class="identifier-syntax">invl</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">MATCHING</span><span class="plain-syntax">, </span><span class="string-syntax">"RC%d: $e\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="identifier-syntax">inv</span><span class="plain-syntax">); </span><span class="identifier-syntax">pos</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">pos</span><span class="plain-syntax"> < </span><span class="identifier-syntax">InvocationLists::length</span><span class="plain-syntax">(</span><span class="identifier-syntax">invl</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">OR_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="plain-syntax"> </span><span class="reserved-syntax">tokens_packet</span><span class="plain-syntax"> </span><span class="identifier-syntax">tokens</span><span class="plain-syntax"> = </span><a href="5-ci.html#SP4" class="function-link"><span class="function-syntax">CompileInvocations::new_tokens_packet</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_1_3" class="named-paragraph-link"><span class="named-paragraph">Substitute the formal parameters into the tokens packet</span><span class="named-paragraph-number">1.3.1.2.1.3</span></a></span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_2_2_1_1" class="named-paragraph-link"><span class="named-paragraph">Compile code to apply this invocation if it's applicable, value mode</span><span class="named-paragraph-number">1.3.1.2.2.2.1.1</span></a></span><span class="plain-syntax">;</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"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax"> <= </span><span class="identifier-syntax">InvocationLists::length</span><span class="plain-syntax">(</span><span class="identifier-syntax">invl</span><span class="plain-syntax">) - </span><span class="constant-syntax">1</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">EmitCode::up</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">L</span><span class="plain-syntax"> != </span><span class="identifier-syntax">EmitCode::level</span><span class="plain-syntax">()) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"misimplemented"</span><span class="plain-syntax">);</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP1_3_1_2_2_2">§1.3.1.2.2.2</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_3_1_2_2_2_1_1" class="paragraph-anchor"></a><b>§1.3.1.2.2.2.1.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile code to apply this invocation if it's applicable, value mode</span><span class="named-paragraph-number">1.3.1.2.2.2.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">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">L</span><span class="plain-syntax"> = </span><span class="identifier-syntax">EmitCode::level</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">ands_made</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_2_2_1_1_1" class="named-paragraph-link"><span class="named-paragraph">Compile the check on invocation applicability, value mode</span><span class="named-paragraph-number">1.3.1.2.2.2.1.1.1</span></a></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">BITWISEOR_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::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_iname</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">Hierarchy::find</span><span class="plain-syntax">(</span><span class="identifier-syntax">FORMAL_RV_HL</span><span class="plain-syntax">));</span>
|
|
<span class="plain-syntax"> </span><a href="5-ci.html#SP2" class="function-link"><span class="function-syntax">CompileInvocations::single</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">VH</span><span class="plain-syntax">, </span><span class="identifier-syntax">inv</span><span class="plain-syntax">, &</span><span class="identifier-syntax">sl</span><span class="plain-syntax">, &</span><span class="identifier-syntax">tokens</span><span class="plain-syntax">, </span><span class="identifier-syntax">allow_implied_newlines</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::val_number</span><span class="plain-syntax">(1);</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">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="plain-syntax"><</span><span class="identifier-syntax">ands_made</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</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">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">L</span><span class="plain-syntax"> != </span><span class="identifier-syntax">EmitCode::level</span><span class="plain-syntax">()) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"misimplemented"</span><span class="plain-syntax">);</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP1_3_1_2_2_2_1">§1.3.1.2.2.2.1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP1_3_1_2_2_2_1_1_1" class="paragraph-anchor"></a><b>§1.3.1.2.2.2.1.1.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile the check on invocation applicability, value mode</span><span class="named-paragraph-number">1.3.1.2.2.2.1.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">Invocations::is_marked_unproven</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</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">checks_made</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">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="plain-syntax"><</span><span class="identifier-syntax">Invocations::get_no_tokens</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</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">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">check_against</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Invocations::get_token_check_to_do</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</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">check_against</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">AND_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="identifier-syntax">ands_made</span><span class="plain-syntax">++;</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP1_3_1_2_1_1_1" class="named-paragraph-link"><span class="named-paragraph">Compile a check that this formal variable matches the token</span><span class="named-paragraph-number">1.3.1.2.1.1.1</span></a></span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">checks_made</span><span class="plain-syntax">++;</span>
|
|
<span class="plain-syntax"> }</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">checks_made</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"this should not be marked unproven"</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> }</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP1_3_1_2_2_2_1_1">§1.3.1.2.2.2.1.1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>§2. Lower level: compiling single invocations. </b></p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">CompileInvocations::single</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">CompileInvocations::single</span></span>:<br/><a href="5-ci.html#SP1_3">§1.3</a>, <a href="5-ci.html#SP1_3_1_2_1">§1.3.1.2.1</a>, <a href="5-ci.html#SP1_3_1_2_2_2_1_1">§1.3.1.2.2.2.1.1</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">value_holster</span><span class="plain-syntax"> *</span><span class="identifier-syntax">VH</span><span class="plain-syntax">, </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">inv</span><span class="plain-syntax">,</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">source_location</span><span class="plain-syntax"> *</span><span class="identifier-syntax">where_from</span><span class="plain-syntax">, </span><span class="reserved-syntax">tokens_packet</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tokens</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">allow_implied_newlines</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">MATCHING</span><span class="plain-syntax">, </span><span class="string-syntax">"Compiling single invocation: $e\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">inv</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">Node::get_say_verb</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">)) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">RTVerbs::ConjugateVerb_invoke_emit</span><span class="plain-syntax">(</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">Node::get_say_verb</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">),</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">Node::get_modal_verb</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">),</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">Annotations::read_int</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">, </span><span class="identifier-syntax">say_verb_negated_ANNOT</span><span class="plain-syntax">));</span>
|
|
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::get_say_adjective</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">)) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">RTAdjectives::invoke</span><span class="plain-syntax">(</span><span class="identifier-syntax">Node::get_say_adjective</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</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="named-paragraph-container code-font"><a href="5-ci.html#SP2_1" class="named-paragraph-link"><span class="named-paragraph">Invoke a phrasal invocation</span><span class="named-paragraph-number">2.1</span></a></span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP2_1" class="paragraph-anchor"></a><b>§2.1. </b>Note that the phrases which compile to Inter jump or return instructions can
|
|
never be marked to save <span class="extract"><span class="extract-syntax">self</span></span>, or the code here would lead to slow stack overflow
|
|
errors, since <span class="extract"><span class="extract-syntax">self</span></span> would be pushed but not pulled.
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Invoke a phrasal invocation</span><span class="named-paragraph-number">2.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">manner_of_return</span><span class="plain-syntax"> = </span><span class="identifier-syntax">DONT_KNOW_MOR</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">save_self</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Invocations::is_marked_to_save_self</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">)) </span><span class="identifier-syntax">save_self</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">save_self</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">PUSH_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_iname</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">Hierarchy::find</span><span class="plain-syntax">(</span><span class="identifier-syntax">SELF_HL</span><span class="plain-syntax">));</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::up</span><span class="plain-syntax">();</span>
|
|
<span class="plain-syntax"> }</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP2_1_2" class="named-paragraph-link"><span class="named-paragraph">The art of invocation is delegation</span><span class="named-paragraph-number">2.1.2</span></a></span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP2_1_3" class="named-paragraph-link"><span class="named-paragraph">Compile a newline if the phrase implicitly requires one</span><span class="named-paragraph-number">2.1.3</span></a></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">save_self</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">PULL_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_iname</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">Hierarchy::find</span><span class="plain-syntax">(</span><span class="identifier-syntax">SELF_HL</span><span class="plain-syntax">));</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::up</span><span class="plain-syntax">();</span>
|
|
<span class="plain-syntax"> }</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">manner_of_return</span><span class="plain-syntax"> != </span><span class="identifier-syntax">DONT_KNOW_MOR</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">MATCHING</span><span class="plain-syntax">, </span><span class="string-syntax">"Single invocation return manner: %d\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">manner_of_return</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-fnc.html#SP4" class="function-link"><span class="function-syntax">Functions::defn_being_compiled</span></a><span class="plain-syntax">()) && (</span><span class="identifier-syntax">manner_of_return</span><span class="plain-syntax"> != </span><span class="identifier-syntax">DONT_KNOW_MOR</span><span class="plain-syntax">))</span>
|
|
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="5-ci.html#SP2_1_1" class="named-paragraph-link"><span class="named-paragraph">If the invocation compiled to a return from a function, check this is allowed</span><span class="named-paragraph-number">2.1.1</span></a></span><span class="plain-syntax">;</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP2">§2</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP2_1_1" class="paragraph-anchor"></a><b>§2.1.1. </b>For example, the definition of the phrase "To begin" isn't allowed to contain the
|
|
invocation "decide on 178", since it isn't a phrase to decide anything. This is
|
|
where that's checked:
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">If the invocation compiled to a return from a function, check this is allowed</span><span class="named-paragraph-number">2.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="identifier-syntax">id_body</span><span class="plain-syntax"> *</span><span class="identifier-syntax">current_idb</span><span class="plain-syntax"> = </span><a href="3-fnc.html#SP4" class="function-link"><span class="function-syntax">Functions::defn_being_compiled</span></a><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">manner_expected</span><span class="plain-syntax"> = </span><span class="identifier-syntax">current_idb</span><span class="plain-syntax">-></span><span class="identifier-syntax">type_data</span><span class="plain-syntax">.</span><span class="identifier-syntax">manner_of_return</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">manner_of_return</span><span class="plain-syntax"> != </span><span class="identifier-syntax">manner_expected</span><span class="plain-syntax">) &&</span>
|
|
<span class="plain-syntax"> (</span><span class="identifier-syntax">manner_expected</span><span class="plain-syntax"> != </span><span class="identifier-syntax">DECIDES_NOTHING_AND_RETURNS_MOR</span><span class="plain-syntax">)) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_source</span><span class="plain-syntax">(1, </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(2,</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">IDTypeData::describe_manner_of_return</span><span class="plain-syntax">(</span><span class="identifier-syntax">manner_of_return</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">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</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">Problems::quote_text</span><span class="plain-syntax">(3,</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">IDTypeData::describe_manner_of_return</span><span class="plain-syntax">(</span><span class="identifier-syntax">manner_expected</span><span class="plain-syntax">,</span>
|
|
<span class="plain-syntax"> &(</span><span class="identifier-syntax">current_idb</span><span class="plain-syntax">-></span><span class="identifier-syntax">type_data</span><span class="plain-syntax">), &</span><span class="identifier-syntax">K</span><span class="plain-syntax">));</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">K</span><span class="plain-syntax">) </span><span class="identifier-syntax">Problems::quote_kind</span><span class="plain-syntax">(4, </span><span class="identifier-syntax">K</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::handmade_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_WrongEndToPhrase</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">K</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::issue_problem_segment</span><span class="plain-syntax">(</span>
|
|
<span class="plain-syntax"> </span><span class="string-syntax">"The line %1 seems to be a way that the phrase you're defining can come "</span>
|
|
<span class="plain-syntax"> </span><span class="string-syntax">"to an end, with %2, but it should always end up with a phrase to "</span>
|
|
<span class="plain-syntax"> </span><span class="string-syntax">"decide %4."</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::issue_problem_segment</span><span class="plain-syntax">(</span>
|
|
<span class="plain-syntax"> </span><span class="string-syntax">"The line %1 seems to be a way that the phrase you're defining can come "</span>
|
|
<span class="plain-syntax"> </span><span class="string-syntax">"to an end, with %2, but it should always end up with %3."</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::issue_problem_end</span><span class="plain-syntax">();</span>
|
|
<span class="plain-syntax"> }</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP2_1">§2.1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP2_1_2" class="paragraph-anchor"></a><b>§2.1.2. </b>The real work is done by one of the two sections following this one. Note that
|
|
only inline invocations are allowed to produce an exotic manner of return — it's
|
|
not possible to define a high-level I7 phrase which effects, say, an immediate
|
|
end to the rule it's used in. Similarly, only inline invocations are allowed
|
|
to be followed by blocks of other phrases — that is, are allowed to define
|
|
control structures.
|
|
</p>
|
|
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">The art of invocation is delegation</span><span class="named-paragraph-number">2.1.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">id_body</span><span class="plain-syntax"> *</span><span class="identifier-syntax">idb</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::get_phrase_invoked</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</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">IDTypeData::invoked_inline</span><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">manner_of_return</span><span class="plain-syntax"> =</span>
|
|
<span class="plain-syntax"> </span><a href="5-cii.html#SP3" class="function-link"><span class="function-syntax">CSIInline::csi_inline</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">VH</span><span class="plain-syntax">, </span><span class="identifier-syntax">inv</span><span class="plain-syntax">, </span><span class="identifier-syntax">where_from</span><span class="plain-syntax">, </span><span class="identifier-syntax">tokens</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
|
|
<span class="plain-syntax"> </span><a href="5-ciac.html#SP1" class="function-link"><span class="function-syntax">CallingFunctions::csi_by_call</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">VH</span><span class="plain-syntax">, </span><span class="identifier-syntax">inv</span><span class="plain-syntax">, </span><span class="identifier-syntax">where_from</span><span class="plain-syntax">, </span><span class="identifier-syntax">tokens</span><span class="plain-syntax">);</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP2_1">§2.1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP2_1_3" class="paragraph-anchor"></a><b>§2.1.3. </b>If <span class="extract"><span class="extract-syntax">allow_implied_newlines</span></span> is set, we understand the final part of a
|
|
text literal to be allowed to print an implied newline. For example, here it's on:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">say</span><span class="plain-syntax"> </span><span class="string-syntax">"At [time of day], I like to serve afternoon tea. Indian or Chinese?"</span><span class="plain-syntax">;</span>
|
|
</pre>
|
|
<p class="commentary">Here the question mark has an implied newline after it. But there are other
|
|
contexts in which newlines are not implied:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">let</span><span class="plain-syntax"> </span><span class="identifier-syntax">the</span><span class="plain-syntax"> </span><span class="identifier-syntax">warning</span><span class="plain-syntax"> </span><span class="identifier-syntax">rubric</span><span class="plain-syntax"> </span><span class="identifier-syntax">be</span><span class="plain-syntax"> </span><span class="string-syntax">"Snakes!"</span><span class="plain-syntax">;</span>
|
|
</pre>
|
|
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Compile a newline if the phrase implicitly requires one</span><span class="named-paragraph-number">2.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">IDTypeData::is_a_say_phrase</span><span class="plain-syntax">(</span><span class="identifier-syntax">Node::get_phrase_invoked</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</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">Node::get_phrase_invoked</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">)-></span><span class="identifier-syntax">type_data</span><span class="plain-syntax">.</span><span class="identifier-syntax">as_say</span><span class="plain-syntax">.</span><span class="identifier-syntax">say_phrase_running_on</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">allow_implied_newlines</span><span class="plain-syntax">) &&</span>
|
|
<span class="plain-syntax"> (</span><span class="identifier-syntax">tokens</span><span class="plain-syntax">-></span><span class="element-syntax">tokens_count</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">Rvalues::is_CONSTANT_of_kind</span><span class="plain-syntax">(</span><span class="identifier-syntax">tokens</span><span class="plain-syntax">-></span><span class="element-syntax">token_vals</span><span class="plain-syntax">[0], </span><span class="identifier-syntax">K_text</span><span class="plain-syntax">)) &&</span>
|
|
<span class="plain-syntax"> (</span><span class="identifier-syntax">Word::text_ending_sentence</span><span class="plain-syntax">(</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">Node::get_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">tokens</span><span class="plain-syntax">-></span><span class="element-syntax">token_vals</span><span class="plain-syntax">[0]))))) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::inv</span><span class="plain-syntax">(</span><span class="identifier-syntax">PRINT_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_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">I</span><span class="string-syntax">"\n"</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">EmitCode::up</span><span class="plain-syntax">();</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> }</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>This code is used in <a href="5-ci.html#SP2_1">§2.1</a>.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>§3. Tokens packets. </b>This structure is a convenient holder for the token values being used when
|
|
invoking a phrase, and for what we think their kinds are.
|
|
</p>
|
|
|
|
<p class="commentary">In many cases that will not be much of an issue, but suppose the phrase to be
|
|
invoked is polymorphic, like so —
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="identifier-syntax">To</span><span class="plain-syntax"> </span><span class="identifier-syntax">discuss</span><span class="plain-syntax"> (</span><span class="identifier-syntax">V</span><span class="plain-syntax"> - </span><span class="identifier-syntax">sayable</span><span class="plain-syntax"> </span><span class="identifier-syntax">value</span><span class="plain-syntax">):</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">say</span><span class="plain-syntax"> </span><span class="string-syntax">"You discourse about [V]."</span>
|
|
</pre>
|
|
<p class="commentary">If the invocation is "discuss 16", then the token has kind <span class="extract"><span class="extract-syntax">K_number</span></span> not
|
|
<span class="extract"><span class="extract-syntax">K_sayable_value</span></span>, because we derive the kind from what the phrase was actually
|
|
invoked on rather than the full range of what it might have been. Similarly,
|
|
the <span class="extract"><span class="extract-syntax">fn_kind</span></span> is <span class="extract"><span class="extract-syntax">function number -> nothing</span></span>, not <span class="extract"><span class="extract-syntax">function sayable value -> nothing</span></span>.
|
|
</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">tokens_packet</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">tokens_count</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">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">token_vals</span><span class="plain-syntax">[</span><span class="identifier-syntax">MAX_TOKENS_PER_PHRASE</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">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">token_kinds</span><span class="plain-syntax">[</span><span class="identifier-syntax">MAX_TOKENS_PER_PHRASE</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">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">fn_kind</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">} </span><span class="reserved-syntax">tokens_packet</span><span class="plain-syntax">;</span>
|
|
</pre>
|
|
<ul class="endnotetexts"><li>The structure tokens_packet is accessed in 3/cb, 5/ciac, 5/cii and here.</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>§4. </b>This is all easy to unpack from the invocation subtree.
|
|
</p>
|
|
|
|
<p class="commentary">If a token holds the name of a kind rather than a value as such, we use the
|
|
<span class="extract"><span class="extract-syntax">nothing</span></span> constant as the "token value", just as a placeholder. It won't be compiled.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">tokens_packet</span><span class="plain-syntax"> </span><span class="function-syntax">CompileInvocations::new_tokens_packet</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">CompileInvocations::new_tokens_packet</span></span>:<br/><a href="5-ci.html#SP1_3">§1.3</a>, <a href="5-ci.html#SP1_3_1_2_1">§1.3.1.2.1</a>, <a href="5-ci.html#SP1_3_1_2_2_2_1">§1.3.1.2.2.2.1</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">inv</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="identifier-syntax">Node::get_phrase_invoked</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">tokens_packet</span><span class="plain-syntax"> </span><span class="identifier-syntax">tokens</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">tokens</span><span class="plain-syntax">.</span><span class="identifier-syntax">tokens_count</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Invocations::get_no_tokens_needed</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</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="plain-syntax"><</span><span class="identifier-syntax">tokens</span><span class="plain-syntax">.</span><span class="element-syntax">tokens_count</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">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">val</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Invocations::get_token_as_parsed</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</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">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Specifications::to_kind</span><span class="plain-syntax">(</span><span class="identifier-syntax">idb</span><span class="plain-syntax">-></span><span class="identifier-syntax">type_data</span><span class="plain-syntax">.</span><span class="identifier-syntax">token_sequence</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">].</span><span class="identifier-syntax">to_match</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">IDTypeData::invoked_inline</span><span class="plain-syntax">(</span><span class="identifier-syntax">idb</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">Kinds::Behaviour::definite</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</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">tokens</span><span class="plain-syntax">.</span><span class="element-syntax">token_kinds</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="identifier-syntax">Specifications::to_kind</span><span class="plain-syntax">(</span><span class="identifier-syntax">val</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">tokens</span><span class="plain-syntax">.</span><span class="element-syntax">token_kinds</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="identifier-syntax">K</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">idb</span><span class="plain-syntax">-></span><span class="identifier-syntax">type_data</span><span class="plain-syntax">.</span><span class="identifier-syntax">token_sequence</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">].</span><span class="identifier-syntax">construct</span><span class="plain-syntax"> == </span><span class="identifier-syntax">KIND_NAME_IDTC</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">tokens</span><span class="plain-syntax">.</span><span class="element-syntax">token_vals</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="identifier-syntax">Rvalues::new_nothing_object_constant</span><span class="plain-syntax">();</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">tokens</span><span class="plain-syntax">.</span><span class="element-syntax">token_vals</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="identifier-syntax">val</span><span class="plain-syntax">;</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">return_kind</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::get_kind_resulting</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</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">return_kind</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">idb</span><span class="plain-syntax">)) </span><span class="identifier-syntax">return_kind</span><span class="plain-syntax"> = </span><span class="identifier-syntax">idb</span><span class="plain-syntax">-></span><span class="identifier-syntax">type_data</span><span class="plain-syntax">.</span><span class="identifier-syntax">return_kind</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">tokens</span><span class="plain-syntax">.</span><span class="identifier-syntax">fn_kind</span><span class="plain-syntax"> =</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::function_kind</span><span class="plain-syntax">(</span><span class="identifier-syntax">tokens</span><span class="plain-syntax">.</span><span class="element-syntax">tokens_count</span><span class="plain-syntax">, </span><span class="identifier-syntax">tokens</span><span class="plain-syntax">.</span><span class="element-syntax">token_kinds</span><span class="plain-syntax">, </span><span class="identifier-syntax">return_kind</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">tokens</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="5-cbal.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="progresschapter"><a href="3-sf.html">3</a></li><li class="progresschapter"><a href="4-cs.html">4</a></li><li class="progresscurrentchapter">5</li><li class="progresssection"><a href="5-cbal.html">cbal</a></li><li class="progresscurrent">ci</li><li class="progresssection"><a href="5-ciac.html">ciac</a></li><li class="progresssection"><a href="5-cii.html">cii</a></li><li class="progresssection"><a href="5-cste.html">cste</a></li><li class="progresssection"><a href="5-ca.html">ca</a></li><li class="progressnext"><a href="5-ciac.html">❯</a></li></ul></div>
|
|
</nav><!--End of weave-->
|
|
|
|
</main>
|
|
</body>
|
|
</html>
|
|
|