1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 16:44:21 +03:00
inform7/docs/core-module/22-cs.html
2020-04-07 01:06:09 +01:00

740 lines
60 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>22/itp</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../compiler.html"><b>compiler tools</b></a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul>
<h2>Compiler Webs</h2>
<ul>
<li><a href="../inbuild/index.html">inbuild</a></li>
<li><a href="../inform7/index.html">inform7</a></li>
<li><a href="../inter/index.html">inter</a></li>
</ul>
<h2>Inbuild Modules</h2>
<ul>
<li><a href="../inbuild-module/index.html">inbuild</a></li>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../syntax-module/index.html">syntax</a></li>
<li><a href="../html-module/index.html">html</a></li>
</ul>
<h2>Inform7 Modules</h2>
<ul>
<li><a href="../core-module/index.html">core</a></li>
<li><a href="../problems-module/index.html">problems</a></li>
<li><a href="../inflections-module/index.html">inflections</a></li>
<li><a href="../linguistics-module/index.html">linguistics</a></li>
<li><a href="../kinds-module/index.html">kinds</a></li>
<li><a href="../if-module/index.html">if</a></li>
<li><a href="../multimedia-module/index.html">multimedia</a></li>
<li><a href="../index-module/index.html">index</a></li>
</ul>
<h2>Inter Modules</h2>
<ul>
<li><a href="../inter-module/index.html">inter</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../codegen-module/index.html">codegen</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '22/cs' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="../compiler.html">Compiler Modules</a></li><li><a href="index.html">core</a></li><li><a href="index.html#22">Chapter 22: Phrases</a></li><li><b>Construction Sequence</b></li></ul><p class="purpose">To deal with all the |.i6t| interpreted commands which bring about the compilation of phrases, and to ensure that they are used in the correct order.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. A day in the life</a></li><li><a href="#SP2">&#167;2. Early morning</a></li><li><a href="#SP3">&#167;3. Mid-morning</a></li><li><a href="#SP4">&#167;4. Late morning</a></li><li><a href="#SP5">&#167;5. Just before noon</a></li><li><a href="#SP6">&#167;6. Noon</a></li><li><a href="#SP7">&#167;7. Early afternoon</a></li><li><a href="#SP10">&#167;10. Mid-afternoon</a></li><li><a href="#SP11">&#167;11. Late Afternoon</a></li><li><a href="#SP14">&#167;14. Evening</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. A day in the life. </b>Suppose we compare the run of Inform to a single day. At dawn the program
starts up. In the morning it finds out the names of all the constant values
defined in the source text: names like "Mrs Blenkinsop", "hatstand", and
so on. By noon it has also found out the wording used for phrases, such as
"award prize (N - a number) to (gardener - a woman)". This means that in
the afternoon it knows every name it ever will, and so it can work through
the definitions of phrases like "award prize...". In the evening, it does
some book-keeping, and at nightfall it shuts down.
</p>
<p class="inwebparagraph">We will use the story of our single day throughout this section on timing,
because everything has to happen in just the right order.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">DAWN_PHT</span><span class="plain"> </span><span class="constant">0</span>
<span class="definitionkeyword">define</span> <span class="constant">EARLY_MORNING_PHT</span><span class="plain"> </span><span class="constant">1</span>
<span class="definitionkeyword">define</span> <span class="constant">LATE_MORNING_PHT</span><span class="plain"> </span><span class="constant">2</span>
<span class="definitionkeyword">define</span> <span class="constant">PRE_NOON_PHT</span><span class="plain"> </span><span class="constant">3</span>
<span class="definitionkeyword">define</span> <span class="constant">EARLY_AFTERNOON_PHT</span><span class="plain"> </span><span class="constant">4</span>
<span class="definitionkeyword">define</span> <span class="constant">MID_AFTERNOON_PHT</span><span class="plain"> </span><span class="constant">5</span>
<span class="definitionkeyword">define</span> <span class="constant">LATE_AFTERNOON_PHT</span><span class="plain"> </span><span class="constant">6</span>
<span class="definitionkeyword">define</span> <span class="constant">EVENING_PHT</span><span class="plain"> </span><span class="constant">7</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">phrase_time_now</span><span class="plain"> = </span><span class="constant">DAWN_PHT</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::advance_phrase_time_to</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">advance_to</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">advance_to</span><span class="plain"> &lt; </span><span class="identifier">phrase_time_now</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Advance from %d to %d\n"</span><span class="plain">, </span><span class="identifier">phrase_time_now</span><span class="plain">, </span><span class="identifier">advance_to</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span>
<span class="string">"The necessary phrase construction events are out of sequence"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">phrase_time_now</span><span class="plain"> = </span><span class="identifier">advance_to</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Manager::advance_phrase_time_to is used in <a href="#SP2">&#167;2</a>, <a href="#SP4">&#167;4</a>, <a href="#SP5">&#167;5</a>, <a href="#SP7">&#167;7</a>, <a href="#SP8">&#167;8</a>, <a href="#SP9">&#167;9</a>, <a href="#SP10">&#167;10</a>, <a href="#SP11">&#167;11</a>, <a href="#SP12">&#167;12</a>, <a href="#SP13">&#167;13</a>, <a href="#SP14">&#167;14</a>.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. Early morning. </b>We run through the phrase preambles to look for named rules like this:
</p>
<blockquote>
<p>Instead of pushing the red button (this is the fire alarm rule): ...</p>
</blockquote>
<p class="inwebparagraph">This looking-for-names is done by parsing the preamble text to a PHUD in
what is called "coarse mode", which can only get an approximate idea at
best: at this stage the "Instead" rulebook and the "red button" don't
exist, so most of the words here are meaningless. The PHUD which coarse
mode parsing produces is far too sketchy to use, and is thrown away.
But at least it does pick out the name "fire alarm rule", and Inform
creates an empty "rule" structure called this, registering this as the
name of a new constant.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::traverse_for_names</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Phrases::Manager::advance_phrase_time_to</span><span class="plain">(</span><span class="constant">EARLY_MORNING_PHT</span><span class="plain">);</span>
<span class="identifier">ParseTree::traverse</span><span class="plain">(</span><span class="functiontext">Task::syntax_tree</span><span class="plain">(), </span><span class="functiontext">Phrases::Manager::visit_for_names</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::visit_for_names</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) == </span><span class="identifier">ROUTINE_NT</span><span class="plain">)</span>
<span class="functiontext">Phrases::Usage::predeclare_name_in</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Manager::traverse_for_names is used in 1/htc (<a href="1-htc.html#SP2_3">&#167;2.3</a>).</p>
<p class="endnote">The function Phrases::Manager::visit_for_names appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. Mid-morning. </b>This is when Inform is making its main traverses through assertions.
Something very useful is happening, but it's happening somewhere else.
Assertions such as
</p>
<blockquote>
<p>Instead is a rulebook.</p>
</blockquote>
<p class="inwebparagraph">are being read, and rulebooks are therefore being created.
</p>
<p class="inwebparagraph">We do nothing at all. We see nodes in the parse tree for phrase definitions,
but we let them go by. The <code class="display"><span class="extract">NULL</span></code>s in these two definitions tell Inform not
to do anything when the assertion traverse reaches nodes of these types:
</p>
<pre class="display">
<span class="reserved">sentence_handler</span><span class="plain"> </span><span class="identifier">COMMAND_SH_handler</span><span class="plain"> = { </span><span class="identifier">INVOCATION_LIST_NT</span><span class="plain">, -1, </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain"> };</span>
<span class="reserved">sentence_handler</span><span class="plain"> </span><span class="identifier">ROUTINE_SH_handler</span><span class="plain"> = { </span><span class="identifier">ROUTINE_NT</span><span class="plain">, -1, </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain"> };</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Late morning. </b>With the assertions read, all the values have their names, and that means
we can go back to phrases like:
</p>
<blockquote>
<p>Instead of pushing the red button (this is the fire alarm rule): ...</p>
</blockquote>
<p class="inwebparagraph">and read them properly. So Inform now runs through the preambles again and
parses them for a second time to PHUDs, but this time in "fine mode" rather
than "coarse mode", and this time the result is not thrown away. If the
phrase is a "To..." phrase declaration, then the PHUD is pretty sketchy and
we parse more substantial PHTD and PHOD structures to accompany it. But if
it is a rule, the PHUD contains a great deal of useful information, and we
accompany it with essentially blank PHTD and PHOD structures. Either way, we
end up with a triplet of PHUD, PHTD and PHOD, and these are combined into a
new <code class="display"><span class="extract">phrase</span></code> structure. The PHSF structure is initially created as a
function of the PHTD: for example, if the phrase reads
</p>
<blockquote>
<p>To award (points - a number): ...</p>
</blockquote>
<p class="inwebparagraph">then the PHTD notes that "points" is the name of a parameter whose kind is
to be "number". The stack frame, PHSF, deduces that "points" will be a
local variable of kind "number" within the phrase when it's running.
Lastly, a blank PHRCD structure is created, filling out the set of five
substructures.
</p>
<p class="inwebparagraph">As they are created, the "To..." phrases are insertion-sorted into a list of
phrases in logical precedence order. This can be done now because it relies
only on the kinds listed in the PHTD, all of which have existed since
mid-morning.
</p>
<p class="inwebparagraph">For reasons discussed below, rules are not yet sorted. But the names created
in mid-morning, such as "fire alarm rule", are associated with their
phrases, and they are marked for what's called "automatic placement". For
example, the fire alarm rule will automatically be placed into the Instead
rulebook, because its preamble begins "Instead". The reason rules are only
marked to be placed later is that placement has to occur in logical
precedence order, but rules are harder to sort than phrases. They have to be
sorted by their PHRCDs, not their PHTDs, and a PHRCD cannot even be parsed
until afternoon because the conditions for a rule often mention phrases &mdash;
for instance, "Instead of waiting when in darkness", making use of an "in
darkness" phrase. So for now we just make a mental note to do automatic
placement later on.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::traverse</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Phrases::Manager::advance_phrase_time_to</span><span class="plain">(</span><span class="constant">LATE_MORNING_PHT</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">progress_target</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">progress_made</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">ParseTree::traverse_int</span><span class="plain">(</span><span class="functiontext">Task::syntax_tree</span><span class="plain">(), </span><span class="functiontext">Phrases::Manager::visit_to_count</span><span class="plain">, &amp;</span><span class="identifier">progress_target</span><span class="plain">);</span>
<span class="identifier">ParseTree::traverse_int_int</span><span class="plain">(</span><span class="functiontext">Task::syntax_tree</span><span class="plain">(), </span><span class="functiontext">Phrases::Manager::visit_to_create</span><span class="plain">, &amp;</span><span class="identifier">progress_target</span><span class="plain">, &amp;</span><span class="identifier">progress_made</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::visit_to_count</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">progress_target</span><span class="plain">) {</span>
<span class="plain">(*</span><span class="identifier">progress_target</span><span class="plain">)++;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::visit_to_create</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">progress_target</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">progress_made</span><span class="plain">) {</span>
<span class="plain">(*</span><span class="identifier">progress_made</span><span class="plain">)++;</span>
<span class="reserved">if</span><span class="plain"> ((*</span><span class="identifier">progress_made</span><span class="plain">) % </span><span class="constant">10</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)</span>
<span class="functiontext">ProgressBar::update</span><span class="plain">(3,</span>
<span class="plain">((</span><span class="reserved">float</span><span class="plain">) (*</span><span class="identifier">progress_made</span><span class="plain">))/((</span><span class="reserved">float</span><span class="plain">) (*</span><span class="identifier">progress_target</span><span class="plain">)));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) == </span><span class="identifier">ROUTINE_NT</span><span class="plain">) {</span>
<span class="functiontext">Phrases::create_from_preamble</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Manager::traverse is used in 1/htc (<a href="1-htc.html#SP2_7">&#167;2.7</a>).</p>
<p class="endnote">The function Phrases::Manager::visit_to_count appears nowhere else.</p>
<p class="endnote">The function Phrases::Manager::visit_to_create appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Just before noon. </b>It is now nearly noon, and things appear to be a little untidy. Why
are the "To..." phrases not yet registered with the excerpt parser?
The answer is that we needed to wait until all of the "To..." phrases
had been created as structures before we could safely proceed. The first
phrase couldn't be registered until we knew the complete logical order
of them all. Well: at last, we do know that, and can make the registration.
Phrases are the very last things to get their names in Inform (well, not
counting local variables, whose names only exist fleetingly).
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::register_meanings</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Phrases::Manager::advance_phrase_time_to</span><span class="plain">(</span><span class="constant">PRE_NOON_PHT</span><span class="plain">);</span>
<span class="functiontext">Routines::ToPhrases::register_all</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Manager::register_meanings is used in 1/htc (<a href="1-htc.html#SP2_7">&#167;2.7</a>).</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Noon. </b>When the final phrase is registered, the hour chimes. From this point
onwards, there's no longer any text which can't be parsed because some
of the names don't exist yet: everything exists.
</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Early afternoon. </b>In the afternoon, we begin by binding up the rulebooks. First, we go through
the phrases destined to be rules, and for each we translate the PHUD (which
contains mainly textual representations of the usage information, e.g.
"taking something (called the thingummy) which is in a lighted room during
Scene Two when the marble slab is open") to a PHRCD (which contains fully
parsed Inform data structures, e.g., an action pattern and a pointer to a
<code class="display"><span class="extract">scene</span></code> structure). As noted above, this often means parsing conditions
which involve phrases, and that's why we're doing it in the afternoon.
</p>
<p class="inwebparagraph">During this PHUD-to-PHRCD parsing process, we make sure that the relevant
phrase's PHSF is the current stack frame, because it's here that the names
of any callings (e.g. "thingummy") are created as local variables to be
valid throughout the phrase.
</p>
<p class="inwebparagraph">Once we're done with this, the PHUD will never be used again.
</p>
<p class="inwebparagraph">Note that the PHRCDs have to be parsed in source text appearance order (the
order which <code class="display"><span class="extract">LOOP_OVER</span></code> follows) so that the back reference "doing it" can
correctly refer to the most recently mentioned action.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::parse_rule_parameters</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Phrases::Manager::advance_phrase_time_to</span><span class="plain">(</span><span class="constant">EARLY_AFTERNOON_PHT</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">LOOP_OVER</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">current_sentence</span><span class="plain"> = </span><span class="identifier">ph</span><span class="plain">-&gt;</span><span class="element">declaration_node</span><span class="plain">;</span>
<span class="functiontext">Frames::make_current</span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-&gt;</span><span class="element">stack_frame</span><span class="plain">));</span>
<span class="identifier">ph</span><span class="plain">-&gt;</span><span class="element">runtime_context_data</span><span class="plain"> =</span>
<span class="functiontext">Phrases::Usage::to_runtime_context_data</span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-&gt;</span><span class="element">usage_data</span><span class="plain">));</span>
<span class="functiontext">Frames::remove_current</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Manager::parse_rule_parameters is used in 1/htc (<a href="1-htc.html#SP2_7">&#167;2.7</a>).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>We can finally make the automatic placements of rules into rulebooks: so
our "fire alarm rule" will at last be placed in the "Instead" rulebook. The
PHRCDs are used to make sure it appears in the right position.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::add_rules_to_rulebooks</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Phrases::Manager::advance_phrase_time_to</span><span class="plain">(</span><span class="constant">EARLY_AFTERNOON_PHT</span><span class="plain">);</span>
<span class="functiontext">Rules::Bookings::make_automatic_placements</span><span class="plain">();</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">iname</span><span class="plain"> = </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">NUMBER_RULEBOOKS_CREATED_HL</span><span class="plain">);</span>
<span class="functiontext">Emit::named_numeric_constant</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">NUMBER_CREATED</span><span class="plain">(</span><span class="reserved">rulebook</span><span class="plain">));</span>
<span class="functiontext">Hierarchy::make_available</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">iname</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Manager::add_rules_to_rulebooks is used in 1/htc (<a href="1-htc.html#SP2_7">&#167;2.7</a>).</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>It might seem as if the rulebooks are now complete, but this is not true,
because we still have to take care of manual placements like:
</p>
<blockquote>
<p>The fire alarm rule is listed in the safety procedures rulebook.</p>
</blockquote>
<p class="inwebparagraph">This is where we get on with that, traversing the parse tree for sentences
of this general sort. Rules can also be unlisted, or constrained to happen
only conditionally, or substituted by other rules.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::parse_rule_placements</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Phrases::Manager::advance_phrase_time_to</span><span class="plain">(</span><span class="constant">EARLY_AFTERNOON_PHT</span><span class="plain">);</span>
<span class="identifier">ParseTree::traverse</span><span class="plain">(</span><span class="functiontext">Task::syntax_tree</span><span class="plain">(), </span><span class="functiontext">Phrases::Manager::visit_to_parse_placements</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::visit_to_parse_placements</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) == </span><span class="identifier">SENTENCE_NT</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">) == </span><span class="identifier">AVERB_NT</span><span class="plain">)) {</span>
<span class="identifier">prevailing_mood</span><span class="plain"> =</span>
<span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">verbal_certainty_ANNOT</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="identifier">down</span><span class="plain">, </span><span class="constant">verb_id_ANNOT</span><span class="plain">) == </span><span class="constant">SPECIAL_MEANING_VB</span><span class="plain">)</span>
<span class="functiontext">Assertions::Traverse::try_special_meaning</span><span class="plain">(</span><span class="constant">TRAVERSE_FOR_RULE_FILING_SMFT</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Manager::parse_rule_placements is used in 1/htc (<a href="1-htc.html#SP2_7">&#167;2.7</a>).</p>
<p class="endnote">The function Phrases::Manager::visit_to_parse_placements appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. Mid-afternoon. </b>It is now mid-afternoon, and the rulebooks are complete. It is time to
compile the I6 routines which will provide the run-time definitions of all
these phrases. This will be a long task, and much of it will be left until
the evening. But we do get rid of some easy cases now: the rules and
adjective definitions.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">total_phrases_to_compile</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">total_phrases_compiled</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::compile_first_block</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Phrases::Manager::advance_phrase_time_to</span><span class="plain">(</span><span class="constant">MID_AFTERNOON_PHT</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Count up the scale of the task</span> <span class="cwebmacronumber">10.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compile definitions of rules in rulebooks</span> <span class="cwebmacronumber">10.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compile definitions of rules left out of rulebooks</span> <span class="cwebmacronumber">10.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compile phrases which define adjectives</span> <span class="cwebmacronumber">10.4</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Mark To... phrases which have definite kinds for future compilation</span> <span class="cwebmacronumber">10.5</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Throw problems for phrases with return kinds too vaguely defined</span> <span class="cwebmacronumber">10.6</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Throw problems for inline phrases named as constants</span> <span class="cwebmacronumber">10.7</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Manager::compile_first_block is used in 1/htc (<a href="1-htc.html#SP2_8">&#167;2.8</a>).</p>
<p class="inwebparagraph"><a id="SP10_1"></a><b>&#167;10.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Count up the scale of the task</span> <span class="cwebmacronumber">10.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">total_phrases_compiled</span><span class="plain"> = </span><span class="constant">0</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">LOOP_OVER</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="reserved">if</span><span class="plain"> (</span><span class="identifier">ph</span><span class="plain">-&gt;</span><span class="element">at_least_one_compiled_form_needed</span><span class="plain">)</span>
<span class="identifier">total_phrases_to_compile</span><span class="plain">++;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_2"></a><b>&#167;10.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Compile definitions of rules in rulebooks</span> <span class="cwebmacronumber">10.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">rulebook</span><span class="plain"> *</span><span class="identifier">rb</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">rb</span><span class="plain">, </span><span class="reserved">rulebook</span><span class="plain">)</span>
<span class="functiontext">Rulebooks::compile_rule_phrases</span><span class="plain">(</span><span class="identifier">rb</span><span class="plain">,</span>
<span class="plain">&amp;</span><span class="identifier">total_phrases_compiled</span><span class="plain">, </span><span class="identifier">total_phrases_to_compile</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_3"></a><b>&#167;10.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Compile definitions of rules left out of rulebooks</span> <span class="cwebmacronumber">10.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">rule</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="reserved">rule</span><span class="plain">)</span>
<span class="functiontext">Rules::compile_definition</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">,</span>
<span class="plain">&amp;</span><span class="identifier">total_phrases_compiled</span><span class="plain">, </span><span class="identifier">total_phrases_to_compile</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_4"></a><b>&#167;10.4. </b>This doesn't compile all adjective definitions, only the ones which supply
a whole multi-step phrase to define them &mdash; a relatively little-used feature
of Inform.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile phrases which define adjectives</span> <span class="cwebmacronumber">10.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</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="reserved">if</span><span class="plain"> (</span><span class="functiontext">Phrases::Usage::get_effect</span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-&gt;</span><span class="element">usage_data</span><span class="plain">)) ==</span>
<span class="constant">DEFINITIONAL_PHRASE_EFF</span><span class="plain">)</span>
<span class="functiontext">Phrases::compile</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">, &amp;</span><span class="identifier">total_phrases_compiled</span><span class="plain">,</span>
<span class="identifier">total_phrases_to_compile</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="functiontext">Adjectives::Meanings::compile_support_code</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_5"></a><b>&#167;10.5. </b>As we'll see, it's legal in Inform to define "To..." phrases with vague
kinds: "To expose (X - a value)", for example. This can't be compiled as
vaguely as the definition implies, since there would be no way to know how
to store X. Instead, for each different kind of X which is actually needed,
a fresh version of the phrase is compiled &mdash; one where X is a number, one
where it's a text, and so on. This is handled by making a "request" for the
phrase, indicating that a compiled version of it will be needed.
</p>
<p class="inwebparagraph">Since "To..." phrases are only compiled on request, we must remember to
request the boring ones with straightforward kinds ("To award (N - a number)
points", say). This is where we do it:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Mark To... phrases which have definite kinds for future compilation</span> <span class="cwebmacronumber">10.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</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">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Phrases::TypeData::kind</span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-&gt;</span><span class="element">type_data</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Behaviour::definite</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ph</span><span class="plain">-&gt;</span><span class="element">at_least_one_compiled_form_needed</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">K</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="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_6"></a><b>&#167;10.6. </b><code class="display">
&lt;<span class="cwebmacrodefn">Throw problems for phrases with return kinds too vaguely defined</span> <span class="cwebmacronumber">10.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</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">kind</span><span class="plain"> *</span><span class="identifier">KR</span><span class="plain"> = </span><span class="functiontext">Phrases::TypeData::get_return_kind</span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-&gt;</span><span class="element">type_data</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">KR</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &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">) == -1)) {</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="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ReturnKindVague</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The declaration %1 tries to set up a phrase which decides a "</span>
<span class="string">"value which is too vaguely described. For example, 'To decide "</span>
<span class="string">"which number is the target: ...' is fine, because 'number' "</span>
<span class="string">"is clear about what kind of value should emerge; but 'To "</span>
<span class="string">"decide which value is the target: ...' is not clear enough."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain">=1; </span><span class="identifier">k</span><span class="plain">&lt;=26; </span><span class="identifier">k</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">KR</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Phrases::TypeData::tokens_contain_variable</span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-&gt;</span><span class="element">type_data</span><span class="plain">), </span><span class="identifier">k</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="identifier">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">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">var_letter</span><span class="plain">);</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">var_letter</span><span class="plain">, </span><span class="character">'A'</span><span class="plain">+</span><span class="identifier">k</span><span class="plain">-1);</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_stream</span><span class="plain">(2, </span><span class="identifier">var_letter</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ReturnKindUndetermined</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The declaration %1 tries to set up a phrase which decides a "</span>
<span class="string">"value which is too vaguely described, because it involves "</span>
<span class="string">"a kind variable (%2) which it can't determine through "</span>
<span class="string">"usage."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">var_letter</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="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_7"></a><b>&#167;10.7. </b><code class="display">
&lt;<span class="cwebmacrodefn">Throw problems for inline phrases named as constants</span> <span class="cwebmacronumber">10.7</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</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="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">)) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Phrases::Usage::has_name_as_constant</span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-&gt;</span><span class="element">usage_data</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="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_NamedInline</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The declaration %1 tries to give a name to a phrase which is "</span>
<span class="string">"defined using inline Inform 6 code in (- markers -). Such "</span>
<span class="string">"phrases can't be named and used as constants because they "</span>
<span class="string">"have no independent existence, being instead made fresh "</span>
<span class="string">"each time they are used."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. Late Afternoon. </b>Rules are pretty well sorted out now, but we still need to compile some I6
to show how they fit together. These miscellaneous function calls can happen
in any order, so long as they all occur in the late afternoon.
</p>
<p class="inwebparagraph">First, rules set to go off at a particular time need to have their timings
noted down:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::TimedEventsTable</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Phrases::Manager::advance_phrase_time_to</span><span class="plain">(</span><span class="constant">LATE_AFTERNOON_PHT</span><span class="plain">);</span>
<span class="functiontext">Phrases::Timed::TimedEventsTable</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::TimedEventTimesTable</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Phrases::Manager::advance_phrase_time_to</span><span class="plain">(</span><span class="constant">LATE_AFTERNOON_PHT</span><span class="plain">);</span>
<span class="functiontext">Phrases::Timed::TimedEventTimesTable</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Manager::TimedEventsTable appears nowhere else.</p>
<p class="endnote">The function Phrases::Manager::TimedEventTimesTable appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>Second, the rulebooks need to be compiled into I6 arrays:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::rulebooks_array</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Phrases::Manager::advance_phrase_time_to</span><span class="plain">(</span><span class="constant">LATE_AFTERNOON_PHT</span><span class="plain">);</span>
<span class="functiontext">Rulebooks::rulebooks_array_array</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::compile_rulebooks</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Phrases::Manager::advance_phrase_time_to</span><span class="plain">(</span><span class="constant">LATE_AFTERNOON_PHT</span><span class="plain">);</span>
<span class="functiontext">Rulebooks::compile_rulebooks</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::RulebookNames_array</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Phrases::Manager::advance_phrase_time_to</span><span class="plain">(</span><span class="constant">LATE_AFTERNOON_PHT</span><span class="plain">);</span>
<span class="functiontext">Rulebooks::RulebookNames_array</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Manager::rulebooks_array is used in 1/htc (<a href="1-htc.html#SP2_8">&#167;2.8</a>).</p>
<p class="endnote">The function Phrases::Manager::compile_rulebooks is used in 1/htc (<a href="1-htc.html#SP2_8">&#167;2.8</a>).</p>
<p class="endnote">The function Phrases::Manager::RulebookNames_array is used in 1/htc (<a href="1-htc.html#SP2_8">&#167;2.8</a>).</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b>And finally, just as the sun slips below the horizon, we compile the code
which prints out values of the kind "rule" at run-time &mdash; for example, taking
the address of the routine which our example rule was compiled to and then
printing out "fire alarm rule".
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::RulePrintingRule_routine</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Phrases::Manager::advance_phrase_time_to</span><span class="plain">(</span><span class="constant">LATE_AFTERNOON_PHT</span><span class="plain">);</span>
<span class="functiontext">Rules::RulePrintingRule_routine</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Manager::RulePrintingRule_routine is used in 1/htc (<a href="1-htc.html#SP2_8">&#167;2.8</a>).</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. Evening. </b>The twilight gathers, but our work is far from done. Recall that we have
accumulated compilation requests for "To..." phrases, but haven't actually
acted on them yet.
</p>
<p class="inwebparagraph">We have to do this in quite an open-ended way, because compiling one phrase
can easily generate fresh requests for others. For instance, suppose we have
the definition "To expose (X - a value)" in play, and suppose that when
compiling the phrase "To advertise", Inform runs into the line "expose the
hoarding text". This causes it to issue a compilation request for "To expose
(X - a text)". Perhaps we've compiled such a form already, but perhaps we
haven't. Compilation therefore goes on until all requests have been dealt
with.
</p>
<p class="inwebparagraph">Compiling phrases also produces the need for other pieces of code to be
generated &mdash; for example, suppose our phrase being compiled, "To advertise",
includes the text:
</p>
<blockquote>
<p>let Z be "Two for the price of one! Just [expose price]!";</p>
</blockquote>
<p class="inwebparagraph">We are going to need to compile "Two for the price of one! Just [expose price]!"
later on, in its own text substitution routine; but notice that it contains
the need for "To expose (X - a number)", and that will generate a further
phrase request.
</p>
<p class="inwebparagraph">Because of this and similar problems, it's impossible to compile all the
phrases alone: we must compile phrases, then things arising from them, then
phrases arising from those, then things arising from the phrases arising
from those, and so on, until we're done. The process is therefore structured
as a set of "coroutines" which each carry out as much as they can and then
hand over to the others to generate more work. (Indeed, the routine below
can be called multiple times in the course of the evening.)
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Manager::compile_as_needed</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Phrases::Manager::advance_phrase_time_to</span><span class="plain">(</span><span class="constant">EVENING_PHT</span><span class="plain">);</span>
<span class="reserved">rule</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="reserved">rule</span><span class="plain">)</span>
<span class="functiontext">Rules::compile_definition</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">,</span>
<span class="plain">&amp;</span><span class="identifier">total_phrases_compiled</span><span class="plain">, </span><span class="identifier">total_phrases_to_compile</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">repeat</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">repeat</span><span class="plain">) {</span>
<span class="identifier">repeat</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="functiontext">Routines::ToPhrases::compilation_coroutine</span><span class="plain">(</span>
<span class="plain">&amp;</span><span class="identifier">total_phrases_compiled</span><span class="plain">, </span><span class="identifier">total_phrases_to_compile</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">repeat</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ListTogether::compilation_coroutine</span><span class="plain">() &gt; </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">repeat</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PL::Actions::ScopeLoops::compilation_coroutine</span><span class="plain">() &gt; </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">repeat</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Strings::TextSubstitutions::compilation_coroutine</span><span class="plain">(</span><span class="identifier">FALSE</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">repeat</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Calculus::Propositions::Deferred::compilation_coroutine</span><span class="plain">() &gt; </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">repeat</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Manager::compile_as_needed is used in 1/htc (<a href="1-htc.html#SP2_8">&#167;2.8</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="22-itp.html">Back to 'Introduction to Phrases'</a></li><li><a href="22-ph.html">Continue with 'Phrases'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>