1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/core-module/22-ptd.html
2019-04-22 15:42:10 +01:00

1223 lines
122 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>22/prcd</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 '22/ptd' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">core</a></li><li><a href="index.html#22">Chapter 22: Phrases</a></li><li><b>Phrase Type Data</b></li></ul><p class="purpose">To create, manage, compare the logical specificity of, and assist excerpt parsing concerning, the type of a To phrase. This involves whether it is void, determines a condition or returns a value (and if so, what kind of value); and also what parameters it takes (possibly values, possible other types used by inline definitions) and their types in turn.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP10">&#167;10. Creation</a></li><li><a href="#SP13">&#167;13. The kind of a phrase</a></li><li><a href="#SP16">&#167;16. The tokens</a></li><li><a href="#SP19">&#167;19. Deprecation</a></li><li><a href="#SP20">&#167;20. Adding token names to a stack frame</a></li><li><a href="#SP21">&#167;21. Comparison of PHTDs</a></li><li><a href="#SP22">&#167;22. Say phrases</a></li><li><a href="#SP23">&#167;23. Inline phrases</a></li><li><a href="#SP28">&#167;28. Return value polymorphism</a></li><li><a href="#SP29">&#167;29. Tweaking phrase ordering</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Definitions. </b></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>Inform is an unusual language in that it does not distinguish between
functions, control structures and keywords: they are all phrases. This
means that the functional description of what a phrase does has to be more
than just a kind like <code class="display"><span class="extract">phrase number -&gt; text</span></code>. For example, "if ..., ..."
is a phrase in Inform, but it has no kind as such: the first "..." is a
condition, the second "..." a phrase invocation, and neither one of those
is a value, so neither one has a kind. It follows that we are going to
need a rather larger data structure to describe what a phrase does than
simply a kind, and that's what we create in this section.
</p>
<p class="inwebparagraph">Here's a simple example from the Standard Rules:
</p>
<blockquote>
<p>To sort (T - table name) in (TC - table column) order: ...</p>
</blockquote>
<p class="inwebparagraph">The "word sequence" for this consists of five "words": sort, 0, in, 1,
order. That is, we store five integers: the word numbers for "sort", "in"
and "order", and then very low integers represent tokens rather than fixed
wording. (It follows from this that a phrase can't be defined in the first
ten words of the source text, but that's okay, because those words can
never be from the author's own source text anyway &mdash; they contain the
instruction to load the Standard Rules.)
</p>
<p class="inwebparagraph">The tokens are the variably-worded parts written with brackets. The "token
sequence" consists of two tokens, "T - table name" and "TC - table column".
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_TOKENS_PER_PHRASE</span><span class="plain"> 10</span>
<span class="definitionkeyword">define</span> <span class="constant">MAX_WORDS_PER_PHRASE</span><span class="plain"> 32 </span> <span class="comment">the most the excerpt parser can hold anyway</span>
</pre>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">ph_type_data</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">registration_text</span><span class="plain">; </span> <span class="comment">words used to register the excerpt meaning</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">word_sequence</span><span class="plain">[</span><span class="constant">MAX_WORDS_PER_PHRASE</span><span class="plain">]; </span> <span class="comment">the "word sequence": see above</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_words</span><span class="plain">; </span> <span class="comment">length of the word sequence</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">phrase_token</span><span class="plain"> </span><span class="identifier">token_sequence</span><span class="plain">[</span><span class="constant">MAX_TOKENS_PER_PHRASE</span><span class="plain">];</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_tokens</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="comment">one of the <code class="display"><span class="extract">*_MOR</span></code> values</span>
<span class="reserved">struct</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="comment"><code class="display"><span class="extract">NULL</span></code> except in the <code class="display"><span class="extract">DECIDES_VALUE_MOR</span></code> case</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">say_details</span><span class="plain"> </span><span class="identifier">as_say</span><span class="plain">; </span> <span class="comment">used only for "say" phrases, that is, text substitutions</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">inline_details</span><span class="plain"> </span><span class="identifier">as_inline</span><span class="plain">; </span> <span class="comment">side effects for phrases like C keywords</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">now_deprecated</span><span class="plain">; </span> <span class="comment">is this a phrase likely to be withdrawn in future?</span>
<span class="plain">} </span><span class="reserved">ph_type_data</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure ph_type_data is accessed in 14/ds2, 22/dptd, 25/pi, 25/ci, 25/cii, 25/cp and here.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>The two tokens of our example phrase, then, are each stored in one of these:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">STANDARD_PT_CONSTRUCT</span><span class="plain"> 1 </span> <span class="comment">e.g., <code class="display"><span class="extract">12</span></code>, <code class="display"><span class="extract">number</span></code>, <code class="display"><span class="extract">open door</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">NEW_LOCAL_PT_CONSTRUCT</span><span class="plain"> 2 </span> <span class="comment">e.g., <code class="display"><span class="extract">nonexisting number variable</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">EXISTING_LOCAL_PT_CONSTRUCT</span><span class="plain"> 3 </span> <span class="comment">e.g., <code class="display"><span class="extract">existing number variable</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">CONDITION_PT_CONSTRUCT</span><span class="plain"> 4 </span> <span class="comment">e.g., <code class="display"><span class="extract">a condition</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">STORAGE_PT_CONSTRUCT</span><span class="plain"> 5 </span> <span class="comment">e.g., <code class="display"><span class="extract">storage</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">TABLE_REFERENCE_PT_CONSTRUCT</span><span class="plain"> 6 </span> <span class="comment">e.g., <code class="display"><span class="extract">table-reference</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">KIND_NAME_PT_CONSTRUCT</span><span class="plain"> 7 </span> <span class="comment">e.g., <code class="display"><span class="extract">name of kind</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">VOID_PT_CONSTRUCT</span><span class="plain"> 8 </span> <span class="comment">e.g., or in fact only, <code class="display"><span class="extract">phrase</span></code></span>
</pre>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">phrase_token</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">token_name</span><span class="plain">; </span> <span class="comment">name</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">to_match</span><span class="plain">; </span> <span class="comment">what we expect to find here</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">token_kind</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">construct</span><span class="plain">; </span> <span class="comment">one of the above values</span>
<span class="plain">} </span><span class="reserved">phrase_token</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure phrase_token is accessed in 5/lp, 12/dtd, 13/kak, 13/rsfk, 14/lv, 14/ds2, 15/cp, 19/tod, 22/dptd, 25/pi, 25/ci, 25/cii and here.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>At first sight that structure looks a bit redundant. Why do we store both a
specification, telling the matcher what to allow, and also a kind?
</p>
<p class="inwebparagraph">The answer is that the kinds hierarchy is not rich enough. "Door" is a kind,
but "open door" is not, and nor is "even number", or
</p>
<blockquote>
<p>a woman in a lighted room</p>
</blockquote>
<p class="inwebparagraph">It seems at first appealing to decide that "open door" (say) ought to be
a kind, but no variable with this kind would be safe: merely by opening a
door somewhere during play, the player could make its current value no
longer fit its kind.
</p>
<p class="inwebparagraph">In order to preserve type safety, Inform forces its storage objects
(variables, table entries, and so on) to have fixed kinds decided at compile
time. We are allowed to create a "number that varies", but not an "even
number that varies", because the former is a kind and the latter is not.
This is rather like C, where variables might be declared like so:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">int width, height; char *name;</span>
</pre>
<p class="inwebparagraph">In C, the range of types which can be stored is the same as the range of
types which can be function arguments, so for instance:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">int area(int width, int height) { return width*height; }</span>
</pre>
<p class="inwebparagraph">But whereas Inform's variables are much like C's, Inform's phrase definitions
are not like C's functions, and they can have much more general arguments:
</p>
<blockquote>
<p>To jemmy open (the barrier - a closed door): ...</p>
</blockquote>
<blockquote>
<p>To repeat (P - a phrase) indefinitely: ...</p>
</blockquote>
<p class="inwebparagraph">We therefore need a much more general way to describe what text can appear
in phrase arguments than a kind can provide, and this is what leads us to
the idea of a "specification". In fact, though, even these examples are
not general enough. Natural language is very slippery about concepts which,
in most computing theories, are formally separate. Consider for instance
the overloaded definition of a phrase like this one:
</p>
<blockquote>
<p>To appreciate (composer - a person): ...</p>
</blockquote>
<blockquote>
<p>To appreciate (composer - Alessandro Striggio): ...</p>
</blockquote>
<p class="inwebparagraph">The early design of Inform did not permit this, since it clearly confused
values and types, but this lack was in fact reported as a bug &mdash; always a
sign that users considered it a natural thing to do. Specifications therefore
needed to be able to represent not only vague descriptions like "person",
but also explicit identities like "Alessandro Striggio".
</p>
<p class="inwebparagraph">Moreover we can't store the specification alone, because then these can't be
represented:
</p>
<blockquote>
<p>(tally - arithmetic value of kind K)</p>
</blockquote>
<blockquote>
<p>(name of a kind of enumerated value)</p>
</blockquote>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>Say phrases &mdash; text substitutions, that is &mdash; need more:
</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">say_details</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">say_phrase</span><span class="plain">; </span> <span class="comment">one of the three <code class="display"><span class="extract">*_SAY_PHRASE</span></code> values</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">say_phrase_running_on</span><span class="plain">; </span> <span class="comment">ignore implied newlines in previous invocation</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">say_phrase_stream_position</span><span class="plain">; </span> <span class="comment">one of the <code class="display"><span class="extract">SSP_*</span></code> values above</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">say_phrase_stream_token_at</span><span class="plain">; </span> <span class="comment">word number of say stream token name</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">say_phrase_stream_closing_token_at</span><span class="plain">; </span> <span class="comment">ditto for choice of ending</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">say_control_structure</span><span class="plain">; </span> <span class="comment">one of the four <code class="display"><span class="extract">*_SAY_CS</span></code> values below</span>
<span class="plain">} </span><span class="reserved">say_details</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure say_details is accessed in 25/cp and here.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>These are for "say control structures", as in "fish [if day is Friday]of
course[end if]" &mdash; the "[if ...]" and "[end if]" both being say phrases which
are control structures.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">NO_SAY_CS</span><span class="plain"> 0</span>
<span class="definitionkeyword">define</span> <span class="constant">IF_SAY_CS</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">OTHERWISE_SAY_CS</span><span class="plain"> 2</span>
<span class="definitionkeyword">define</span> <span class="constant">OTHERWISE_IF_SAY_CS</span><span class="plain"> 3</span>
<span class="definitionkeyword">define</span> <span class="constant">END_IF_SAY_CS</span><span class="plain"> 4</span>
</pre>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>The say stream is the sequence of successive invocations in a single say,
or in a piece of text with substitutions. Some say phrases are compound in that
they must occur in a given sequence.
</p>
<p class="inwebparagraph">The following markers are used to identify such say phrases:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">SSP_NONE</span><span class="plain"> 0</span>
<span class="definitionkeyword">define</span> <span class="constant">SSP_START</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">SSP_MIDDLE</span><span class="plain"> 2</span>
<span class="definitionkeyword">define</span> <span class="constant">SSP_END</span><span class="plain"> 3</span>
</pre>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>Inline phrase definitions are used to implement what, in other languages,
would be control-structure keywords, so inline phrases sometimes need bells,
whistles and doodads which regular phrases don't.
</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">inline_details</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">invoked_inline_not_as_call</span><span class="plain">; </span> <span class="comment">if <code class="display"><span class="extract">FALSE</span></code>, none of the rest applies</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">let_phrase</span><span class="plain">; </span> <span class="comment">one of the <code class="display"><span class="extract">*_LET_PHRASE</span></code> values below</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">assignment_phrase</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">TRUE</span></code> if this has to be typechecked as an assignment</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">arithmetical_operation</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">-1</span></code>, or one of the <code class="display"><span class="extract">*_OPERATION</span></code> constants</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">block_follows</span><span class="plain">; </span> <span class="comment">for inline phrases only: followed by a begin... end block?</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">only_in_loop</span><span class="plain">; </span> <span class="comment">if not null, the phrase can only be used in this block</span>
<span class="plain">} </span><span class="reserved">inline_details</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure inline_details is accessed in 22/dptd, 25/pi and here.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>Where:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">NOT_A_LET_PHRASE</span><span class="plain"> 0 </span> <span class="comment">needs to be 0 so that <code class="display"><span class="extract">let_phrase</span></code> can be a C condition</span>
<span class="definitionkeyword">define</span> <span class="constant">ASSIGNMENT_LET_PHRASE</span><span class="plain"> 1 </span> <span class="comment">the regular "let"</span>
<span class="definitionkeyword">define</span> <span class="constant">EQUATION_LET_PHRASE</span><span class="plain"> 2 </span> <span class="comment">"let" inviting Inform to solve an equation</span>
</pre>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. Creation. </b></p>
<pre class="display">
<span class="reserved">ph_type_data</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::new</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">ph_type_data</span><span class="plain"> </span><span class="identifier">phtd</span><span class="plain">;</span>
<span class="identifier">phtd</span><span class="element">.registration_text</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="identifier">phtd</span><span class="element">.manner_of_return</span><span class="plain"> = </span><span class="constant">DECIDES_NOTHING_MOR</span><span class="plain">;</span>
<span class="identifier">phtd</span><span class="element">.return_kind</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">phtd</span><span class="element">.no_words</span><span class="plain"> = 0;</span>
<span class="identifier">phtd</span><span class="element">.no_tokens</span><span class="plain"> = 0;</span>
<span class="identifier">phtd</span><span class="element">.as_say</span><span class="plain"> = </span><span class="functiontext">Phrases::TypeData::new_say_details</span><span class="plain">();</span>
<span class="identifier">phtd</span><span class="element">.as_inline</span><span class="plain"> = </span><span class="functiontext">Phrases::TypeData::new_inline_details</span><span class="plain">();</span>
<span class="identifier">phtd</span><span class="element">.now_deprecated</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">phtd</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::new is used in 22/ph (<a href="22-ph.html#SP6_3">&#167;6.3</a>), 22/pav (<a href="22-pav.html#SP5">&#167;5</a>).</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>And the manner of return is set shortly after that:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::set_mor</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">mor</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">phtd</span><span class="plain">-</span><span class="element">&gt;manner_of_return</span><span class="plain"> = </span><span class="identifier">mor</span><span class="plain">;</span>
<span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;return_kind</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::get_mor</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;manner_of_return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">Phrases::TypeData::get_return_kind</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;manner_of_return</span><span class="plain"> == </span><span class="constant">DECIDES_CONDITION_MOR</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K_truth_state</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;return_kind</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::set_mor is used in 22/ph (<a href="22-ph.html#SP6_3">&#167;6.3</a>), 22/dptd (<a href="22-dptd.html#SP16">&#167;16</a>).</p>
<p class="endnote">The function Phrases::TypeData::get_mor is used in 14/rv (<a href="14-rv.html#SP23_7">&#167;23.7</a>), 25/cii (<a href="25-cii.html#SP3_1_1_4_7_1">&#167;3.1.1.4.7.1</a>).</p>
<p class="endnote">The function Phrases::TypeData::get_return_kind is used in <a href="#SP13">&#167;13</a>, 14/rv (<a href="14-rv.html#SP23_7">&#167;23.7</a>), 14/ds2 (<a href="14-ds2.html#SP11_9_1_1">&#167;11.9.1.1</a>), 20/eq (<a href="20-eq.html#SP41_3">&#167;41.3</a>), 22/cs (<a href="22-cs.html#SP10_6">&#167;10.6</a>).</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b></p>
<pre class="display">
<span class="reserved">char</span><span class="plain"> *</span><span class="functiontext">Phrases::TypeData::describe_manner_of_return</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">mor</span><span class="plain">, </span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</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="reserved">switch</span><span class="plain"> (</span><span class="identifier">mor</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">DECIDES_NOTHING_MOR</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"no value resulting"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">DECIDES_VALUE_MOR</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">phtd</span><span class="plain">) &amp;&amp; (</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;return_kind</span><span class="plain">) &amp;&amp; (</span><span class="identifier">K</span><span class="plain">)) *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;return_kind</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="string">"a phrase to decide a value"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">DECIDES_CONDITION_MOR</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"a phrase to make a decision"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">DECIDES_NOTHING_AND_RETURNS_MOR</span><span class="plain">:</span>
<span class="reserved">return</span><span class="plain"> </span><span class="string">"a phrase providing an outcome to a rulebook"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="string">"some phrase"</span><span class="plain">; </span> <span class="comment">should never actually be needed</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::describe_manner_of_return is used in 22/dptd (<a href="22-dptd.html#SP1">&#167;1</a>), 25/ci (<a href="25-ci.html#SP3_1_1_2">&#167;3.1.1.2</a>).</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. The kind of a phrase. </b>As noted above, phrases can be such that "kind" is meaningless (consider "if",
or "now"), but it might be tempting to think that for function-like phrases,
at least, the kind tells you everything about when they apply. But this isn't
true. Consider:
</p>
<blockquote>
<p>To barricade (D - a door): ...</p>
</blockquote>
<blockquote>
<p>To barricade (D - a closed door): ...</p>
</blockquote>
<p class="inwebparagraph">These both have the same kind, <code class="display"><span class="extract">phrase door -&gt; nothing</span></code>, and that's reasonable
because they're safe to use in the same circumstances. But they will apply
in different circumstances at run-time.
</p>
<p class="inwebparagraph">A further subtlety comes with phrases like:
</p>
<blockquote>
<p>To juxtapose (name of kind of value K) with (alpha - K) and (beta - K): ...</p>
</blockquote>
<p class="inwebparagraph">What's the kind of this? From the point of view of compilation, it's
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">phrase (K, K) -&gt; nothing</span>
</pre>
<p class="inwebparagraph">but this is not quite right, because it doesn't make clear how Inform is to
infer the kind K &mdash; should it take it from the value supplied as alpha, or
beta? This makes a difference in some cases of ambiguity. The answer of
course is neither: for example, when Inform reads
</p>
<blockquote>
<p>juxtapose numbers with 12 and 31;</p>
</blockquote>
<p class="inwebparagraph">it sets K to "number" from the explicit text "numbers", rather than inferring
it from the 12 or the 31. So, internally, Inform regards the kind of this
phrase as
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">phrase (K, K, K) -&gt; nothing</span>
</pre>
<p class="inwebparagraph">even though it will compile actual function calls to "juxtapose" with two
rather than three arguments. (This is all a sort of poor man's second-order
logic, since one argument is in effect a kind rather than a value.)
</p>
<pre class="display">
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">Phrases::TypeData::kind</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">argument_kinds</span><span class="plain">[</span><span class="constant">MAX_TOKENS_PER_PHRASE</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">j</span><span class="plain"> = 0;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;no_tokens</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="identifier">argument_kinds</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">++] = </span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;token_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.token_kind</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="functiontext">Phrases::TypeData::get_return_kind</span><span class="plain">(</span><span class="identifier">phtd</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Kinds::function_kind</span><span class="plain">(</span><span class="identifier">j</span><span class="plain">, </span><span class="identifier">argument_kinds</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::kind is used in <a href="#SP14">&#167;14</a>, 20/eq (<a href="20-eq.html#SP48">&#167;48</a>), 22/cs (<a href="22-cs.html#SP10_5">&#167;10.5</a>), 22/ph (<a href="22-ph.html#SP6_5">&#167;6.5</a>), 22/dptd (<a href="22-dptd.html#SP6_5">&#167;6.5</a>), 22/pav (<a href="22-pav.html#SP5">&#167;5</a>), 25/pi (<a href="25-pi.html#SP3">&#167;3</a>), 25/cp (<a href="25-cp.html#SP3_2">&#167;3.2</a>).</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. </b>Whence:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::contains_variables</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">) {</span>
<span class="reserved">return</span>
<span class="identifier">Kinds::contains</span><span class="plain">(</span>
<span class="functiontext">Phrases::TypeData::kind</span><span class="plain">(</span><span class="identifier">phtd</span><span class="plain">),</span>
<span class="identifier">CON_KIND_VARIABLE</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::contains_variables is used in 14/ds2 (<a href="14-ds2.html#SP11_9_1_1_4">&#167;11.9.1.1.4</a>).</p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. </b>More specifically:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::tokens_contain_variable</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">v</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">&lt;</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;no_tokens</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">Kinds::Behaviour::involves_var</span><span class="plain">(</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;token_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.token_kind</span><span class="plain">, </span><span class="identifier">v</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::tokens_contain_variable is used in 22/cs (<a href="22-cs.html#SP10_6">&#167;10.6</a>).</p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. The tokens. </b></p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::get_no_tokens</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;no_tokens</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::get_no_tokens is used in 25/in (<a href="25-in.html#SP18">&#167;18</a>).</p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. </b></p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::index_of_token_creating_a_variable</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</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="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;no_tokens</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">phtd</span><span class="plain">-</span><span class="element">&gt;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">NEW_LOCAL_PT_CONSTRUCT</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> -1;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::index_of_token_creating_a_variable appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP18"></a><b>&#167;18. </b>This odd-looking question is asked when handling the ambiguity between the
name of a property ("carrying capacity", say) as a value in its own right,
and the same name metonymically referring to the value of the property for
a given instance ("carrying capacity of the player", say).
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::preamble_requires_property_value</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</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="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;no_tokens</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="functiontext">Lvalues::get_storage_form</span><span class="plain">(</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;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="plain">== </span><span class="constant">PROPERTY_VALUE_NT</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::preamble_requires_property_value appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP19"></a><b>&#167;19. Deprecation. </b>Phrases which are "deprecated" are those defined by the Standard Rules, or
other extensions in the standard Inform installation, which we now think are
redundant or a bad idea: we don't want to withdraw them without warning, so
the procedure is to deprecate them in one major build and withdraw them
in the next.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::deprecated</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;now_deprecated</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::deprecate_phrase</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">) {</span>
<span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;now_deprecated</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::deprecated is used in 22/dptd (<a href="22-dptd.html#SP6_6">&#167;6.6</a>), 22/pi (<a href="22-pi.html#SP1_3">&#167;1.3</a>).</p>
<p class="endnote">The function Phrases::TypeData::deprecate_phrase is used in 22/dptd (<a href="22-dptd.html#SP17">&#167;17</a>).</p>
<p class="inwebparagraph"><a id="SP20"></a><b>&#167;20. Adding token names to a stack frame. </b>Suppose Inform is compiling code to represent this:
</p>
<blockquote>
<p>To sort (T - table name) in (TC - table column) order: ...</p>
</blockquote>
<p class="inwebparagraph">On the stack frame for this code, "T" and "TC" will need to be local
variables &mdash; that is, they will need to be locally available as names,
referring to the values which the phrase was called with.
</p>
<p class="inwebparagraph">In that simple example, the phrase preamble makes clear what the kinds of
"T" and "TC" should be, but it isn't always so simple. For example:
</p>
<blockquote>
<p>To add (new entry - K) to (L - list of values of kind K): ...</p>
</blockquote>
<p class="inwebparagraph">Here the preamble allows a wide range of kinds, and Inform compiles
different versions of the code for each value of K actually needed. So
the following routine is called with a particular kind to be used. For
instance, if the source text ever contains an invocation like:
</p>
<blockquote>
<p>add 14 to the list of scores;</p>
</blockquote>
<p class="inwebparagraph">then at some point Inform will have to compile a version of the phrase
which has the kind:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">phrase (number, list of numbers) -&gt; nothing</span>
</pre>
<p class="inwebparagraph">The routine below then dismantles that kind to extract the kinds of the
arguments, "number" and then "list of numbers", and creates local
variables "new entry" and "L" with those kinds.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::into_stack_frame</span><span class="plain">(</span><span class="reserved">ph_stack_frame</span><span class="plain"> *</span><span class="identifier">phsf</span><span class="plain">,</span>
<span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_in_this_compilation</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">first</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">kind_in_this_compilation</span><span class="plain">) != </span><span class="identifier">CON_phrase</span><span class="plain">)</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"no function kind"</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">args</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">ret</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">Kinds::binary_construction_material</span><span class="plain">(</span><span class="identifier">kind_in_this_compilation</span><span class="plain">, &amp;</span><span class="identifier">args</span><span class="plain">, &amp;</span><span class="identifier">ret</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="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;no_tokens</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="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">args</span><span class="plain">) != </span><span class="identifier">CON_TUPLE_ENTRY</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad tupling"</span><span class="plain">);</span>
<span class="identifier">Kinds::binary_construction_material</span><span class="plain">(</span><span class="identifier">args</span><span class="plain">, &amp;</span><span class="identifier">K</span><span class="plain">, &amp;</span><span class="identifier">args</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">first</span><span class="plain">) {</span>
<span class="functiontext">LocalVariables::add_call_parameter</span><span class="plain">(</span><span class="identifier">phsf</span><span class="plain">, </span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;token_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.token_name</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">local_variable</span><span class="plain"> *</span><span class="identifier">lvar</span><span class="plain"> = </span><span class="functiontext">LocalVariables::get_ith_parameter</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">lvar</span><span class="plain">) </span><span class="functiontext">LocalVariables::set_kind</span><span class="plain">(</span><span class="identifier">lvar</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">ret</span><span class="plain">, </span><span class="identifier">K_nil</span><span class="plain">)) </span><span class="functiontext">Frames::set_kind_returned</span><span class="plain">(</span><span class="identifier">phsf</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Frames::set_kind_returned</span><span class="plain">(</span><span class="identifier">phsf</span><span class="plain">, </span><span class="identifier">ret</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::into_stack_frame is used in 22/ph (<a href="22-ph.html#SP6_5">&#167;6.5</a>), 25/cp (<a href="25-cp.html#SP3_2">&#167;3.2</a>).</p>
<p class="inwebparagraph"><a id="SP21"></a><b>&#167;21. Comparison of PHTDs. </b>This is used when sorting "To..." phrases in order of logical priority:
see Phrases for the return codes.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::comparison</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd1</span><span class="plain">, </span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd2</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phtd1</span><span class="plain"> == </span><span class="identifier">phtd2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">EQUAL_PH</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Loop construct keywords have priority</span> <span class="cwebmacronumber">21.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">More fixed words beats fewer</span> <span class="cwebmacronumber">21.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">More tokens beats fewer</span> <span class="cwebmacronumber">21.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Next use alphabetical order, counting tokens as after the Zs</span> <span class="cwebmacronumber">21.4</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Finally try comparing the to-match specifications of the tokens</span> <span class="cwebmacronumber">21.5</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">INCOMPARABLE_PH</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::comparison is used in 22/tp (<a href="22-tp.html#SP4">&#167;4</a>).</p>
<p class="inwebparagraph"><a id="SP21_1"></a><b>&#167;21.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Loop construct keywords have priority</span> <span class="cwebmacronumber">21.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="functiontext">Phrases::TypeData::inline_type_data_comparison</span><span class="plain">(</span><span class="identifier">phtd1</span><span class="plain">, </span><span class="identifier">phtd2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> != </span><span class="constant">EQUAL_PH</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP21_2"></a><b>&#167;21.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">More fixed words beats fewer</span> <span class="cwebmacronumber">21.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">fw1</span><span class="plain"> = </span><span class="identifier">phtd1</span><span class="plain">-</span><span class="element">&gt;no_words</span><span class="plain"> - </span><span class="identifier">phtd1</span><span class="plain">-</span><span class="element">&gt;no_tokens</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">fw2</span><span class="plain"> = </span><span class="identifier">phtd2</span><span class="plain">-</span><span class="element">&gt;no_words</span><span class="plain"> - </span><span class="identifier">phtd2</span><span class="plain">-</span><span class="element">&gt;no_tokens</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fw1</span><span class="plain"> &gt; </span><span class="identifier">fw2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">BEFORE_PH</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fw1</span><span class="plain"> &lt; </span><span class="identifier">fw2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">AFTER_PH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP21_3"></a><b>&#167;21.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">More tokens beats fewer</span> <span class="cwebmacronumber">21.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phtd1</span><span class="plain">-</span><span class="element">&gt;no_tokens</span><span class="plain"> &gt; </span><span class="identifier">phtd2</span><span class="plain">-</span><span class="element">&gt;no_tokens</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">BEFORE_PH</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phtd1</span><span class="plain">-</span><span class="element">&gt;no_tokens</span><span class="plain"> &lt; </span><span class="identifier">phtd2</span><span class="plain">-</span><span class="element">&gt;no_tokens</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">AFTER_PH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP21_4"></a><b>&#167;21.4. </b>At this point the two phrases have the same number of words and tokens,
but the words may be different and/or the tokens in different places.
We might for example be comparing these two:
</p>
<blockquote>
<p>To grab (the prize - an object) swiftly: ...</p>
</blockquote>
<blockquote>
<p>To grab at (the rosette - an object): ...</p>
</blockquote>
<p class="inwebparagraph">We alphabetical order, placing "grab ZZZZZZ swiftly" after "grab at ZZZZZZ".
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Next use alphabetical order, counting tokens as after the Zs</span> <span class="cwebmacronumber">21.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">phtd1</span><span class="plain">-</span><span class="element">&gt;no_words</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">phtd1</span><span class="plain">-</span><span class="element">&gt;word_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] &lt; </span><span class="constant">MAX_TOKENS_PER_PHRASE</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phtd2</span><span class="plain">-</span><span class="element">&gt;word_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] &gt;= </span><span class="constant">MAX_TOKENS_PER_PHRASE</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">AFTER_PH</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">phtd2</span><span class="plain">-</span><span class="element">&gt;word_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] &lt; </span><span class="constant">MAX_TOKENS_PER_PHRASE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">BEFORE_PH</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">x</span><span class="plain"> = </span><span class="identifier">Wide::cmp</span><span class="plain">(</span>
<span class="identifier">Lexer::word_raw_text</span><span class="plain">(</span><span class="identifier">phtd1</span><span class="plain">-</span><span class="element">&gt;word_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]),</span>
<span class="identifier">Lexer::word_raw_text</span><span class="plain">(</span><span class="identifier">phtd2</span><span class="plain">-</span><span class="element">&gt;word_sequence</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">x</span><span class="plain"> &gt; 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">AFTER_PH</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">x</span><span class="plain"> &lt; 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">BEFORE_PH</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="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP21_5"></a><b>&#167;21.5. </b>Now our two phrases have identical wording, and tokens in the same positions,
but may have different specifications for them. For example:
</p>
<blockquote>
<p>To grab at (the rosette - an object): ...</p>
</blockquote>
<blockquote>
<p>To grab at (the rosette - a thing on the table): ...</p>
</blockquote>
<p class="inwebparagraph">We give priority to the second of these, because it's more specific. On
the other hand these are simply incomparable:
</p>
<blockquote>
<p>To grab at (the rosette - an object): ...</p>
</blockquote>
<blockquote>
<p>To grab at (the prime - a number): ...</p>
</blockquote>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Finally try comparing the to-match specifications of the tokens</span> <span class="cwebmacronumber">21.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">possibly_subschema</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">, </span><span class="identifier">possibly_superschema</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">phtd1</span><span class="plain">-</span><span class="element">&gt;no_tokens</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">spec1</span><span class="plain"> = </span><span class="identifier">phtd1</span><span class="plain">-</span><span class="element">&gt;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="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec2</span><span class="plain"> = </span><span class="identifier">phtd2</span><span class="plain">-</span><span class="element">&gt;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>
&lt;<span class="cwebmacro">See if the ith token rules out being a sub- or superschema</span> <span class="cwebmacronumber">21.5.2</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">possibly_subschema</span><span class="plain">) || (</span><span class="identifier">possibly_superschema</span><span class="plain">))</span>
&lt;<span class="cwebmacro">These are worryingly similar in wording, so check the return kinds</span> <span class="cwebmacronumber">21.5.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">possibly_subschema</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">SUBSCHEMA_PH</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">possibly_superschema</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">SUPERSCHEMA_PH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP21_5_1"></a><b>&#167;21.5.1. </b>We need to watch out for this sort of thing:
</p>
<blockquote>
<p>To decide what number is my special value: decide on 4.</p>
</blockquote>
<blockquote>
<p>To decide what person is my special value: decide on the player.</p>
</blockquote>
<p class="inwebparagraph">which makes "my special value" of a kind which can't be decided; but
we can't just compare the return kinds, because that might pick up
false positives in the case of kind variables, etc.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">These are worryingly similar in wording, so check the return kinds</span> <span class="cwebmacronumber">21.5.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">phtd1</span><span class="plain">-</span><span class="element">&gt;manner_of_return</span><span class="plain"> != </span><span class="identifier">phtd2</span><span class="plain">-</span><span class="element">&gt;manner_of_return</span><span class="plain">) ||</span>
<span class="plain">((</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">phtd1</span><span class="plain">-</span><span class="element">&gt;return_kind</span><span class="plain">, </span><span class="identifier">phtd2</span><span class="plain">-</span><span class="element">&gt;return_kind</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Kinds::Behaviour::definite</span><span class="plain">(</span><span class="identifier">phtd1</span><span class="plain">-</span><span class="element">&gt;return_kind</span><span class="plain">))))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">CONFLICTED_PH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP21_5">&#167;21.5</a>.</p>
<p class="inwebparagraph"><a id="SP21_5_2"></a><b>&#167;21.5.2. </b>We delegate to <code class="display"><span class="extract">Specifications::compare_specificity</span></code> to decide what's more
specific, but note that this routine can return 0 (meaning, equally
specific) for two different reasons: because the specifications are basically
the same as each other, or because they're completely different but have
about the same complexity. The <code class="display"><span class="extract">wont_mix</span></code> flag is set in the latter case.
</p>
<p class="inwebparagraph">Because the test is made by seeing if one specification matches another, we
also protect it from the special "nonexisting variable" tokens,
used only in inline phrase preambles. It would otherwise think "existing
variable" is more specific than "new variable", which isn't helpful.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">See if the ith token rules out being a sub- or superschema</span> <span class="cwebmacronumber">21.5.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">phtd1</span><span class="plain">-</span><span class="element">&gt;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">NEW_LOCAL_PT_CONSTRUCT</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">phtd2</span><span class="plain">-</span><span class="element">&gt;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">NEW_LOCAL_PT_CONSTRUCT</span><span class="plain">)) {</span>
<span class="identifier">possibly_superschema</span><span class="plain"> = </span><span class="identifier">FALSE</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">phtd1</span><span class="plain">-</span><span class="element">&gt;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">NEW_LOCAL_PT_CONSTRUCT</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">phtd2</span><span class="plain">-</span><span class="element">&gt;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">NEW_LOCAL_PT_CONSTRUCT</span><span class="plain">)) {</span>
<span class="identifier">possibly_subschema</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">wont_mix</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">r</span><span class="plain"> = </span><span class="functiontext">Specifications::compare_specificity</span><span class="plain">(</span><span class="identifier">spec1</span><span class="plain">, </span><span class="identifier">spec2</span><span class="plain">, &amp;</span><span class="identifier">wont_mix</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">wont_mix</span><span class="plain">) { </span><span class="identifier">possibly_subschema</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="identifier">possibly_superschema</span><span class="plain"> = </span><span class="identifier">FALSE</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">r</span><span class="plain"> &lt; 0) </span><span class="identifier">possibly_subschema</span><span class="plain"> = </span><span class="identifier">FALSE</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">r</span><span class="plain"> &gt; 0) </span><span class="identifier">possibly_superschema</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP21_5">&#167;21.5</a>.</p>
<p class="inwebparagraph"><a id="SP22"></a><b>&#167;22. Say phrases. </b></p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">NOT_A_SAY_PHRASE</span><span class="plain"> 0 </span> <span class="comment">needs to be 0 so that <code class="display"><span class="extract">sd.say_phrase</span></code> can be a C condition</span>
<span class="definitionkeyword">define</span> <span class="constant">A_MISCELLANEOUS_SAY_PHRASE</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">THE_PRIMORDIAL_SAY_PHRASE</span><span class="plain"> 2</span>
</pre>
<pre class="display">
<span class="reserved">say_details</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::new_say_details</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">say_details</span><span class="plain"> </span><span class="identifier">sd</span><span class="plain">;</span>
<span class="identifier">sd</span><span class="element">.say_phrase</span><span class="plain"> = </span><span class="constant">NOT_A_SAY_PHRASE</span><span class="plain">;</span>
<span class="identifier">sd</span><span class="element">.say_phrase_running_on</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">sd</span><span class="element">.say_control_structure</span><span class="plain"> = </span><span class="constant">NO_SAY_CS</span><span class="plain">;</span>
<span class="identifier">sd</span><span class="element">.say_phrase_stream_position</span><span class="plain"> = </span><span class="constant">SSP_NONE</span><span class="plain">;</span>
<span class="identifier">sd</span><span class="element">.say_phrase_stream_token_at</span><span class="plain"> = -1;</span>
<span class="identifier">sd</span><span class="element">.say_phrase_stream_closing_token_at</span><span class="plain"> = -1;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">sd</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">first_say_made</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::make_sd</span><span class="plain">(</span><span class="reserved">say_details</span><span class="plain"> *</span><span class="identifier">sd</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">ro</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">cs</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">pos</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">at</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">cat</span><span class="plain">) {</span>
<span class="identifier">sd</span><span class="plain">-</span><span class="element">&gt;say_phrase</span><span class="plain"> = </span><span class="constant">A_MISCELLANEOUS_SAY_PHRASE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">first_say_made</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">sd</span><span class="plain">-</span><span class="element">&gt;say_phrase</span><span class="plain"> = </span><span class="constant">THE_PRIMORDIAL_SAY_PHRASE</span><span class="plain">;</span>
<span class="identifier">first_say_made</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">sd</span><span class="plain">-</span><span class="element">&gt;say_phrase_running_on</span><span class="plain"> = </span><span class="identifier">ro</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cs</span><span class="plain"> &gt;= 0) </span><span class="identifier">sd</span><span class="plain">-</span><span class="element">&gt;say_control_structure</span><span class="plain"> = </span><span class="identifier">cs</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pos</span><span class="plain"> &gt;= 0) </span><span class="identifier">sd</span><span class="plain">-</span><span class="element">&gt;say_phrase_stream_position</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">at</span><span class="plain"> &gt;= 0) </span><span class="identifier">sd</span><span class="plain">-</span><span class="element">&gt;say_phrase_stream_token_at</span><span class="plain"> = </span><span class="identifier">at</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cat</span><span class="plain"> &gt;= 0) </span><span class="identifier">sd</span><span class="plain">-</span><span class="element">&gt;say_phrase_stream_closing_token_at</span><span class="plain"> = </span><span class="identifier">cat</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::log_say_details</span><span class="plain">(</span><span class="reserved">say_details</span><span class="plain"> </span><span class="identifier">sd</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">sd</span><span class="element">.say_phrase</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">NOT_A_SAY_PHRASE</span><span class="plain">: </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">A_MISCELLANEOUS_SAY_PHRASE</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" A_MISCELLANEOUS_SAY_PHRASE\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">THE_PRIMORDIAL_SAY_PHRASE</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" THE_PRIMORDIAL_SAY_PHRASE\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" &lt;invalid say phrase status&gt;\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sd</span><span class="element">.say_phrase_running_on</span><span class="plain">)</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">" running on from previous say invocation without implied newline\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">sd</span><span class="element">.say_control_structure</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">NO_SAY_CS</span><span class="plain">: </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">IF_SAY_CS</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" IF_SAY_CS\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">END_IF_SAY_CS</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" END_IF_SAY_CS\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">OTHERWISE_SAY_CS</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" OTHERWISE_SAY_CS\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">OTHERWISE_IF_SAY_CS</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" OTHERWISE_IF_SAY_CS\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" &lt;invalid say phrase status&gt;\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::is_a_say_phrase</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="reserved">if</span><span class="plain"> ((</span><span class="identifier">ph</span><span class="plain">) &amp;&amp; (</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.as_say.say_phrase</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::is_a_say_X_phrase</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;as_say.say_phrase</span><span class="plain"> == </span><span class="constant">NOT_A_SAY_PHRASE</span><span class="plain">) </span><span class="reserved">return</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">phtd</span><span class="plain">-</span><span class="element">&gt;no_words</span><span class="plain"> == 2) &amp;&amp; (</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;word_sequence</span><span class="plain">[1] &lt; </span><span class="constant">MAX_TOKENS_PER_PHRASE</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::is_a_spare_say_X_phrase</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;as_say.say_phrase</span><span class="plain"> == </span><span class="constant">NOT_A_SAY_PHRASE</span><span class="plain">) </span><span class="reserved">return</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">phtd</span><span class="plain">-</span><span class="element">&gt;no_words</span><span class="plain"> == 2) &amp;&amp; (</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;word_sequence</span><span class="plain">[1] &lt; </span><span class="constant">MAX_TOKENS_PER_PHRASE</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">phtd</span><span class="plain">-</span><span class="element">&gt;token_sequence</span><span class="plain">[0]</span><span class="element">.token_kind</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K</span><span class="plain">) &amp;&amp; (</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="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::is_the_primordial_say</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;as_say.say_phrase</span><span class="plain"> == </span><span class="constant">THE_PRIMORDIAL_SAY_PHRASE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::get_say_data</span><span class="plain">(</span><span class="reserved">say_details</span><span class="plain"> *</span><span class="identifier">sd</span><span class="plain">,</span>
<span class="reserved">int</span><span class="plain"> *</span><span class="identifier">say_cs</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">ssp_tok</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">ssp_ctok</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">ssp_pos</span><span class="plain">) {</span>
<span class="plain">*</span><span class="identifier">say_cs</span><span class="plain"> = </span><span class="identifier">sd</span><span class="plain">-</span><span class="element">&gt;say_control_structure</span><span class="plain">;</span>
<span class="plain">*</span><span class="identifier">ssp_tok</span><span class="plain"> = </span><span class="identifier">sd</span><span class="plain">-</span><span class="element">&gt;say_phrase_stream_token_at</span><span class="plain">;</span>
<span class="plain">*</span><span class="identifier">ssp_ctok</span><span class="plain"> = </span><span class="identifier">sd</span><span class="plain">-</span><span class="element">&gt;say_phrase_stream_closing_token_at</span><span class="plain">;</span>
<span class="plain">*</span><span class="identifier">ssp_pos</span><span class="plain"> = </span><span class="identifier">sd</span><span class="plain">-</span><span class="element">&gt;say_phrase_stream_position</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::preface_for_say_HTML</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">say_details</span><span class="plain"> </span><span class="identifier">sd</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">paste_format</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sd</span><span class="element">.say_phrase</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sd</span><span class="element">.say_phrase</span><span class="plain"> != </span><span class="constant">THE_PRIMORDIAL_SAY_PHRASE</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">paste_format</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">PASTE_PHRASE_FORMAT</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"["</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INDEX_PHRASE_FORMAT</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"say \</span><span class="plain">"</span><span class="string">["</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">paste_format</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">PASTE_PHRASE_FORMAT</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"say \</span><span class="plain">"</span><span class="string">\</span><span class="plain">"</span><span class="string">"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NOT_APPLICABLE</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INDEX_PHRASE_FORMAT</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"say \</span><span class="plain">"</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::epilogue_for_say_HTML</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">say_details</span><span class="plain"> </span><span class="identifier">sd</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">paste_format</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sd</span><span class="element">.say_phrase</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sd</span><span class="element">.say_phrase</span><span class="plain"> != </span><span class="constant">THE_PRIMORDIAL_SAY_PHRASE</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">paste_format</span><span class="plain"> == </span><span class="constant">PASTE_PHRASE_FORMAT</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"]"</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">paste_format</span><span class="plain"> == </span><span class="constant">INDEX_PHRASE_FORMAT</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"]\</span><span class="plain">"</span><span class="string">"</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">paste_format</span><span class="plain"> == </span><span class="constant">INDEX_PHRASE_FORMAT</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::ssp_matches</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">ssp_tok</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">list_pos</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">int</span><span class="plain"> </span><span class="identifier">this_tok</span><span class="plain"> = </span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;as_say.say_phrase_stream_token_at</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">this_pos</span><span class="plain"> = </span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;as_say.say_phrase_stream_position</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">this_tok</span><span class="plain"> == -1) </span><span class="reserved">return</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">this_pos</span><span class="plain"> != </span><span class="identifier">list_pos</span><span class="plain">) </span><span class="reserved">return</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">compare_words</span><span class="plain">(</span><span class="identifier">ssp_tok</span><span class="plain">, </span><span class="identifier">this_tok</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">*</span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Wordings::trim_first_word</span><span class="plain">(</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;registration_text</span><span class="plain">); </span> <span class="comment">to remove the word "say"</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::new_say_details is used in <a href="#SP10">&#167;10</a>.</p>
<p class="endnote">The function Phrases::TypeData::make_sd is used in 22/dptd (<a href="22-dptd.html#SP17_2">&#167;17.2</a>).</p>
<p class="endnote">The function Phrases::TypeData::log_say_details is used in 22/dptd (<a href="22-dptd.html#SP1">&#167;1</a>).</p>
<p class="endnote">The function Phrases::TypeData::is_a_say_phrase is used in 14/ds2 (<a href="14-ds2.html#SP11_9_1_1_8">&#167;11.9.1.1.8</a>), 22/dptd (<a href="22-dptd.html#SP6_5">&#167;6.5</a>), 25/in (<a href="25-in.html#SP22">&#167;22</a>), 25/pi (<a href="25-pi.html#SP2">&#167;2</a>), 25/cp (<a href="25-cp.html#SP5_2_1">&#167;5.2.1</a>, <a href="25-cp.html#SP6">&#167;6</a>, <a href="25-cp.html#SP8_1">&#167;8.1</a>).</p>
<p class="endnote">The function Phrases::TypeData::is_a_say_X_phrase is used in 14/ds2 (<a href="14-ds2.html#SP15_1">&#167;15.1</a>).</p>
<p class="endnote">The function Phrases::TypeData::is_a_spare_say_X_phrase is used in 14/ds2 (<a href="14-ds2.html#SP10_1_1">&#167;10.1.1</a>, <a href="14-ds2.html#SP10_1_1_2">&#167;10.1.1.2</a>).</p>
<p class="endnote">The function Phrases::TypeData::is_the_primordial_say is used in 10/cap (<a href="10-cap.html#SP12_1">&#167;12.1</a>).</p>
<p class="endnote">The function Phrases::TypeData::get_say_data is used in 25/cp (<a href="25-cp.html#SP8_1">&#167;8.1</a>).</p>
<p class="endnote">The function Phrases::TypeData::preface_for_say_HTML is used in 22/dptd (<a href="22-dptd.html#SP3">&#167;3</a>).</p>
<p class="endnote">The function Phrases::TypeData::epilogue_for_say_HTML is used in 22/dptd (<a href="22-dptd.html#SP3">&#167;3</a>).</p>
<p class="endnote">The function Phrases::TypeData::ssp_matches is used in 25/cp (<a href="25-cp.html#SP9">&#167;9</a>).</p>
<p class="inwebparagraph"><a id="SP23"></a><b>&#167;23. Inline phrases. </b>On some platforms, notably Android, <code class="display"><span class="extract">inline</span></code> is a reserved word in some versions
of <code class="display"><span class="extract">gcc</span></code>, so we need to be careful not to call any variables or structure members
by than name.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">NO_BLOCK_FOLLOWS</span><span class="plain"> 0 </span> <span class="comment">this needs to be 0, to make if conditions work</span>
<span class="definitionkeyword">define</span> <span class="constant">MISCELLANEOUS_BLOCK_FOLLOWS</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">CONDITIONAL_BLOCK_FOLLOWS</span><span class="plain"> 2</span>
<span class="definitionkeyword">define</span> <span class="constant">LOOP_BODY_BLOCK_FOLLOWS</span><span class="plain"> 3</span>
</pre>
<pre class="display">
<span class="reserved">inline_details</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::new_inline_details</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">inline_details</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">;</span>
<span class="identifier">id</span><span class="element">.invoked_inline_not_as_call</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">id</span><span class="element">.let_phrase</span><span class="plain"> = </span><span class="constant">NOT_A_LET_PHRASE</span><span class="plain">;</span>
<span class="identifier">id</span><span class="element">.block_follows</span><span class="plain"> = </span><span class="constant">NO_BLOCK_FOLLOWS</span><span class="plain">;</span>
<span class="identifier">id</span><span class="element">.only_in_loop</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">id</span><span class="element">.assignment_phrase</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">id</span><span class="element">.arithmetical_operation</span><span class="plain"> = -1;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::new_inline_details is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP24"></a><b>&#167;24. </b></p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_lets_made</span><span class="plain"> = 0;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::make_id</span><span class="plain">(</span><span class="reserved">inline_details</span><span class="plain"> *</span><span class="identifier">id</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">op</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">assgn</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">let</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">blk</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">only_in</span><span class="plain">) {</span>
<span class="identifier">id</span><span class="plain">-</span><span class="element">&gt;arithmetical_operation</span><span class="plain"> = </span><span class="identifier">op</span><span class="plain">;</span>
<span class="identifier">id</span><span class="plain">-</span><span class="element">&gt;assignment_phrase</span><span class="plain"> = </span><span class="identifier">assgn</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">let</span><span class="plain"> == </span><span class="constant">ASSIGNMENT_LET_PHRASE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">no_lets_made</span><span class="plain">++ &gt;= 3)) </span><span class="identifier">let</span><span class="plain"> = </span><span class="constant">NOT_A_LET_PHRASE</span><span class="plain">;</span>
<span class="identifier">id</span><span class="plain">-</span><span class="element">&gt;let_phrase</span><span class="plain"> = </span><span class="identifier">let</span><span class="plain">;</span>
<span class="identifier">id</span><span class="plain">-</span><span class="element">&gt;block_follows</span><span class="plain"> = </span><span class="identifier">blk</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">only_in</span><span class="plain"> == -1) </span><span class="identifier">id</span><span class="plain">-</span><span class="element">&gt;only_in_loop</span><span class="plain"> = </span><span class="identifier">L</span><span class="string">"loop"</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">only_in</span><span class="plain"> &gt; 0) </span><span class="identifier">id</span><span class="plain">-</span><span class="element">&gt;only_in_loop</span><span class="plain"> = </span><span class="identifier">Lexer::word_text</span><span class="plain">(</span><span class="identifier">only_in</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::make_id is used in 22/dptd (<a href="22-dptd.html#SP17">&#167;17</a>).</p>
<p class="inwebparagraph"><a id="SP25"></a><b>&#167;25. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::log_inline_details</span><span class="plain">(</span><span class="reserved">inline_details</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">id</span><span class="element">.block_follows</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" block follows\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">id</span><span class="element">.let_phrase</span><span class="plain"> != </span><span class="constant">NOT_A_LET_PHRASE</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" let phrase (%d)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">id</span><span class="element">.let_phrase</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">id</span><span class="element">.only_in_loop</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" may only be used in a %w body\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">id</span><span class="element">.only_in_loop</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">id</span><span class="element">.invoked_inline_not_as_call</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" invoked inline\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" invoked by I6 function call\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::log_inline_details is used in 22/dptd (<a href="22-dptd.html#SP1">&#167;1</a>).</p>
<p class="inwebparagraph"><a id="SP26"></a><b>&#167;26. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::make_inline</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">) {</span>
<span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;as_inline.invoked_inline_not_as_call</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::invoked_inline</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="reserved">return</span><span class="plain"> </span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.as_inline.invoked_inline_not_as_call</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::make_inline is used in 22/ph (<a href="22-ph.html#SP6_3">&#167;6.3</a>).</p>
<p class="endnote">The function Phrases::TypeData::invoked_inline is used in 22/cs (<a href="22-cs.html#SP10_7">&#167;10.7</a>), 22/tp (<a href="22-tp.html#SP8">&#167;8</a>), 25/ci (<a href="25-ci.html#SP3_1_1_1">&#167;3.1.1.1</a>, <a href="25-ci.html#SP4_1">&#167;4.1</a>).</p>
<p class="inwebparagraph"><a id="SP27"></a><b>&#167;27. </b></p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::is_a_let_assignment</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="reserved">if</span><span class="plain"> (</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.as_inline.let_phrase</span><span class="plain"> == </span><span class="constant">ASSIGNMENT_LET_PHRASE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::is_a_let_equation</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="reserved">if</span><span class="plain"> (</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.as_inline.let_phrase</span><span class="plain"> == </span><span class="constant">EQUATION_LET_PHRASE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::arithmetic_operation</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="reserved">return</span><span class="plain"> </span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.as_inline.arithmetical_operation</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::is_arithmetic_phrase</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="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Phrases::TypeData::arithmetic_operation</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">) &gt;= 0) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Phrases::TypeData::arithmetic_operation</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">) &lt; </span><span class="identifier">NO_OPERATIONS</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::is_assignment_phrase</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="reserved">return</span><span class="plain"> </span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.as_inline.assignment_phrase</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="functiontext">Phrases::TypeData::only_in</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="reserved">if</span><span class="plain"> (</span><span class="identifier">ph</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.as_inline.only_in_loop</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::block_follows</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="reserved">return</span><span class="plain"> </span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.as_inline.block_follows</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::is_a_let_assignment is used in 14/ds2 (<a href="14-ds2.html#SP11_9_1_1_3_1">&#167;11.9.1.1.3.1</a>, <a href="14-ds2.html#SP11_9_1_1_3_1_1">&#167;11.9.1.1.3.1.1</a>, <a href="14-ds2.html#SP14">&#167;14</a>, <a href="14-ds2.html#SP15_1">&#167;15.1</a>).</p>
<p class="endnote">The function Phrases::TypeData::is_a_let_equation is used in 25/pi (<a href="25-pi.html#SP5_2">&#167;5.2</a>).</p>
<p class="endnote">The function Phrases::TypeData::arithmetic_operation is used in 14/ds2 (<a href="14-ds2.html#SP11_9_1_1_2">&#167;11.9.1.1.2</a>, <a href="14-ds2.html#SP11_9_1_1_2_2">&#167;11.9.1.1.2.2</a>), 20/eq (<a href="20-eq.html#SP41_3">&#167;41.3</a>), 22/cs (<a href="22-cs.html#SP10_6">&#167;10.6</a>), 25/cii (<a href="25-cii.html#SP3_5_7">&#167;3.5.7</a>).</p>
<p class="endnote">The function Phrases::TypeData::is_arithmetic_phrase is used in 14/ds2 (<a href="14-ds2.html#SP11_9_1_1_2">&#167;11.9.1.1.2</a>, <a href="14-ds2.html#SP11_9_1_1_3">&#167;11.9.1.1.3</a>).</p>
<p class="endnote">The function Phrases::TypeData::is_assignment_phrase is used in 14/ds2 (<a href="14-ds2.html#SP11_9_1_1_5">&#167;11.9.1.1.5</a>).</p>
<p class="endnote">The function Phrases::TypeData::only_in is used in 14/ds2 (<a href="14-ds2.html#SP11_9_1_1_9">&#167;11.9.1.1.9</a>).</p>
<p class="endnote">The function Phrases::TypeData::block_follows is used in 25/cii (<a href="25-cii.html#SP1">&#167;1</a>, <a href="25-cii.html#SP1_2_1">&#167;1.2.1</a>, <a href="25-cii.html#SP3_5_1_1">&#167;3.5.1.1</a>).</p>
<p class="inwebparagraph"><a id="SP28"></a><b>&#167;28. Return value polymorphism. </b>Inform has two sorts of polymorphism &mdash; that is, there are two ways in which
the kinds of phrases can vary. One is by means of kind variables, the other
is for arithmetic operations such as "plus" or "times": where the range of
kinds which can go in is quite large, and the kind which comes out is then
determined on dimensional grounds. (A number times a length is another
length, but a number plus a length is an error, and so on.)
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::return_decided_dimensionally</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;manner_of_return</span><span class="plain"> == </span><span class="constant">DECIDES_VALUE_MOR</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">phtd</span><span class="plain">-</span><span class="element">&gt;as_inline.arithmetical_operation</span><span class="plain"> &gt;= 0)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::return_decided_dimensionally is used in 14/rv (<a href="14-rv.html#SP23_7">&#167;23.7</a>).</p>
<p class="inwebparagraph"><a id="SP29"></a><b>&#167;29. Tweaking phrase ordering. </b>Phrases marked for use only within a particular control structure, such as
"otherwise" within "if", automatically precede all other phrases. The idea
is that these are keywords whose effect is so powerful that we don't want
any chance of ambiguities arising due to unwise phrase definitions in the
source text.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::TypeData::inline_type_data_comparison</span><span class="plain">(</span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd1</span><span class="plain">, </span><span class="reserved">ph_type_data</span><span class="plain"> *</span><span class="identifier">phtd2</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">phtd1</span><span class="plain">-</span><span class="element">&gt;as_inline.only_in_loop</span><span class="plain">) &amp;&amp; (</span><span class="identifier">phtd2</span><span class="plain">-</span><span class="element">&gt;as_inline.only_in_loop</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">BEFORE_PH</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">phtd2</span><span class="plain">-</span><span class="element">&gt;as_inline.only_in_loop</span><span class="plain">) &amp;&amp; (</span><span class="identifier">phtd1</span><span class="plain">-</span><span class="element">&gt;as_inline.only_in_loop</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">AFTER_PH</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">EQUAL_PH</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::TypeData::inline_type_data_comparison is used in <a href="#SP21_1">&#167;21.1</a>.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="22-prcd.html">Back to 'Phrase Runtime Context Data'</a></li><li><a href="22-dptd.html">Continue with 'Describing Phrase Type Data'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>