mirror of
https://github.com/ganelson/inform.git
synced 2024-07-05 16:44:21 +03:00
981 lines
102 KiB
HTML
981 lines
102 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>25/pi</title>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<meta http-equiv="Content-Language" content="en-gb">
|
|
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
</head>
|
|
<body>
|
|
|
|
<!--Weave of '25/ci' generated by 7-->
|
|
<ul class="crumbs"><li><a href="../webs.html">★</a></li><li><a href="index.html">core</a></li><li><a href="index.html#25">Chapter 25: Compilation</a></li><li><b>Compile Invocations</b></li></ul><p class="purpose">Here we generate Inform 6 code to execute the phrase(s) called for by an invocation list.</p>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. Definitions</a></li><li><a href="#SP3">§3. Top level: compiling lists</a></li><li><a href="#SP4">§4. Lower level: compiling single invocations</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. Definitions. </b></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§2. </b>This represents the tokens being used when invoking a phrase:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">tokens_packet</span><span class="plain"> {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">tokens_count</span><span class="plain">; </span> <span class="comment">number of arguments to phrase</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">args</span><span class="plain">[32]; </span> <span class="comment">what they are</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_required</span><span class="plain">[32]; </span> <span class="comment">what pointer kinds of value, if they are</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">as_requested</span><span class="plain">; </span> <span class="comment">kind for the function call</span>
|
|
<span class="plain">} </span><span class="reserved">tokens_packet</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure tokens_packet is accessed in 25/ciac, 25/cii and here.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. Top level: compiling lists. </b>The invocation list will consist of at least one invocation, and all of these
|
|
except possibly the last one will be "unproven" by the type-checking
|
|
apparatus — that is, will not be safe to execute without run-time checking.
|
|
We must execute exactly one invocation in the list — the first one which
|
|
is found to be type-safe — or else produce a run-time error message.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">It follows that there is only one case where no checking is needed: when
|
|
the list consists of a single proven invocation. This we compile directly
|
|
to the I6 stream. In all other cases, we compile a function call to a
|
|
"resolver routine" to the I6 stream, delegating the choice to an
|
|
external routine: and we will probably have to compile this routine, too,
|
|
unless the decision on this block is one that we recognise from an
|
|
earlier invocation list (in what may be another setting entirely).
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Invocations::Compiler::compile_invocation_list</span><span class="plain">(</span><span class="identifier">value_holster</span><span class="plain"> *</span><span class="identifier">VH</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">invl</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">VH</span><span class="plain">-></span><span class="identifier">vhmode_wanted</span><span class="plain"> == </span><span class="identifier">INTER_VAL_VHMODE</span><span class="plain">) </span><span class="identifier">VH</span><span class="plain">-></span><span class="identifier">vhmode_provided</span><span class="plain"> = </span><span class="identifier">INTER_VAL_VHMODE</span><span class="plain">;</span>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">VH</span><span class="plain">-></span><span class="identifier">vhmode_provided</span><span class="plain"> = </span><span class="identifier">INTER_VOID_VHMODE</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">wn</span><span class="plain"> = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Invocations::length_of_list</span><span class="plain">(</span><span class="identifier">invl</span><span class="plain">) > 0) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Compiling from %d invocations\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="functiontext">Invocations::length_of_list</span><span class="plain">(</span><span class="identifier">invl</span><span class="plain">));</span>
|
|
<span class="identifier">source_location</span><span class="plain"> </span><span class="identifier">sl</span><span class="plain"> = </span><span class="identifier">Lexer::word_location</span><span class="plain">(</span><span class="identifier">wn</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Invocations::is_marked_to_save_self</span><span class="plain">(</span><span class="functiontext">Invocations::first_in_list</span><span class="plain">(</span><span class="identifier">invl</span><span class="plain">))) {</span>
|
|
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">PUSH_BIP</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">SELF_HL</span><span class="plain">));</span>
|
|
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Invocations::is_marked_unproven</span><span class="plain">(</span><span class="functiontext">Invocations::first_in_list</span><span class="plain">(</span><span class="identifier">invl</span><span class="plain">))) {</span>
|
|
<<span class="cwebmacro">Compile using run-time resolution to choose between invocations</span> <span class="cwebmacronumber">3.2</span>><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<<span class="cwebmacro">Compile as a series of invocations all of which run</span> <span class="cwebmacronumber">3.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Invocations::is_marked_to_save_self</span><span class="plain">(</span><span class="functiontext">Invocations::first_in_list</span><span class="plain">(</span><span class="identifier">invl</span><span class="plain">))) {</span>
|
|
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">PULL_BIP</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">Produce::ref_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">SELF_HL</span><span class="plain">));</span>
|
|
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Invocations::Compiler::compile_invocation_list is used in 14/rv (<a href="14-rv.html#SP24">§24</a>), 25/cp (<a href="25-cp.html#SP6">§6</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_1"></a><b>§3.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Compile as a series of invocations all of which run</span> <span class="cwebmacronumber">3.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pos</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_THROUGH_INVOCATION_LIST</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">invl</span><span class="plain">) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"C%d: $e\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">); </span><span class="identifier">pos</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_say_verb</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">)) {</span>
|
|
<span class="functiontext">NewVerbs::ConjugateVerb_invoke_emit</span><span class="plain">(</span>
|
|
<span class="identifier">ParseTree::get_say_verb</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">),</span>
|
|
<span class="identifier">ParseTree::get_modal_verb</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">),</span>
|
|
<span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">say_verb_negated_ANNOT</span><span class="plain">));</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_say_adjective</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">)) {</span>
|
|
<span class="functiontext">Adjectives::Meanings::emit</span><span class="plain">(</span><span class="identifier">ParseTree::get_say_adjective</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">));</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<<span class="cwebmacro">Otherwise, use the standard way to compile an invoked phrase</span> <span class="cwebmacronumber">3.1.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3">§3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_1_1"></a><b>§3.1.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Otherwise, use the standard way to compile an invoked phrase</span> <span class="cwebmacronumber">3.1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain"> = </span><span class="identifier">ParseTree::get_phrase_invoked</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">);</span>
|
|
<span class="reserved">tokens_packet</span><span class="plain"> </span><span class="identifier">tokens</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">First construct an arguments packet</span> <span class="cwebmacronumber">3.1.1.1</span>><span class="plain">;</span>
|
|
<span class="identifier">value_holster</span><span class="plain"> </span><span class="identifier">VH2</span><span class="plain"> = </span><span class="identifier">Holsters::new</span><span class="plain">(</span><span class="identifier">VH</span><span class="plain">-></span><span class="identifier">vhmode_wanted</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">returned_in_manner</span><span class="plain"> =</span>
|
|
<span class="functiontext">Invocations::Compiler::compile_single_invocation</span><span class="plain">(&</span><span class="identifier">VH2</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">, &</span><span class="identifier">sl</span><span class="plain">, &</span><span class="identifier">tokens</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">phrase_being_compiled</span><span class="plain">) && (</span><span class="identifier">returned_in_manner</span><span class="plain"> != </span><span class="constant">DONT_KNOW_MOR</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">If the invocation compiled to a return from a function, check this is allowed</span> <span class="cwebmacronumber">3.1.1.2</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_1">§3.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_1_1_1"></a><b>§3.1.1.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">First construct an arguments packet</span> <span class="cwebmacronumber">3.1.1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">tokens</span><span class="element">.tokens_count</span><span class="plain"> = </span><span class="functiontext">Invocations::get_no_tokens_needed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">);</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">tokens</span><span class="element">.tokens_count</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">val</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token_as_parsed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span>
|
|
<span class="identifier">ph</span><span class="plain">-</span><span class="element">>type_data.token_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.to_match</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Phrases::TypeData::invoked_inline</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="identifier">Kinds::Behaviour::definite</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">))</span>
|
|
<span class="identifier">tokens</span><span class="element">.kind_required</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">val</span><span class="plain">);</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">tokens</span><span class="element">.kind_required</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">K</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">>type_data.token_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.construct</span><span class="plain"> == </span><span class="constant">KIND_NAME_PT_CONSTRUCT</span><span class="plain">)</span>
|
|
<span class="identifier">tokens</span><span class="element">.args</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="functiontext">Rvalues::new_nothing_object_constant</span><span class="plain">();</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">tokens</span><span class="element">.args</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">val</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">return_kind</span><span class="plain"> = </span><span class="identifier">ParseTree::get_kind_resulting</span><span class="plain">(</span><span class="functiontext">Invocations::first_in_list</span><span class="plain">(</span><span class="identifier">invl</span><span class="plain">));</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">return_kind</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) && (</span><span class="identifier">ph</span><span class="plain">)) </span><span class="identifier">return_kind</span><span class="plain"> = </span><span class="identifier">ph</span><span class="plain">-</span><span class="element">>type_data.return_kind</span><span class="plain">;</span>
|
|
<span class="identifier">tokens</span><span class="element">.as_requested</span><span class="plain"> =</span>
|
|
<span class="identifier">Kinds::function_kind</span><span class="plain">(</span><span class="identifier">tokens</span><span class="element">.tokens_count</span><span class="plain">, </span><span class="identifier">tokens</span><span class="element">.kind_required</span><span class="plain">, </span><span class="identifier">return_kind</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_1_1">§3.1.1</a>, <a href="#SP3_2_3_3_1">§3.2.3.3.1</a>, <a href="#SP3_2_3_4_1">§3.2.3.4.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_1_1_2"></a><b>§3.1.1.2. </b>For example, a standard "To..." phrase isn't allowed to contain the invocation
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>decide on 178;</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">since it isn't a phrase to decide anything. This is where that's checked:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">If the invocation compiled to a return from a function, check this is allowed</span> <span class="cwebmacronumber">3.1.1.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">manner_expected</span><span class="plain"> = </span><span class="identifier">phrase_being_compiled</span><span class="plain">-</span><span class="element">>type_data.manner_of_return</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">returned_in_manner</span><span class="plain"> != </span><span class="identifier">manner_expected</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="identifier">manner_expected</span><span class="plain"> != </span><span class="constant">DECIDES_NOTHING_AND_RETURNS_MOR</span><span class="plain">)) {</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"C%d: $e: returned in manner %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">returned_in_manner</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"vs Phrase being compiled: %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">manner_expected</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::quote_text</span><span class="plain">(2,</span>
|
|
<span class="functiontext">Phrases::TypeData::describe_manner_of_return</span><span class="plain">(</span><span class="identifier">returned_in_manner</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">));</span>
|
|
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">Problems::quote_text</span><span class="plain">(3,</span>
|
|
<span class="functiontext">Phrases::TypeData::describe_manner_of_return</span><span class="plain">(</span><span class="identifier">manner_expected</span><span class="plain">,</span>
|
|
<span class="plain">&(</span><span class="identifier">phrase_being_compiled</span><span class="plain">-</span><span class="element">>type_data</span><span class="plain">), &</span><span class="identifier">K</span><span class="plain">));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">) </span><span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">K</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_WrongEndToPhrase</span><span class="plain">));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">)</span>
|
|
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
|
|
<span class="string">"The line %1 seems to be a way that the phrase you're defining can come "</span>
|
|
<span class="string">"to an end, with %2, but it should always end up with a phrase to "</span>
|
|
<span class="string">"decide %4."</span><span class="plain">);</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
|
|
<span class="string">"The line %1 seems to be a way that the phrase you're defining can come "</span>
|
|
<span class="string">"to an end, with %2, but it should always end up with %3."</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_1_1">§3.1.1</a>, <a href="#SP3_2_3_3_1_3">§3.2.3.3.1.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2"></a><b>§3.2. </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 run-time.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">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="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Compile using run-time resolution to choose between invocations</span> <span class="cwebmacronumber">3.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain"> = </span><span class="identifier">ParseTree::get_phrase_invoked</span><span class="plain">(</span><span class="functiontext">Invocations::first_in_list</span><span class="plain">(</span><span class="identifier">invl</span><span class="plain">));</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="functiontext">Invocations::get_no_tokens</span><span class="plain">(</span><span class="functiontext">Invocations::first_in_list</span><span class="plain">(</span><span class="identifier">invl</span><span class="plain">));</span>
|
|
<span class="functiontext">Frames::need_at_least_this_many_formals</span><span class="plain">(</span><span class="identifier">N</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">void_mode</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">>type_data.manner_of_return</span><span class="plain"> == </span><span class="constant">DECIDES_NOTHING_MOR</span><span class="plain">) </span><span class="identifier">void_mode</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
|
|
<<span class="cwebmacro">Compile the resolution</span> <span class="cwebmacronumber">3.2.3</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3">§3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_1"></a><b>§3.2.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>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">if (condition for I1 to be valid) invoke I1(T1, ..., Tm);</span>
|
|
<span class="plain">else if (condition for I2 to be valid) invoke I2(T1, ..., Tm);</span>
|
|
<span class="plain">...</span>
|
|
<span class="plain">else run-time-error-message();</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">where the chain of execution runs into the error message code only if none
|
|
of I1, ..., In can be applied. In fact, it will sometimes happen that the
|
|
final invocation can be proved applicable at compile time, and then we'll
|
|
compile this instead:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">if (condition for I1 to be valid) invoke I1(T1, ..., Tm);</span>
|
|
<span class="plain">else if (condition for I2 to be valid) invoke I2(T1, ..., Tm);</span>
|
|
<span class="plain">else invoke In(T1, ..., Tm);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">Note that it's not possible for an intermediate invocation in the group to
|
|
be provably correct, because if it is then we wouldn't have collected any
|
|
further possibilities.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_2"></a><b>§3.2.2. </b>That's almost what we do, but not quite. The problem lies in the fact that
|
|
the tokens T1, ..., Tm 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 (for example if T1 were a call to some phrase to decide
|
|
something, and that phrase had side-effects). So in fact we modify our
|
|
scheme like so:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">formal_par1 = T1;</span>
|
|
<span class="plain">formal_par2 = T2;</span>
|
|
<span class="plain">...</span>
|
|
<span class="plain">if (condition for I1 to be valid) invoke I1(formal_par1, ..., formal_parm);</span>
|
|
<span class="plain">else if (condition for I2 to be valid) invoke I2(formal_par1, ..., formal_parm);</span>
|
|
<span class="plain">...</span>
|
|
<span class="plain">else run-time-error-message();</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">This fixes the side-effect problem, provided we compile the conditions so
|
|
that they measure the "formal parameters" instead of the original T1, T2, ...
|
|
But another possible trap is that the <code class="display"><span class="extract">formal_par1</span></code>, ..., variables need
|
|
to be local to the current I6 stack frame, since evaluation of T2, say,
|
|
might itself involve a call to another phrase which recursively needs to
|
|
make a resolution itself.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Finding local storage here is more problematic than it looks. I6 has an
|
|
absolute limit on the number of local variables, imposed by the virtual
|
|
machines it runs on. We can't create any local stack space, because the
|
|
stack isn't memory-accessible on either of the VMs Inform compiles to. It's
|
|
not reliable to create an auxiliary stack in main memory, because this
|
|
couldn't resize on the Z-machine, and we want to avoid use of the heap,
|
|
because we want Inform to carry on working even in cramped Z-machine cases
|
|
where there's no memory for any heap at all. What we do, then, is to store
|
|
<code class="display"><span class="extract">formal_par1</span></code> et seq as global I6 variables, and to use an outer shell
|
|
routine to push and pull their values, thus in effect making them additional
|
|
locals, albeit at a small performance hit.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3"></a><b>§3.2.3. </b>In value mode we want the same strategy and code paths, but all in
|
|
the context of a value.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Compile the resolution</span> <span class="cwebmacronumber">3.2.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">void_mode</span><span class="plain">) {</span>
|
|
<<span class="cwebmacro">Compile code to set the formal parameters in void mode</span> <span class="cwebmacronumber">3.2.3.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Compile code to apply the first invocation which is applicable</span> <span class="cwebmacronumber">3.2.3.3</span>><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">TERNARYSEQUENTIAL_BIP</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_conditions_tested</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">Produce::level</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<<span class="cwebmacro">Emit code to set the formal parameters in expression mode</span> <span class="cwebmacronumber">3.2.3.2</span>><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain"> != </span><span class="identifier">Produce::level</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">())) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"formal parameter expression error"</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">NC</span><span class="plain"> = 0, </span><span class="identifier">unprov</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">prov</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Count the applicability conditions</span> <span class="cwebmacronumber">3.2.3.5</span>><span class="plain">;</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">); </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="string">"Think %d unprov %d prov %d"</span><span class="plain">, </span><span class="identifier">NC</span><span class="plain">, </span><span class="identifier">unprov</span><span class="plain">, </span><span class="identifier">prov</span><span class="plain">); </span><span class="functiontext">Emit::code_comment</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">); </span><span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">unprov</span><span class="plain">) { </span><span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">OR_BIP</span><span class="plain">); </span><span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">()); }</span>
|
|
<<span class="cwebmacro">Compile code to apply the first invocation which is applicable, as expression</span> <span class="cwebmacronumber">3.2.3.4</span>><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = 0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">NC</span><span class="plain">-1; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prov</span><span class="plain">) </span><span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">unprov</span><span class="plain">) {</span>
|
|
<<span class="cwebmacro">Compile code for the execution path where no invocations were applicable</span> <span class="cwebmacronumber">3.2.3.6</span>><span class="plain">;</span>
|
|
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain"> != </span><span class="identifier">Produce::level</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">())) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"applicability expression error"</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">FORMAL_RV_HL</span><span class="plain">));</span>
|
|
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2">§3.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3_1"></a><b>§3.2.3.1. </b>In void mode, this code is simple: it just produces a list of assignments:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">formal_par1 = T1;</span>
|
|
<span class="plain">formal_par2 = T2;</span>
|
|
<span class="plain">...</span>
|
|
|
|
<<span class="cwebmacrodefn">Compile code to set the formal parameters in void mode</span> <span class="cwebmacronumber">3.2.3.1</span>> =
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">N</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<<span class="cwebmacro">Compile the actual assignment</span> <span class="cwebmacronumber">3.2.3.1.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2_3">§3.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3_2"></a><b>§3.2.3.2. </b>In value mode, we exploit the fact that, as in C, assignments return a value
|
|
and are therefore legal in an expression context; but, again avoiding the
|
|
serial comma at the cost of a fruitless addition,
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">(formal_parn = Tn) + ... + (formal_par1 = T1)</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">Again, this is written in reverse order because I6 will evaluate this from
|
|
right to left: we want T1 to evaluate first, then T2, and so on.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Emit code to set the formal parameters in expression mode</span> <span class="cwebmacronumber">3.2.3.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">N</span><span class="plain">-1; </span><span class="identifier">i</span><span class="plain">>=0; </span><span class="identifier">i</span><span class="plain">--) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> > 0) { </span><span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">PLUS_BIP</span><span class="plain">); </span><span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">()); }</span>
|
|
<<span class="cwebmacro">Compile the actual assignment</span> <span class="cwebmacronumber">3.2.3.1.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">N</span><span class="plain">-1; </span><span class="identifier">i</span><span class="plain">>0; </span><span class="identifier">i</span><span class="plain">--) </span><span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2_3">§3.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3_1_1"></a><b>§3.2.3.1.1. </b>A parameter corresponding to the name of a kind has no meaningful value
|
|
at run-time; we assign 0 to it for the sake of tidiness.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Compile the actual assignment</span> <span class="cwebmacronumber">3.2.3.1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="functiontext">NonlocalVariables::temporary_formal</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">STORE_BIP</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">Produce::ref_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="functiontext">NonlocalVariables::formal_par</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">>type_data.token_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.construct</span><span class="plain"> == </span><span class="constant">KIND_NAME_PT_CONSTRUCT</span><span class="plain">)</span>
|
|
<span class="identifier">Produce::val</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 0);</span>
|
|
<span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="constant">BEGIN_COMPILATION_MODE</span><span class="plain">;</span>
|
|
<span class="identifier">COMPILATION_MODE_ENTER</span><span class="plain">(</span><span class="constant">DEREFERENCE_POINTERS_CMODE</span><span class="plain">);</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">value</span><span class="plain"> =</span>
|
|
<span class="functiontext">Invocations::get_token_as_parsed</span><span class="plain">(</span><span class="functiontext">Invocations::first_in_list</span><span class="plain">(</span><span class="identifier">invl</span><span class="plain">), </span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">to_be_used_as</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span>
|
|
<span class="identifier">ph</span><span class="plain">-</span><span class="element">>type_data.token_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.to_match</span><span class="plain">);</span>
|
|
<span class="functiontext">Specifications::Compiler::emit_to_kind</span><span class="plain">(</span><span class="identifier">value</span><span class="plain">, </span><span class="identifier">to_be_used_as</span><span class="plain">);</span>
|
|
<span class="constant">END_COMPILATION_MODE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2_3_1">§3.2.3.1</a>, <a href="#SP3_2_3_2">§3.2.3.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3_3"></a><b>§3.2.3.3. </b>So now we come to the part which switches the execution stream. In void mode,
|
|
it will look like so:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">if (condition for I1 to be valid) invoke I1;</span>
|
|
<span class="plain">else if (condition for I2 to be valid) invoke I2;</span>
|
|
<span class="plain">...</span>
|
|
<span class="plain">else run-time-error-message();</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">but in value mode, where invocations return values,
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">((condition for I1 to be valid) && ((formal_rv = I1) bitwise-or 1))</span>
|
|
<span class="plain">logical-or ((condition for I2 to be valid) && ((formal_rv = I2) bitwise-or 1))</span>
|
|
<span class="plain">...</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">The key here is that I6, like C, evaluates operands of <code class="display"><span class="extract">&&</span></code> 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 <code class="display"><span class="extract">formal_rv</span></code>) never
|
|
happens; and similarly for logical-or. Bitwise or doesn't have that property,
|
|
and the ridiculous trick of bitwise-or-ing with 1 ensures that any value is
|
|
made non-zero, so that the assignment is always regarded by I6 as "true".
|
|
This in turn means that if any invocation is reached in this expression,
|
|
no subsequent lines are looked at.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Compile code to apply the first invocation which is applicable</span> <span class="cwebmacronumber">3.2.3.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_conditions_tested</span><span class="plain"> = 0, </span><span class="identifier">if_depth</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pos</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">last_inv</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_THROUGH_INVOCATION_LIST</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">invl</span><span class="plain">) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"RC%d: $e\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">); </span><span class="identifier">pos</span><span class="plain">++;</span>
|
|
<span class="identifier">last_inv</span><span class="plain"> = </span><span class="identifier">inv</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_conditions_tested</span><span class="plain"> > 0) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">void_mode</span><span class="plain">) {</span>
|
|
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">Produce::code</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<<span class="cwebmacro">Compile code to apply this invocation if it's applicable</span> <span class="cwebmacronumber">3.2.3.3.1</span>><span class="character">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Invocations::is_marked_unproven</span><span class="plain">(</span><span class="identifier">last_inv</span><span class="plain">)) {</span>
|
|
<<span class="cwebmacro">Compile code for the execution path where no invocations were applicable</span> <span class="cwebmacronumber">3.2.3.6</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">if_depth</span><span class="plain"> > 0) { </span><span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">()); </span><span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">()); </span><span class="identifier">if_depth</span><span class="plain">--; }</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2_3">§3.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3_4"></a><b>§3.2.3.4. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Compile code to apply the first invocation which is applicable, as expression</span> <span class="cwebmacronumber">3.2.3.4</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pos</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">last_inv</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_THROUGH_INVOCATION_LIST</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">invl</span><span class="plain">) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"RC%d: $e\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">); </span><span class="identifier">pos</span><span class="plain">++;</span>
|
|
<span class="identifier">last_inv</span><span class="plain"> = </span><span class="identifier">inv</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Compile code to apply this invocation if it's applicable, expression version</span> <span class="cwebmacronumber">3.2.3.4.1</span>><span class="character">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2_3">§3.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3_5"></a><b>§3.2.3.5. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Count the applicability conditions</span> <span class="cwebmacronumber">3.2.3.5</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">last_inv</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_THROUGH_INVOCATION_LIST</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">invl</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">checks_needed</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="identifier">last_inv</span><span class="plain"> = </span><span class="identifier">inv</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="functiontext">Invocations::get_no_tokens</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">check_against</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token_check_to_do</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">check_against</span><span class="plain">) </span><span class="identifier">checks_needed</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">checks_needed</span><span class="plain">) </span><span class="identifier">NC</span><span class="plain">++; </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">prov</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Invocations::is_marked_unproven</span><span class="plain">(</span><span class="identifier">last_inv</span><span class="plain">)) </span><span class="identifier">unprov</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2_3">§3.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3_6"></a><b>§3.2.3.6. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Compile code for the execution path where no invocations were applicable</span> <span class="cwebmacronumber">3.2.3.6</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_conditions_tested</span><span class="plain"> == 0) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"condition proof error"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">void_mode</span><span class="plain">) {</span>
|
|
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">Produce::code</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">Produce::inv_call_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">ARGUMENTTYPEFAILED_HL</span><span class="plain">));</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">Produce::val</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sl</span><span class="plain">.</span><span class="identifier">line_number</span><span class="plain">);</span>
|
|
<span class="reserved">extension_file</span><span class="plain"> *</span><span class="identifier">ef</span><span class="plain"> = </span><span class="functiontext">SourceFiles::get_extension_corresponding</span><span class="plain">(</span><span class="identifier">sl</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ef</span><span class="plain">) </span><span class="identifier">Produce::val</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">ef</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain"> + 1);</span>
|
|
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2_3">§3.2.3</a>, <a href="#SP3_2_3_3">§3.2.3.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3_3_1"></a><b>§3.2.3.3.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Compile code to apply this invocation if it's applicable</span> <span class="cwebmacronumber">3.2.3.3.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_say_verb</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">))</span>
|
|
<span class="functiontext">NewVerbs::ConjugateVerb_invoke_emit</span><span class="plain">(</span>
|
|
<span class="identifier">ParseTree::get_say_verb</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">),</span>
|
|
<span class="identifier">ParseTree::get_modal_verb</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">),</span>
|
|
<span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">say_verb_negated_ANNOT</span><span class="plain">));</span>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_say_adjective</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">))</span>
|
|
<span class="functiontext">Adjectives::Meanings::emit</span><span class="plain">(</span><span class="identifier">ParseTree::get_say_adjective</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">));</span>
|
|
<span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain"> = </span><span class="identifier">ParseTree::get_phrase_invoked</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">);</span>
|
|
<span class="reserved">tokens_packet</span><span class="plain"> </span><span class="identifier">tokens</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">First construct an arguments packet</span> <span class="cwebmacronumber">3.1.1.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Substitute the formal parameter variables into the tokens</span> <span class="cwebmacronumber">3.2.3.3.1.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Compile the check on invocation applicability, emission version</span> <span class="cwebmacronumber">3.2.3.3.1.2</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Compile the invocation part, emission version</span> <span class="cwebmacronumber">3.2.3.3.1.3</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2_3_3">§3.2.3.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3_4_1"></a><b>§3.2.3.4.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Compile code to apply this invocation if it's applicable, expression version</span> <span class="cwebmacronumber">3.2.3.4.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_say_verb</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">))</span>
|
|
<span class="functiontext">NewVerbs::ConjugateVerb_invoke_emit</span><span class="plain">(</span>
|
|
<span class="identifier">ParseTree::get_say_verb</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">),</span>
|
|
<span class="identifier">ParseTree::get_modal_verb</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">),</span>
|
|
<span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">say_verb_negated_ANNOT</span><span class="plain">));</span>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_say_adjective</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">))</span>
|
|
<span class="functiontext">Adjectives::Meanings::emit</span><span class="plain">(</span><span class="identifier">ParseTree::get_say_adjective</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">));</span>
|
|
<span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain"> = </span><span class="identifier">ParseTree::get_phrase_invoked</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">);</span>
|
|
<span class="reserved">tokens_packet</span><span class="plain"> </span><span class="identifier">tokens</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">First construct an arguments packet</span> <span class="cwebmacronumber">3.1.1.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Substitute the formal parameter variables into the tokens</span> <span class="cwebmacronumber">3.2.3.3.1.1</span>><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">Produce::level</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">()), </span><span class="identifier">or_made</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">ands_made</span><span class="plain"> = 0;</span>
|
|
<<span class="cwebmacro">Compile the check on invocation applicability, expression version</span> <span class="cwebmacronumber">3.2.3.4.1.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Compile the invocation part, emission version</span> <span class="cwebmacronumber">3.2.3.3.1.3</span>><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">ands_made</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">target</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">or_made</span><span class="plain">) </span><span class="identifier">target</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">target</span><span class="plain"> != </span><span class="identifier">Produce::level</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">())) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"levels wrong"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2_3_4">§3.2.3.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3_3_1_1"></a><b>§3.2.3.3.1.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Substitute the formal parameter variables into the tokens</span> <span class="cwebmacronumber">3.2.3.3.1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">tokens</span><span class="element">.tokens_count</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="reserved">nonlocal_variable</span><span class="plain"> *</span><span class="identifier">nlv</span><span class="plain"> = </span><span class="functiontext">NonlocalVariables::temporary_formal</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="functiontext">NonlocalVariables::set_kind</span><span class="plain">(</span><span class="identifier">nlv</span><span class="plain">, </span><span class="identifier">tokens</span><span class="element">.kind_required</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
|
|
<span class="identifier">tokens</span><span class="element">.args</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="functiontext">Lvalues::new_actual_NONLOCAL_VARIABLE</span><span class="plain">(</span><span class="identifier">nlv</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2_3_3_1">§3.2.3.3.1</a>, <a href="#SP3_2_3_4_1">§3.2.3.4.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3_3_1_2"></a><b>§3.2.3.3.1.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Compile the check on invocation applicability, emission version</span> <span class="cwebmacronumber">3.2.3.3.1.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">check_needed</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="functiontext">Invocations::get_no_tokens</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">check_against</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token_check_to_do</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">check_against</span><span class="plain"> != </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">check_needed</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">check_needed</span><span class="plain"> > 0) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">void_mode</span><span class="plain">) {</span>
|
|
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">IFELSE_BIP</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<<span class="cwebmacro">Put the condition check here, emission version</span> <span class="cwebmacronumber">3.2.3.3.1.2.1</span>><span class="plain">;</span>
|
|
<span class="identifier">Produce::code</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">if_depth</span><span class="plain">++;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">AND_BIP</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<<span class="cwebmacro">Put the condition check here, emission version</span> <span class="cwebmacronumber">3.2.3.3.1.2.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">no_conditions_tested</span><span class="plain">++;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Invocations::is_marked_unproven</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">))</span>
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"unable to compile a run-time kind check"</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2_3_3_1">§3.2.3.3.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3_4_1_1"></a><b>§3.2.3.4.1.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Compile the check on invocation applicability, expression version</span> <span class="cwebmacronumber">3.2.3.4.1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">check_needed</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="functiontext">Invocations::get_no_tokens</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">check_against</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token_check_to_do</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">check_against</span><span class="plain"> != </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">check_needed</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">check_needed</span><span class="plain"> > 0) {</span>
|
|
<span class="identifier">no_conditions_tested</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">no_conditions_tested</span><span class="plain"> < </span><span class="identifier">NC</span><span class="plain">) || (</span><span class="identifier">prov</span><span class="plain">)) {</span>
|
|
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">OR_BIP</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">()); </span><span class="identifier">or_made</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="functiontext">Invocations::get_no_tokens</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">check_against</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token_check_to_do</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">check_against</span><span class="plain">) {</span>
|
|
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">AND_BIP</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">()); </span><span class="identifier">ands_made</span><span class="plain">++;</span>
|
|
<span class="constant">BEGIN_COMPILATION_MODE</span><span class="plain">;</span>
|
|
<span class="identifier">COMPILATION_MODE_EXIT</span><span class="plain">(</span><span class="constant">DEREFERENCE_POINTERS_CMODE</span><span class="plain">);</span>
|
|
<span class="reserved">nonlocal_variable</span><span class="plain"> *</span><span class="identifier">nlv</span><span class="plain"> = </span><span class="functiontext">NonlocalVariables::temporary_formal</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="functiontext">Lvalues::new_actual_NONLOCAL_VARIABLE</span><span class="plain">(</span><span class="identifier">nlv</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Compile a check that this formal variable matches the token, emission version</span> <span class="cwebmacronumber">3.2.3.4.1.1.1</span>><span class="plain">;</span>
|
|
<span class="constant">END_COMPILATION_MODE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2_3_4_1">§3.2.3.4.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3_3_1_2_1"></a><b>§3.2.3.3.1.2.1. </b>There may be checks needed on several tokens, so we accumulate these into
|
|
a list divided by logical-and <code class="display"><span class="extract">&&</span></code> operators.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Put the condition check here, emission version</span> <span class="cwebmacronumber">3.2.3.3.1.2.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">and_depth</span><span class="plain"> = 0;</span>
|
|
<span class="constant">BEGIN_COMPILATION_MODE</span><span class="plain">;</span>
|
|
<span class="identifier">COMPILATION_MODE_EXIT</span><span class="plain">(</span><span class="constant">DEREFERENCE_POINTERS_CMODE</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0, </span><span class="identifier">check_count</span><span class="plain"> = 0; </span><span class="identifier">i</span><span class="plain"><</span><span class="functiontext">Invocations::get_no_tokens</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">check_against</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token_check_to_do</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">check_against</span><span class="plain"> != </span><span class="identifier">NULL</span><span class="plain">) {</span>
|
|
<span class="identifier">check_count</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">check_count</span><span class="plain"> < </span><span class="identifier">check_needed</span><span class="plain">) {</span>
|
|
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">AND_BIP</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">and_depth</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">nonlocal_variable</span><span class="plain"> *</span><span class="identifier">nlv</span><span class="plain"> = </span><span class="functiontext">NonlocalVariables::temporary_formal</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="functiontext">Lvalues::new_actual_NONLOCAL_VARIABLE</span><span class="plain">(</span><span class="identifier">nlv</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Compile a check that this formal variable matches the token, emission version</span> <span class="cwebmacronumber">3.2.3.4.1.1.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">and_depth</span><span class="plain"> > 0) { </span><span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">()); </span><span class="identifier">and_depth</span><span class="plain">--; }</span>
|
|
|
|
<span class="constant">END_COMPILATION_MODE</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2_3_3_1_2">§3.2.3.3.1.2</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3_4_1_1_1"></a><b>§3.2.3.4.1.1.1. </b>There are two things we might want to check, exemplified by what happens
|
|
in this situation:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>To collate (N - an even number): ...</p>
|
|
|
|
</blockquote>
|
|
|
|
<blockquote>
|
|
<p>To collate (N - 10): ...</p>
|
|
|
|
</blockquote>
|
|
|
|
<blockquote>
|
|
<p>collate X;</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">To compile "collate X", we need to test at run-time which invocation applies.
|
|
(We actually check the second of these first, because it's more specific.)
|
|
In case we test if X is 10, in the other that X matches the description
|
|
"even number".
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Compile a check that this formal variable matches the token, emission version</span> <span class="cwebmacronumber">3.2.3.4.1.1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Specifications::is_description</span><span class="plain">(</span><span class="identifier">check_against</span><span class="plain">)) {</span>
|
|
<span class="functiontext">Calculus::Deferrals::emit_test_if_var_matches_description</span><span class="plain">(</span>
|
|
<span class="identifier">spec</span><span class="plain">, </span><span class="identifier">check_against</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTreeUsage::is_value</span><span class="plain">(</span><span class="identifier">check_against</span><span class="plain">)) {</span>
|
|
<span class="reserved">pcalc_prop</span><span class="plain"> *</span><span class="identifier">prop</span><span class="plain"> = </span><span class="functiontext">Calculus::Propositions::Abstract::to_set_relation</span><span class="plain">(</span><span class="identifier">R_equality</span><span class="plain">,</span>
|
|
<span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">check_against</span><span class="plain">);</span>
|
|
<span class="functiontext">Calculus::Deferrals::emit_test_of_proposition</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Error on: $T"</span><span class="plain">, </span><span class="identifier">check_against</span><span class="plain">);</span>
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad check-against in run-time type check"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2_3_4_1_1">§3.2.3.4.1.1</a>, <a href="#SP3_2_3_3_1_2_1">§3.2.3.3.1.2.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3_2_3_3_1_3"></a><b>§3.2.3.3.1.3. </b>...and the actual invocation is now simple. In void mode, simply:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">invoke(formal-vars)</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">whereas in value mode,
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">((formal_rv = invoke(formal-vars)) bitwise-or 1)</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">As noted above, the bitwise-or is a clumsy way to force the condition to
|
|
evaluate to "true" with a minimum of branches in the compiled code.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Compile the invocation part, emission version</span> <span class="cwebmacronumber">3.2.3.3.1.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (!</span><span class="identifier">void_mode</span><span class="plain">) {</span>
|
|
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">BITWISEOR_BIP</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">STORE_BIP</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">Produce::ref_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">FORMAL_RV_HL</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">value_holster</span><span class="plain"> </span><span class="identifier">VH2</span><span class="plain"> = </span><span class="identifier">Holsters::new</span><span class="plain">(</span><span class="identifier">VH</span><span class="plain">-></span><span class="identifier">vhmode_wanted</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">returned_in_manner</span><span class="plain"> =</span>
|
|
<span class="functiontext">Invocations::Compiler::compile_single_invocation</span><span class="plain">(&</span><span class="identifier">VH2</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">, &</span><span class="identifier">sl</span><span class="plain">, &</span><span class="identifier">tokens</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (!</span><span class="identifier">void_mode</span><span class="plain">) {</span>
|
|
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">Produce::val</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 1);</span>
|
|
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">returned_in_manner</span><span class="plain"> != </span><span class="constant">DONT_KNOW_MOR</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">If the invocation compiled to a return from a function, check this is allowed</span> <span class="cwebmacronumber">3.1.1.2</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP3_2_3_3_1">§3.2.3.3.1</a>, <a href="#SP3_2_3_4_1">§3.2.3.4.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. Lower level: compiling single invocations. </b></p>
|
|
|
|
<p class="inwebparagraph">Phrases to decide a condition must compile to valid I6 conditions, which
|
|
we need to ensure there are round brackets around.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Invocations::Compiler::compile_single_invocation</span><span class="plain">(</span><span class="identifier">value_holster</span><span class="plain"> *</span><span class="identifier">VH</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain">,</span>
|
|
<span class="identifier">source_location</span><span class="plain"> *</span><span class="identifier">where_from</span><span class="plain">, </span><span class="reserved">tokens_packet</span><span class="plain"> *</span><span class="identifier">tokens</span><span class="plain">) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Compiling single invocation: $e\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">);</span>
|
|
<span class="constant">BEGIN_COMPILATION_MODE</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain"> = </span><span class="identifier">ParseTree::get_phrase_invoked</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">manner_of_return</span><span class="plain"> = </span><span class="constant">DONT_KNOW_MOR</span><span class="plain">;</span>
|
|
|
|
<<span class="cwebmacro">The art of invocation is delegation</span> <span class="cwebmacronumber">4.1</span>><span class="plain">;</span>
|
|
|
|
<<span class="cwebmacro">Compile a newline if the phrase implicitly requires one</span> <span class="cwebmacronumber">4.2</span>><span class="plain">;</span>
|
|
|
|
<span class="constant">END_COMPILATION_MODE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">manner_of_return</span><span class="plain"> != </span><span class="constant">DONT_KNOW_MOR</span><span class="plain">)</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Single invocation return manner: %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">manner_of_return</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">manner_of_return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Invocations::Compiler::compile_single_invocation is used in <a href="#SP3_1_1">§3.1.1</a>, <a href="#SP3_2_3_3_1_3">§3.2.3.3.1.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4_1"></a><b>§4.1. </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="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">The art of invocation is delegation</span> <span class="cwebmacronumber">4.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Phrases::TypeData::invoked_inline</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">))</span>
|
|
<span class="identifier">manner_of_return</span><span class="plain"> =</span>
|
|
<span class="functiontext">Invocations::Inline::csi_inline_outer</span><span class="plain">(</span><span class="identifier">VH</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">where_from</span><span class="plain">, </span><span class="identifier">tokens</span><span class="plain">);</span>
|
|
<span class="reserved">else</span>
|
|
<span class="functiontext">Invocations::AsCalls::csi_by_call</span><span class="plain">(</span><span class="identifier">VH</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">where_from</span><span class="plain">, </span><span class="identifier">tokens</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP4">§4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4_2"></a><b>§4.2. </b>This is where we implement the convention that saying text ending with a full
|
|
stop automatically generates a newline:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Compile a newline if the phrase implicitly requires one</span> <span class="cwebmacronumber">4.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Invocations::implies_newline</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="identifier">tokens</span><span class="plain">-</span><span class="element">>tokens_count</span><span class="plain"> > 0) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Rvalues::is_CONSTANT_of_kind</span><span class="plain">(</span><span class="identifier">tokens</span><span class="plain">-</span><span class="element">>args</span><span class="plain">[0], </span><span class="identifier">K_text</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="identifier">Word::text_ending_sentence</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">tokens</span><span class="plain">-</span><span class="element">>args</span><span class="plain">[0]))))) {</span>
|
|
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">PRINT_BIP</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="identifier">Produce::val_text</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">I</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP4">§4</a>.</p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="25-pi.html">Back to 'Parse Invocations'</a></li><li><a href="25-ciac.html">Continue with 'Compile Invocations As Calls'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
</body>
|
|
</html>
|
|
|