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-tp.html
2019-08-31 13:56:36 +01:00

432 lines
48 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>22/pav</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/tp' 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>To Phrases</b></li></ul><p class="purpose">To manage the sorting of To... phrases in logical precedence order, and keep track of which kinds they are being applied to.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP3">&#167;3. Logical priority of To phrases</a></li><li><a href="#SP6">&#167;6. Registering and compiling To phrases</a></li><li><a href="#SP7">&#167;7. Compilation requests</a></li><li><a href="#SP12">&#167;12. Phrase option parsing</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>"To" phrases are compiled only when they are needed, and they can be
compiled in variant forms depending on the kinds of their arguments; so
we use the following chits to keep track of what's outstanding:
</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">to_phrase_request</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">requested_phrase</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">requested_exact_kind</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_variables_interpretation</span><span class="plain">[27];</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">req_iname</span><span class="plain">;</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">to_phrase_request</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure to_phrase_request is accessed in 25/cp, 26/ts and here.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. Logical priority of To phrases. </b>"To" phrases are insertion-sorted, as they are defined, into a linked list
held in logical priority order. This essentially means that two lexically
indistinguishable phrases (e.g., "admire (OC - an open container)" and
"admire (C - a container)") are placed such that the more specific, in
type-checking terms, comes first (the open container case being the more
specific). The purpose of this list is to ensure that excerpt meanings
for phrase definitions are registered in logical priority order, because
the excerpt parser prefers earlier registrations to later ones in case
of ambiguity.
</p>
<p class="inwebparagraph">Note that the following sort algorithm affects only "to..." phrases,
and therefore has no effect on rule ordering within rulebooks.
</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>The system for deciding which of two phrases is logically prior, if
either is. This is not quite compatible with the other comparison routines
(for comparing action patterns, SPs, etc.) because it returns a wider
variety of values:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">BEFORE_PH</span><span class="plain"> -3</span>
<span class="definitionkeyword">define</span> <span class="constant">SUBSCHEMA_PH</span><span class="plain"> -1</span>
<span class="definitionkeyword">define</span> <span class="constant">EQUAL_PH</span><span class="plain"> 0</span>
<span class="definitionkeyword">define</span> <span class="constant">SUPERSCHEMA_PH</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">INCOMPARABLE_PH</span><span class="plain"> 2</span>
<span class="definitionkeyword">define</span> <span class="constant">AFTER_PH</span><span class="plain"> 3</span>
<span class="definitionkeyword">define</span> <span class="constant">CONFLICTED_PH</span><span class="plain"> 4</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Routines::ToPhrases::compare</span><span class="plain">(</span><span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph1</span><span class="plain">, </span><span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph2</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">Phrases::TypeData::comparison</span><span class="plain">(&amp;(</span><span class="identifier">ph1</span><span class="plain">-</span><span class="element">&gt;type_data</span><span class="plain">), &amp;(</span><span class="identifier">ph2</span><span class="plain">-</span><span class="element">&gt;type_data</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Log::aspect_switched_on</span><span class="plain">(</span><span class="constant">PHRASE_COMPARISONS_DA</span><span class="plain">)) || (</span><span class="identifier">r</span><span class="plain"> == </span><span class="constant">CONFLICTED_PH</span><span class="plain">)) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Phrase comparison ("</span><span class="plain">);</span>
<span class="functiontext">Phrases::write_HTML_representation</span><span class="plain">(</span><span class="identifier">DL</span><span class="plain">, </span><span class="identifier">ph1</span><span class="plain">, </span><span class="constant">PASTE_PHRASE_FORMAT</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">") "</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">r</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INCOMPARABLE_PH</span><span class="plain">: </span><span class="identifier">LOG</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">SUBSCHEMA_PH</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;="</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">SUPERSCHEMA_PH</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&gt;="</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">EQUAL_PH</span><span class="plain">: </span><span class="identifier">LOG</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">BEFORE_PH</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;"</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">AFTER_PH</span><span class="plain">: </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&gt;"</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">CONFLICTED_PH</span><span class="plain">: </span><span class="identifier">LOG</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="identifier">LOG</span><span class="plain">(</span><span class="string">" ("</span><span class="plain">);</span>
<span class="functiontext">Phrases::write_HTML_representation</span><span class="plain">(</span><span class="identifier">DL</span><span class="plain">, </span><span class="identifier">ph2</span><span class="plain">, </span><span class="constant">PASTE_PHRASE_FORMAT</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">")\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">r</span><span class="plain"> == </span><span class="constant">CONFLICTED_PH</span><span class="plain">) {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="functiontext">Phrases::declaration_node</span><span class="plain">(</span><span class="identifier">ph1</span><span class="plain">));</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(2, </span><span class="functiontext">Phrases::declaration_node</span><span class="plain">(</span><span class="identifier">ph2</span><span class="plain">));</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ConflictedReturnKinds</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The two phrase definitions %1 and %2 make the same wording "</span>
<span class="string">"produce two different kinds of value, which is not allowed."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">return</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 Routines::ToPhrases::compare is used in <a href="#SP5">&#167;5</a>.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>The following routine takes a phrase and makes it officially a To
phrase, which in particular means adding it to the list of To phrases in
logical order.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Routines::ToPhrases::new</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">phrase</span><span class="plain"> *</span><span class="identifier">previous_phrase</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">current_phrase</span><span class="plain"> = </span><span class="identifier">first_in_logical_order</span><span class="plain">;</span>
<span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;requests_package</span><span class="plain"> = </span><span class="functiontext">Hierarchy::package</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;owning_module</span><span class="plain">, </span><span class="constant">PHRASES_HAP</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">first_in_logical_order</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">first_in_logical_order</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="reserved">while</span><span class="plain"> ((</span><span class="identifier">current_phrase</span><span class="plain"> != </span><span class="identifier">NULL</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Routines::ToPhrases::compare</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">, </span><span class="identifier">current_phrase</span><span class="plain">) &gt;= 0)) {</span>
<span class="identifier">previous_phrase</span><span class="plain"> = </span><span class="identifier">current_phrase</span><span class="plain">;</span>
<span class="identifier">current_phrase</span><span class="plain"> = </span><span class="identifier">current_phrase</span><span class="plain">-</span><span class="element">&gt;next_in_logical_order</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">previous_phrase</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;next_in_logical_order</span><span class="plain"> = </span><span class="identifier">first_in_logical_order</span><span class="plain">;</span>
<span class="identifier">first_in_logical_order</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="plain">}</span>
<span class="identifier">previous_phrase</span><span class="plain">-</span><span class="element">&gt;next_in_logical_order</span><span class="plain"> = </span><span class="identifier">ph</span><span class="plain">;</span>
<span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;next_in_logical_order</span><span class="plain"> = </span><span class="identifier">current_phrase</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Routines::ToPhrases::new is used in 22/ph (<a href="22-ph.html#SP6_7">&#167;6.7</a>).</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Registering and compiling To phrases. </b>These are the only places where the logical precedence list is directly used,
but registration of the excerpts in precedence order ensures that this
ordering has a profound effect on expression parsing throughout Inform.
</p>
<p class="inwebparagraph">Compilation in precedence order is by contrast done for purely cosmetic
reasons, that is, to make the compiled code more legible.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Routines::ToPhrases::register_all</span><span class="plain">(</span><span class="reserved">void</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">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = 0;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">ph</span><span class="plain"> = </span><span class="identifier">first_in_logical_order</span><span class="plain">; </span><span class="identifier">ph</span><span class="plain">; </span><span class="identifier">ph</span><span class="plain"> = </span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;next_in_logical_order</span><span class="plain">) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;declaration_node</span><span class="plain">;</span>
<span class="functiontext">Phrases::Parser::register_excerpt</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">);</span>
<span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;sequence_count</span><span class="plain"> = </span><span class="identifier">c</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">Routines::ToPhrases::sequence_count</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="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> 0;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;sequence_count</span><span class="plain"> == -1) {</span>
<span class="functiontext">Phrases::log</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Sequence count not ready"</span><span class="plain">);</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;sequence_count</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Routines::ToPhrases::register_all is used in 22/cs (<a href="22-cs.html#SP5">&#167;5</a>).</p>
<p class="endnote">The function Routines::ToPhrases::sequence_count is used in 25/in (<a href="25-in.html#SP10">&#167;10</a>, <a href="25-in.html#SP27">&#167;27</a>).</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Compilation requests. </b>Here's how a request is made. The kind supplied should be that which the phrase
has in this version: for example, given the definition
</p>
<blockquote>
<p>To judge (V - a value) against (W - a value): ...</p>
</blockquote>
<p class="inwebparagraph">the invocation
</p>
<p class="inwebparagraph"> judge 2 against "two";
</p>
<p class="inwebparagraph">would result in a call to this routine where K was set to:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">phrase (number, text) -&gt; nothing</span>
</pre>
<p class="inwebparagraph">If the kind involves variables, the caller must also supply the current
values in force, so that there is no possible ambiguity in how we read K.
</p>
<pre class="display">
<span class="reserved">to_phrase_request</span><span class="plain"> *</span><span class="functiontext">Routines::ToPhrases::make_request</span><span class="plain">(</span><span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">,</span>
<span class="identifier">kind_variable_declaration</span><span class="plain"> *</span><span class="identifier">kvd</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ph</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad request"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">nr</span><span class="plain"> = 0;</span>
<span class="reserved">to_phrase_request</span><span class="plain"> *</span><span class="identifier">req</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">req</span><span class="plain">, </span><span class="reserved">to_phrase_request</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="identifier">req</span><span class="plain">-</span><span class="element">&gt;requested_phrase</span><span class="plain">) {</span>
<span class="identifier">nr</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">K</span><span class="plain">, </span><span class="identifier">req</span><span class="plain">-</span><span class="element">&gt;requested_exact_kind</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">req</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Behaviour::semidefinite</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Issue a problem message for undetermined kinds</span> <span class="cwebmacronumber">7.1</span>&gt;<span class="plain">;</span>
<span class="identifier">req</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">to_phrase_request</span><span class="plain">);</span>
<span class="identifier">req</span><span class="plain">-</span><span class="element">&gt;requested_exact_kind</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">;</span>
<span class="identifier">req</span><span class="plain">-</span><span class="element">&gt;requested_phrase</span><span class="plain"> = </span><span class="identifier">ph</span><span class="plain">;</span>
<span class="identifier">compilation_module</span><span class="plain"> *</span><span class="identifier">cm</span><span class="plain"> = </span><span class="functiontext">Modules::current</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;declaration_node</span><span class="plain">) </span><span class="identifier">cm</span><span class="plain"> = </span><span class="functiontext">Modules::find</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;declaration_node</span><span class="plain">);</span>
<span class="identifier">package_request</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Hierarchy::package_within</span><span class="plain">(</span><span class="constant">REQUESTS_HAP</span><span class="plain">, </span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;requests_package</span><span class="plain">);</span>
<span class="identifier">req</span><span class="plain">-</span><span class="element">&gt;req_iname</span><span class="plain"> = </span><span class="functiontext">Hierarchy::make_localised_iname_in</span><span class="plain">(</span><span class="constant">PHRASE_FN_HL</span><span class="plain">, </span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">cm</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;27; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">req</span><span class="plain">-</span><span class="element">&gt;kind_variables_interpretation</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (; </span><span class="identifier">kvd</span><span class="plain">; </span><span class="identifier">kvd</span><span class="plain">=</span><span class="identifier">kvd</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">)</span>
<span class="identifier">req</span><span class="plain">-</span><span class="element">&gt;kind_variables_interpretation</span><span class="plain">[</span><span class="identifier">kvd</span><span class="plain">-&gt;</span><span class="identifier">kv_number</span><span class="plain">] = </span><span class="identifier">kvd</span><span class="plain">-&gt;</span><span class="identifier">kv_value</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">req</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Routines::ToPhrases::make_request is used in <a href="#SP8">&#167;8</a>, 22/cs (<a href="22-cs.html#SP10_5">&#167;10.5</a>), 22/pav (<a href="22-pav.html#SP7">&#167;7</a>), 25/ciac (<a href="25-ciac.html#SP1">&#167;1</a>).</p>
<p class="inwebparagraph"><a id="SP7_1"></a><b>&#167;7.1. </b>It's quite hard to get this, but if you supply the empty list written as
a constant to a phrase which uses a kind variable in the form "list of K",
then K would have be just "value", since Inform doesn't know what the empty
list is a list of. The result would be:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem message for undetermined kinds</span> <span class="cwebmacronumber">7.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="functiontext">Phrases::declaration_node</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">));</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_UndeterminedKind</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::empty</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The phrase %1 needs to be used in such a way that I know "</span>
<span class="string">"what kinds of values go into it."</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">Problems::quote_wording_as_source</span><span class="plain">(2, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The phrase %1 needs to be used in such a way that I know "</span>
<span class="string">"what kinds of values go into it; so I'm not sure how to "</span>
<span class="string">"make sense of it from %2."</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>The following puts together an I6 identifier for a phrase, and also handles
the case of an inline definition which happens to consist of a call to an
I6 routine.
</p>
<pre class="display">
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="functiontext">Routines::ToPhrases::make_iname</span><span class="plain">(</span><span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">req_kind</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Phrases::TypeData::invoked_inline</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">)) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">identifier</span><span class="plain">);</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="functiontext">Phrases::get_inline_definition</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">found</span><span class="plain"> = </span><span class="identifier">FALSE</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">p</span><span class="plain">[</span><span class="identifier">i</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">Characters::isalpha</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain"> = 0;</span>
<span class="reserved">while</span><span class="plain"> (((</span><span class="identifier">Characters::isalpha</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])) || (</span><span class="identifier">Characters::isdigit</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])) || (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == </span><span class="character">'_'</span><span class="plain">)) &amp;&amp; (</span><span class="identifier">j</span><span class="plain">++ &lt; 31))</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">identifier</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++]);</span>
<span class="identifier">found</span><span class="plain"> = </span><span class="identifier">TRUE</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">found</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="functiontext">Phrases::declaration_node</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_phrase</span><span class="plain">(2, </span><span class="identifier">ph</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_PhraseNamedI6Failed</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, defining the phrase '%2' with a piece of Inform 6 "</span>
<span class="string">"code, but also giving it a name as a function to be used in an "</span>
<span class="string">"equation, or in some functional programming context. That's only "</span>
<span class="string">"allowed if the I6 definition consists simply of a call to an "</span>
<span class="string">"I6 function - and this doesn't, so far as I can see."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">identifier</span><span class="plain">, </span><span class="string">"ErrorRecoverySymbol"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">symb</span><span class="plain"> = </span><span class="identifier">Produce::find_by_name</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">identifier</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">identifier</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">symb</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">to_phrase_request</span><span class="plain"> *</span><span class="identifier">req</span><span class="plain"> = </span><span class="functiontext">Routines::ToPhrases::make_request</span><span class="plain">(</span>
<span class="identifier">ph</span><span class="plain">, </span><span class="identifier">req_kind</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">EMPTY_WORDING</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Routines::Compile::iname</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">, </span><span class="identifier">req</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Routines::ToPhrases::make_iname is used in 20/eq (<a href="20-eq.html#SP48">&#167;48</a>), 22/pav (<a href="22-pav.html#SP8_1">&#167;8.1</a>).</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>The following coroutine compiles any pending requests for phrase compilation
since the last time it was called.
</p>
<pre class="display">
<span class="reserved">to_phrase_request</span><span class="plain"> *</span><span class="identifier">latest_request_granted</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Routines::ToPhrases::compilation_coroutine</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">int</span><span class="plain"> </span><span class="identifier">max_i</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = 0;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">TRUE</span><span class="plain">) {</span>
<span class="reserved">to_phrase_request</span><span class="plain"> *</span><span class="identifier">req</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">latest_request_granted</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">req</span><span class="plain"> = </span><span class="identifier">FIRST_OBJECT</span><span class="plain">(</span><span class="reserved">to_phrase_request</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">req</span><span class="plain"> = </span><span class="identifier">NEXT_OBJECT</span><span class="plain">(</span><span class="identifier">latest_request_granted</span><span class="plain">, </span><span class="reserved">to_phrase_request</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">req</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">latest_request_granted</span><span class="plain"> = </span><span class="identifier">req</span><span class="plain">;</span>
<span class="functiontext">Phrases::compile</span><span class="plain">(</span><span class="identifier">latest_request_granted</span><span class="plain">-</span><span class="element">&gt;requested_phrase</span><span class="plain">,</span>
<span class="identifier">i</span><span class="plain">, </span><span class="identifier">max_i</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">latest_request_granted</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">N</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Routines::ToPhrases::compilation_coroutine is used in 22/cs (<a href="22-cs.html#SP14">&#167;14</a>).</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>In the course of doing this, <code class="display"><span class="extract">Phrases::compile</span></code> calls us back to ask us
to write a comment about this:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Routines::ToPhrases::comment_on_request</span><span class="plain">(</span><span class="reserved">to_phrase_request</span><span class="plain"> *</span><span class="identifier">req</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">req</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">Produce::comment</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">I</span><span class="string">"No specific request"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="string">"Request %d: "</span><span class="plain">, </span><span class="identifier">req</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Kinds::Textual::write</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="identifier">req</span><span class="plain">-</span><span class="element">&gt;requested_exact_kind</span><span class="plain">);</span>
<span class="identifier">Produce::comment</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">C</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Routines::ToPhrases::comment_on_request is used in 25/cp (<a href="25-cp.html#SP3_1">&#167;3.1</a>).</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>It also needs access to:
</p>
<pre class="display">
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">Routines::ToPhrases::kind_of_request</span><span class="plain">(</span><span class="reserved">to_phrase_request</span><span class="plain"> *</span><span class="identifier">req</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">req</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"null request"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">req</span><span class="plain">-</span><span class="element">&gt;requested_exact_kind</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">kind</span><span class="plain"> **</span><span class="functiontext">Routines::ToPhrases::kind_variables_for_request</span><span class="plain">(</span><span class="reserved">to_phrase_request</span><span class="plain"> *</span><span class="identifier">req</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">req</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"null request"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">req</span><span class="plain">-</span><span class="element">&gt;kind_variables_interpretation</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Routines::ToPhrases::kind_of_request is used in 25/cp (<a href="25-cp.html#SP3_2">&#167;3.2</a>).</p>
<p class="endnote">The function Routines::ToPhrases::kind_variables_for_request is used in 25/cp (<a href="25-cp.html#SP3_2">&#167;3.2</a>).</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. Phrase option parsing. </b>These indirections are provided so that the implementation of phrase options
is confined to the current Chapter.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Routines::ToPhrases::allows_options</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="functiontext">Phrases::Options::allows_options</span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;options_data</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">phrase</span><span class="plain"> *</span><span class="functiontext">Routines::ToPhrases::meaning_as_phrase</span><span class="plain">(</span><span class="identifier">excerpt_meaning</span><span class="plain"> *</span><span class="identifier">em</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">em</span><span class="plain"> == </span><span class="identifier">NULL</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="reserved">return</span><span class="plain"> </span><span class="identifier">RETRIEVE_POINTER_phrase</span><span class="plain">(</span><span class="identifier">em</span><span class="plain">-&gt;</span><span class="identifier">data</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Routines::ToPhrases::parse_phrase_option_used</span><span class="plain">(</span><span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Phrases::Options::parse</span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;options_data</span><span class="plain">), </span><span class="identifier">W</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Routines::ToPhrases::allows_options appears nowhere else.</p>
<p class="endnote">The function Routines::ToPhrases::meaning_as_phrase appears nowhere else.</p>
<p class="endnote">The function Routines::ToPhrases::parse_phrase_option_used is used in 10/cap (<a href="10-cap.html#SP6">&#167;6</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="22-pav.html">Back to 'Phrases as Values'</a></li><li><a href="22-tp2.html">Continue with 'Timed Phrases'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>