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/14-ds2.html
2020-01-27 21:54:07 +00:00

5342 lines
572 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>14/cfs</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 '14/ds2' 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#14">Chapter 14: Specifications</a></li><li><b>Dash</b></li></ul><p class="purpose">Dash is the part of Inform most nearly like a typechecker in a conventional compiler.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP4">&#167;4. The Dashboard</a></li><li><a href="#SP8">&#167;8. Return values</a></li><li><a href="#SP9">&#167;9. (1) Entering Dash</a></li><li><a href="#SP10">&#167;10. (2) Recursion point</a></li><li><a href="#SP11">&#167;11. (3) Context switching</a></li><li><a href="#SP11_8">&#167;11.8. New variables</a></li><li><a href="#SP11_9">&#167;11.9. (4) Typechecking within current context</a></li><li><a href="#SP11_9_1_2">&#167;11.9.1.2. (4S) Verifying single non-invocation readings</a></li><li><a href="#SP13">&#167;13. Arithmetic operands</a></li><li><a href="#SP14">&#167;14. Local variable markers</a></li><li><a href="#SP15">&#167;15. Problems, problems, problems</a></li><li><a href="#SP19">&#167;19. (5) Single nodes</a></li><li><a href="#SP19_2">&#167;19.2. Rule (5.a)</a></li><li><a href="#SP19_3">&#167;19.3. Rule (5.b)</a></li><li><a href="#SP19_4">&#167;19.4. Rule (5.c)</a></li><li><a href="#SP19_5">&#167;19.5. Rule (5.d)</a></li><li><a href="#SP19_6">&#167;19.6. Rule (5.e)</a></li><li><a href="#SP22">&#167;22. Ambiguity testing flags</a></li><li><a href="#SP27">&#167;27. Value checking</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>Dash is the second typechecking algorithm to be used in Inform, installed in
early 2015: the first had served since 2003, but became unwieldy after so many
exceptional cases had been added to it, and was impossible to adapt to the
redesigned parse tree. Dash is not so called because it's faster (it's
actually a few percent slower), but because at one stage Inform was running
both typecheckers side by side: TC and TC-dash, or Dash for short. TC-dash
won, it's still called Dash, and TC is no more.
</p>
<p class="inwebparagraph">Because Dash also deals with text which entirely fails to make sense, which in
other compilers would be rejected at a lower level, it has to issue basic
syntax errors as well as type mismatch errors. This is arguably a good thing,
though, because it means they can be issued using the same generally helpful
system as more sophisticated problems.
</p>
<p class="inwebparagraph">Partly because of the need to do this, the type-checker has a top-down
approach. It aims to prove that the node found can match what's expected,
making selections from alternative readings, and in limited cases actually
making changes to the parse tree, in order to do this. For instance,
consider checking the tree for:
</p>
<blockquote>
<p>let the score be the score plus 10</p>
</blockquote>
<p class="inwebparagraph">Dash takes the view that the phrase usage can be proved correct, so long as
the arguments can also be proved. There are several valid interpretations of
"let ... be ...", and these are all present in the parse tree as alternative
interpretations, so the typechecker tries each in turn, accepting one (or
more) if the arguments can be proved to be of the right type. This means
proving that argument 0 ("the score") matches a generic <code class="display"><span class="extract">NONLOCAL_VARIABLE_NT</span></code>
and also that argument 1 ("the score plus 10") matches a generic rvalue. A
further rule requires that the kind of value of argument 1 must match the kind
of value stored in the variable, here a "number", so we must prove that too.
Now "plus" is polymorphic and can produce different kinds of value depending
on the kinds of value it acts upon, so again we must check all possible
interpretations. But we finally succeed in showing that "score" is an lvalue,
"10" is a number, "score" is also a number, and that "plus" on two numbers
gives a number, so we complete the proof and the phrase is proved correct.
</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>When issuing problems, we show a form of backtrace so that the user can
see what we've considered, and this is used to accumulate data for that.
</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">inv_token_problem_token</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">problematic_text</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">as_parsed</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">already_described</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">new_name</span><span class="plain">; </span> <span class="comment">found in context of a name not yet defined</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">inv_token_problem_token</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure inv_token_problem_token is private to this section.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. The Dashboard. </b>Dash uses a small suite of global variables to keep track of two decidedly
global side-effects of checking: the issuing of problem messages, and the
setting of kind variables. This suite is called the "dashboard".
</p>
<p class="inwebparagraph">First, we keep track of the problem messages we will issue, if any, using
a bitmap made up of the following modes:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">BEGIN_DASH_MODE</span><span class="plain"> </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">s_dm</span><span class="plain"> = </span><span class="identifier">dash_mode</span><span class="plain">; </span><span class="identifier">kind</span><span class="plain"> **</span><span class="identifier">s_kvc</span><span class="plain"> = </span><span class="identifier">kind_of_var_to_create</span><span class="plain">; </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">s_invl</span><span class="plain"> = </span><span class="identifier">Dash_ambiguity_list</span><span class="plain">;</span>
<span class="definitionkeyword">define</span> <span class="identifier">DASH_MODE_ENTER</span><span class="plain">(</span><span class="identifier">mode</span><span class="plain">) </span><span class="identifier">dash_mode</span><span class="plain"> |= </span><span class="identifier">mode</span><span class="plain">;</span>
<span class="definitionkeyword">define</span> <span class="identifier">DASH_MODE_CREATE</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) </span><span class="identifier">kind_of_var_to_create</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">;</span>
<span class="definitionkeyword">define</span> <span class="identifier">DASH_MODE_INVL</span><span class="plain">(</span><span class="identifier">invl</span><span class="plain">) </span><span class="identifier">Dash_ambiguity_list</span><span class="plain"> = </span><span class="identifier">invl</span><span class="plain">;</span>
<span class="definitionkeyword">define</span> <span class="identifier">DASH_MODE_EXIT</span><span class="plain">(</span><span class="identifier">mode</span><span class="plain">) </span><span class="identifier">dash_mode</span><span class="plain"> &amp;= (~</span><span class="identifier">mode</span><span class="plain">);</span>
<span class="definitionkeyword">define</span> <span class="constant">END_DASH_MODE</span><span class="plain"> </span><span class="identifier">dash_mode</span><span class="plain"> = </span><span class="identifier">s_dm</span><span class="plain">; </span><span class="identifier">kind_of_var_to_create</span><span class="plain"> = </span><span class="identifier">s_kvc</span><span class="plain">; </span><span class="identifier">Dash_ambiguity_list</span><span class="plain"> = </span><span class="identifier">s_invl</span><span class="plain">;</span>
<span class="definitionkeyword">define</span> <span class="identifier">TEST_DASH_MODE</span><span class="plain">(</span><span class="identifier">mode</span><span class="plain">) (</span><span class="identifier">dash_mode</span><span class="plain"> &amp; </span><span class="identifier">mode</span><span class="plain">)</span>
<span class="definitionkeyword">define</span> <span class="constant">ISSUE_PROBLEMS_DMODE</span><span class="plain"> 0</span><span class="identifier">x00000001</span><span class="plain"> </span> <span class="comment">rather than keep silent about them</span>
<span class="definitionkeyword">define</span> <span class="constant">ISSUE_LOCAL_PROBLEMS_DMODE</span><span class="plain"> 0</span><span class="identifier">x00000002</span><span class="plain"> </span> <span class="comment">at the end, that is</span>
<span class="definitionkeyword">define</span> <span class="constant">ISSUE_GROSS_PROBLEMS_DMODE</span><span class="plain"> 0</span><span class="identifier">x00000004</span><span class="plain"> </span> <span class="comment">at the end, that is</span>
<span class="definitionkeyword">define</span> <span class="constant">ISSUE_INTERESTING_PROBLEMS_DMODE</span><span class="plain"> 0</span><span class="identifier">x00000008</span><span class="plain"> </span> <span class="comment">unless casting to text</span>
<span class="definitionkeyword">define</span> <span class="constant">ABSOLUTE_SILENCE_DMODE</span><span class="plain"> 0</span><span class="identifier">x00000010</span><span class="plain"> </span> <span class="comment">say nothing at all</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">dash_mode</span><span class="plain"> = </span><span class="constant">ISSUE_PROBLEMS_DMODE</span><span class="plain">; </span> <span class="comment">default</span>
<span class="identifier">kind</span><span class="plain"> **</span><span class="identifier">kind_of_var_to_create</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="identifier">dash_recursion_count</span><span class="plain"> = 0;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>Three grades of problem can appear: "ordinary", "gross" and "grosser than
gross". We distinguish these in order to produce a Problem message which
reflects the biggest thing wrong, rather than being so esoteric that it misses
the main point. Changing a particular error condition from an ordinary to a
gross problem, or vice versa, has no effect on the result returned by Dash,
only on the Problem messages given to the user.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">THIS_IS_A_GROSSER_THAN_GROSS_PROBLEM</span>
<span class="identifier">no_gross_problems_thrown</span><span class="plain">++; </span> <span class="comment">problems this gross cannot be suppressed</span>
<span class="definitionkeyword">define</span> <span class="constant">THIS_IS_A_GROSS_PROBLEM</span>
<span class="identifier">no_gross_problems_thrown</span><span class="plain">++; </span> <span class="comment">this increments even if the message is suppressed</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">TEST_DASH_MODE</span><span class="plain">(</span><span class="constant">ISSUE_PROBLEMS_DMODE</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">TEST_DASH_MODE</span><span class="plain">(</span><span class="constant">ISSUE_GROSS_PROBLEMS_DMODE</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="definitionkeyword">define</span> <span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TEST_DASH_MODE</span><span class="plain">(</span><span class="constant">ISSUE_PROBLEMS_DMODE</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_gross_problems_thrown</span><span class="plain"> = 0;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_interesting_problems_thrown</span><span class="plain"> = 0;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">initial_problem_count</span><span class="plain"> = 0;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">backtraced_problem_count</span><span class="plain"> = 0;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::problems_have_been_issued</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">initial_problem_count</span><span class="plain"> &lt; </span><span class="identifier">problem_count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::problems_have_been_issued is used in <a href="#SP11_9_2">&#167;11.9.2</a>, <a href="#SP11_9_2_2">&#167;11.9.2.2</a>, <a href="#SP11_9_1_1_3_1">&#167;11.9.1.1.3.1</a>, <a href="#SP11_9_1_1_4">&#167;11.9.1.1.4</a>, <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>Next, we keep track of the most recent set of meanings attached to the
kind variables A, B, C, ..., Z, and the most recently looked-at list of
invocations.
</p>
<pre class="display">
<span class="identifier">kind_variable_declaration</span><span class="plain"> *</span><span class="identifier">most_recent_interpretation</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">Dash_ambiguity_list</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>We need careful debug logging of what Dash does. During Inform's infancy, it
was not so much that this was the great habitat and breeding ground for bugs;
more that those bugs which were here were by far the hardest to root out. So
careful logging on demand is vital.
</p>
<p class="inwebparagraph">Each call to the recursive Dash has its own unique ID number, to make logging
more legible.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">LOG_DASH_LEFT</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"[%d%s] "</span><span class="plain">,</span>
<span class="identifier">unique_DR_call_identifier</span><span class="plain">,</span>
<span class="plain">(</span><span class="identifier">TEST_DASH_MODE</span><span class="plain">(</span><span class="constant">ISSUE_PROBLEMS_DMODE</span><span class="plain">))?</span><span class="string">""</span><span class="plain">:</span><span class="string">"-silent"</span><span class="plain">);</span>
<span class="definitionkeyword">define</span> <span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="identifier">stage</span><span class="plain">)</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"[%d%s] %s $P\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">unique_DR_call_identifier</span><span class="plain">,</span>
<span class="plain">(</span><span class="identifier">TEST_DASH_MODE</span><span class="plain">(</span><span class="constant">ISSUE_PROBLEMS_DMODE</span><span class="plain">))?</span><span class="string">""</span><span class="plain">:</span><span class="string">"-silent"</span><span class="plain">, </span><span class="identifier">stage</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">unique_DR_call_identifier</span><span class="plain"> = 0, </span><span class="identifier">DR_call_counter</span><span class="plain"> = 0; </span> <span class="comment">solely to make the log more legible</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. Return values. </b>Dash records the outcome of checking as one of three states.
</p>
<p class="inwebparagraph">It is perhaps telling that we never need a <code class="display"><span class="extract">Dash::best_case</span></code> routine.
Typecheckers are not allowed to be optimistic.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::worst_case</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv1</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv2</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">rv1</span><span class="plain"> == </span><span class="identifier">NEVER_MATCH</span><span class="plain">) || (</span><span class="identifier">rv2</span><span class="plain"> == </span><span class="identifier">NEVER_MATCH</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">rv1</span><span class="plain"> == </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">) || (</span><span class="identifier">rv2</span><span class="plain"> == </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::worst_case is used in <a href="#SP11_5">&#167;11.5</a>, <a href="#SP11_6">&#167;11.6</a>, <a href="#SP11_9_2_2_1">&#167;11.9.2.2.1</a>, <a href="#SP11_9_1_1">&#167;11.9.1.1</a>, <a href="#SP11_9_1_1_4">&#167;11.9.1.1.4</a>, <a href="#SP11_9_1_1_6">&#167;11.9.1.1.6</a>, <a href="#SP11_9_1_2">&#167;11.9.1.2</a>, <a href="#SP27">&#167;27</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. (1) Entering Dash. </b>Dash is structured into levels and this is level 1, the topmost.
</p>
<p class="inwebparagraph">Dash has three points of entry: to check a condition, check a value, or check
an invocation list for a phrase used in a routine.
</p>
<p class="inwebparagraph">These top-level routines do not look recursive, but in fact some can be,
because Dash needs to call the predicate calculus engine to typecheck
propositions: and these in turn call Dash to check that constant values
are used correctly.
</p>
<p class="inwebparagraph">All of these funnel downwards into level 2:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::check_condition</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="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">cn</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">CONDITION_CONTEXT_NT</span><span class="plain">);</span>
<span class="identifier">cn</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Dash (1): condition\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Dash::funnel_to_level_2</span><span class="plain">(</span><span class="identifier">cn</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::check_value</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="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">vn</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">RVALUE_CONTEXT_NT</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">) </span><span class="identifier">ParseTree::set_kind_required_by_context</span><span class="plain">(</span><span class="identifier">vn</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="identifier">vn</span><span class="plain">-</span><span class="element">&gt;down</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">K</span><span class="plain">) </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Dash (1): value of kind $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Dash (1): value\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Dash::funnel_to_level_2</span><span class="plain">(</span><span class="identifier">vn</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::check_value_silently</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="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">vn</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">RVALUE_CONTEXT_NT</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">) </span><span class="identifier">ParseTree::set_kind_required_by_context</span><span class="plain">(</span><span class="identifier">vn</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="identifier">vn</span><span class="plain">-</span><span class="element">&gt;down</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">K</span><span class="plain">) </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Dash (1): value of kind $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Dash (1): value\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Dash::funnel_to_level_2</span><span class="plain">(</span><span class="identifier">vn</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::check_invl</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="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Dash (1): invocation list '%W'\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Dash::funnel_to_level_2</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::funnel_to_level_2</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">silently</span><span class="plain">) {</span>
<span class="identifier">no_gross_problems_thrown</span><span class="plain"> = 0;</span>
<span class="identifier">dash_recursion_count</span><span class="plain"> = 0;</span>
<span class="constant">BEGIN_DASH_MODE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (!</span><span class="identifier">silently</span><span class="plain">) </span><span class="identifier">DASH_MODE_ENTER</span><span class="plain">(</span><span class="constant">ISSUE_PROBLEMS_DMODE</span><span class="plain">);</span>
<span class="identifier">initial_problem_count</span><span class="plain"> = </span><span class="identifier">problem_count</span><span class="plain">;</span>
<span class="identifier">DASH_MODE_CREATE</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">Kinds::Compare::show_frame_variables</span><span class="plain">();</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext">Dash::typecheck_recursive</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="constant">END_DASH_MODE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::check_condition is used in <a href="#SP24">&#167;24</a>, <a href="#SP25">&#167;25</a>, 21/rl (<a href="21-rl.html#SP11_1">&#167;11.1</a>), 25/cp (<a href="25-cp.html#SP5_3_2">&#167;5.3.2</a>).</p>
<p class="endnote">The function Dash::check_value is used in <a href="#SP25">&#167;25</a>, <a href="#SP28">&#167;28</a>, 11/tr (<a href="11-tr.html#SP10">&#167;10</a>), 11/tcp (<a href="11-tcp.html#SP6_1">&#167;6.1</a>), 12/cad (<a href="12-cad.html#SP6">&#167;6</a>), 25/cii (<a href="25-cii.html#SP8">&#167;8</a>), 25/cp (<a href="25-cp.html#SP5_3_5">&#167;5.3.5</a>), 26/ts (<a href="26-ts.html#SP11">&#167;11</a>).</p>
<p class="endnote">The function Dash::check_value_silently is used in 11/tcp (<a href="11-tcp.html#SP6_1">&#167;6.1</a>), 18/lc (<a href="18-lc.html#SP8">&#167;8</a>).</p>
<p class="endnote">The function Dash::check_invl is used in 25/cp (<a href="25-cp.html#SP6">&#167;6</a>).</p>
<p class="endnote">The function Dash::funnel_to_level_2 appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. (2) Recursion point. </b>Loosely speaking, Dash works by visiting every node in the parse tree being
examined with the following routine, which is therefore recursive as Dash
heads ever downward.
</p>
<p class="inwebparagraph">The routine itself is really just an outer shell, though, and has two
functions: it keeps the debugging log tidy (see above) and it produces
the backtrace if the inner routine should throw a problem message.
</p>
<p class="inwebparagraph">The recursion limit below is clearly arbitrary, but is there to prevent the
algorithm from slowing Inform unacceptably in the event of something like
</p>
<blockquote>
<p>say g / g / g / g / g / g / g / g / g / g / g / g / g / g / g / g / g / g / g / g / g / g / g;</p>
</blockquote>
<p class="inwebparagraph">where "g" is a term Inform doesn't recognise, because otherwise this will
recurse through every possible interpretation of the divide sign (i.e. every
possible order of operations).
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_DASH_RECURSION</span><span class="plain"> 10000</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::typecheck_recursive</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="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">context</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">consider_alternatives</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</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">"Dash on null node"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">dash_recursion_count</span><span class="plain"> &gt;= </span><span class="constant">MAX_DASH_RECURSION</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="identifier">dash_recursion_count</span><span class="plain">++;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">outer_id</span><span class="plain"> = </span><span class="identifier">unique_DR_call_identifier</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">problem_count_before</span><span class="plain"> = </span><span class="identifier">problem_count</span><span class="plain">;</span>
<span class="identifier">unique_DR_call_identifier</span><span class="plain"> = </span><span class="identifier">DR_call_counter</span><span class="plain">++;</span>
<span class="identifier">LOG_INDENT</span><span class="plain">;</span>
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(2)"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">return_value</span><span class="plain"> = </span><span class="functiontext">Dash::typecheck_recursive_inner</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">context</span><span class="plain">, </span><span class="identifier">consider_alternatives</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">return_value</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">: </span><span class="constant">LOG_DASH_LEFT</span><span class="plain">; </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"== always\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">: </span><span class="constant">LOG_DASH_LEFT</span><span class="plain">; </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"== sometimes\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">: </span><span class="constant">LOG_DASH_LEFT</span><span class="plain">; </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"== never\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"impossible verdict from Dash"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">problem_count</span><span class="plain"> &gt; </span><span class="identifier">problem_count_before</span><span class="plain">) &amp;&amp; (</span><span class="identifier">consider_alternatives</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Consider adding a backtrace of what the type-checker was up to</span> <span class="cwebmacronumber">10.1</span>&gt;<span class="plain">;</span>
<span class="identifier">unique_DR_call_identifier</span><span class="plain"> = </span><span class="identifier">outer_id</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">return_value</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::typecheck_recursive is used in <a href="#SP9">&#167;9</a>, <a href="#SP11_1">&#167;11.1</a>, <a href="#SP11_9_1">&#167;11.9.1</a>, <a href="#SP11_9_2_2_1">&#167;11.9.2.2.1</a>, <a href="#SP11_9_1_1_2_1">&#167;11.9.1.1.2.1</a>, <a href="#SP11_9_1_1_3_1">&#167;11.9.1.1.3.1</a>, <a href="#SP11_9_1_2">&#167;11.9.1.2</a>, <a href="#SP13">&#167;13</a>, <a href="#SP15_3">&#167;15.3</a>, <a href="#SP15_4">&#167;15.4</a>.</p>
<p class="inwebparagraph"><a id="SP10_1"></a><b>&#167;10.1. </b>The backtrace is added to problem messages only if we have just been checking
a phrase, and if it produced problems not previously seen. The trick here is
to ensure that if we have
</p>
<blockquote>
<p>let X be a random wibble bibble spong;</p>
</blockquote>
<p class="inwebparagraph">then it will be the "random ..." phrase which is backtraced, and not the
"let ..." phrase, even though that also goes wrong in turn.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Consider adding a backtrace of what the type-checker was up to</span> <span class="cwebmacronumber">10.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> &gt; </span><span class="identifier">backtraced_problem_count</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;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">) == </span><span class="constant">INVOCATION_LIST_NT</span><span class="plain">)) {</span>
<span class="identifier">it_is_not_worth_adding</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Backtrace what phrase definitions the type-checker was looking at</span> <span class="cwebmacronumber">10.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">it_is_not_worth_adding</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">backtraced_problem_count</span><span class="plain"> = </span><span class="identifier">problem_count</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_1_1"></a><b>&#167;10.1.1. </b>We skip proven invocations, and those never needed because of them, since
those aren't in dispute; and we also skip groups not even reached, since they
aren't where the problem lies. (This can happen when checking a compound "say",
from a text substitution.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Backtrace what phrase definitions the type-checker was looking at</span> <span class="cwebmacronumber">10.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain">;</span>
<span class="identifier">LOOP_THROUGH_ALTERNATIVES</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$e\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">to_show</span><span class="plain"> = 0;</span>
<span class="identifier">LOOP_THROUGH_ALTERNATIVES</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) {</span>
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain"> = </span><span class="identifier">ParseTree::get_phrase_invoked</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Phrases::TypeData::is_a_spare_say_X_phrase</span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data</span><span class="plain">))) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="identifier">to_show</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">announce</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">latest</span><span class="plain"> = </span><span class="identifier">Problems::Issue::latest_sigil</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">latest</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"PM_AllInvsFailed"</span><span class="plain">)) </span><span class="identifier">announce</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">announce</span><span class="plain">) </span>&lt;<span class="cwebmacro">Produce the I was trying... banner</span> <span class="cwebmacronumber">10.1.1.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Produce the list of possibilities</span> <span class="cwebmacronumber">10.1.1.2</span>&gt;<span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">real_found</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Produce the tokens which were recognisable as something</span> <span class="cwebmacronumber">10.1.1.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Produce the tokens which weren't recognisable as something</span> <span class="cwebmacronumber">10.1.1.5</span>&gt;<span class="character">;</span>
&lt;<span class="cwebmacro">Produce the tokens which were intentionally not recognisable as something</span> <span class="cwebmacronumber">10.1.1.4</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">real_found</span><span class="plain">) </span>&lt;<span class="cwebmacro">Produce a note about real versus integer</span> <span class="cwebmacronumber">10.1.1.6</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_1">&#167;10.1</a>.</p>
<p class="inwebparagraph"><a id="SP10_1_1_1"></a><b>&#167;10.1.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Produce the I was trying... banner</span> <span class="cwebmacronumber">10.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::issue_problem_begin</span><span class="plain">(</span><span class="string">"*"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">to_show</span><span class="plain"> &gt; 1)</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span><span class="string">"I was trying to match one of these phrases:"</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span><span class="string">"I was trying to match this phrase:"</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="#SP10_1_1">&#167;10.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP10_1_1_2"></a><b>&#167;10.1.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Produce the list of possibilities</span> <span class="cwebmacronumber">10.1.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">shown</span><span class="plain"> = 0;</span>
<span class="identifier">LOOP_THROUGH_ALTERNATIVES</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) {</span>
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain"> = </span><span class="identifier">ParseTree::get_phrase_invoked</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Phrases::TypeData::is_a_spare_say_X_phrase</span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data</span><span class="plain">))) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="identifier">shown</span><span class="plain">++;</span>
<span class="identifier">Problems::quote_number</span><span class="plain">(1, &amp;</span><span class="identifier">shown</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_invocation</span><span class="plain">(2, </span><span class="identifier">inv</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">announce</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">Problems::issue_problem_begin</span><span class="plain">(</span><span class="string">"***"</span><span class="plain">);</span>
<span class="identifier">announce</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">Problems::issue_problem_begin</span><span class="plain">(</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">to_show</span><span class="plain"> &gt; 1) </span><span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span><span class="string">"%1. %2"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span><span class="string">"%2"</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_1_1">&#167;10.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP10_1_1_3"></a><b>&#167;10.1.1.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Produce the tokens which were recognisable as something</span> <span class="cwebmacronumber">10.1.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">any</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">inv_token_problem_token</span><span class="plain"> *</span><span class="identifier">itpt</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">itpt</span><span class="plain">, </span><span class="reserved">inv_token_problem_token</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;as_parsed</span><span class="plain">, </span><span class="constant">UNKNOWN_NT</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;already_described</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;already_described</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="identifier">any</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">any</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">Problems::issue_problem_begin</span><span class="plain">(</span><span class="string">"*"</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span><span class="string">"I recognised:"</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Produce this token</span> <span class="cwebmacronumber">10.1.1.3.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_1_1">&#167;10.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP10_1_1_3_1"></a><b>&#167;10.1.1.3.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Produce this token</span> <span class="cwebmacronumber">10.1.1.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::quote_wording_tinted_green</span><span class="plain">(1, </span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;problematic_text</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_spec</span><span class="plain">(2, </span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;as_parsed</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_begin</span><span class="plain">(</span><span class="string">"****"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTreeUsage::is_value</span><span class="plain">(</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;as_parsed</span><span class="plain">)) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;as_parsed</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">changed</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">K</span><span class="plain"> = </span><span class="identifier">Kinds::substitute</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, &amp;</span><span class="identifier">changed</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="identifier">K</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">K_real_number</span><span class="plain">)) </span><span class="identifier">real_found</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">ParseTreeUsage::is_lvalue</span><span class="plain">(</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;as_parsed</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Produce the token for an lvalue</span> <span class="cwebmacronumber">10.1.1.3.1.1</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;as_parsed</span><span class="plain">, </span><span class="constant">PHRASE_TO_DECIDE_VALUE_NT</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Produce the token for a phrase deciding a value</span> <span class="cwebmacronumber">10.1.1.3.1.2</span>&gt;
<span class="reserved">else</span>
&lt;<span class="cwebmacro">Produce the token for a constant rvalue</span> <span class="cwebmacronumber">10.1.1.3.1.3</span>&gt;<span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span><span class="string">"%1 = &lt;i&gt;%2&lt;/i&gt;"</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="#SP10_1_1_3">&#167;10.1.1.3</a>.</p>
<p class="inwebparagraph"><a id="SP10_1_1_3_1_1"></a><b>&#167;10.1.1.3.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Produce the token for an lvalue</span> <span class="cwebmacronumber">10.1.1.3.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span><span class="string">"%1 = &lt;i&gt;%2&lt;/i&gt;, holding &lt;i&gt;%3&lt;/i&gt;"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_1_1_3_1">&#167;10.1.1.3.1</a>.</p>
<p class="inwebparagraph"><a id="SP10_1_1_3_1_2"></a><b>&#167;10.1.1.3.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Produce the token for a phrase deciding a value</span> <span class="cwebmacronumber">10.1.1.3.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">seg</span><span class="plain"> = </span><span class="string">"%1 = an instruction to work out &lt;i&gt;%3&lt;/i&gt;"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">seg</span><span class="plain"> = </span><span class="string">"%1 = a phrase"</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">found_invl</span><span class="plain"> = </span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;as_parsed</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain">;</span>
<span class="identifier">LOOP_THROUGH_ALTERNATIVES</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">found_invl</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$e\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::reading_passed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">seg</span><span class="plain"> = </span><span class="string">"%1 = an instruction I think should work out &lt;i&gt;%3&lt;/i&gt;, "</span>
<span class="string">"but which I can't make sense of"</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="functiontext">Invocations::get_no_tokens</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">tok</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token_as_parsed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">, </span><span class="constant">UNKNOWN_NT</span><span class="plain">)) {</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(4, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">));</span>
<span class="identifier">seg</span><span class="plain"> = </span><span class="string">"%1 = an instruction I think should work out &lt;i&gt;%3&lt;/i&gt;, "</span>
<span class="string">"but which I can't perform because '%4' doesn't make sense here"</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span><span class="identifier">seg</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_1_1_3_1">&#167;10.1.1.3.1</a>.</p>
<p class="inwebparagraph"><a id="SP10_1_1_3_1_3"></a><b>&#167;10.1.1.3.1.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Produce the token for a constant rvalue</span> <span class="cwebmacronumber">10.1.1.3.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">seg</span><span class="plain"> = </span><span class="string">"%1 = &lt;i&gt;%3&lt;/i&gt;"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Rvalues::is_CONSTANT_construction</span><span class="plain">(</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;as_parsed</span><span class="plain">, </span><span class="identifier">CON_property</span><span class="plain">)) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain"> = </span><span class="identifier">ParseTree::get_constant_property</span><span class="plain">(</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;as_parsed</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::is_value_property</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">)) {</span>
<span class="reserved">binary_predicate</span><span class="plain"> *</span><span class="identifier">bp</span><span class="plain"> = </span><span class="functiontext">Properties::Valued::get_stored_relation</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">bp</span><span class="plain">) {</span>
<span class="identifier">seg</span><span class="plain"> = </span><span class="string">"%1 = &lt;i&gt;%3&lt;/i&gt;, which is used to store %4, "</span>
<span class="string">"but is not the same thing as the relation itself"</span><span class="plain">;</span>
<span class="functiontext">Problems::quote_relation</span><span class="plain">(4, </span><span class="identifier">bp</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span><span class="identifier">seg</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_1_1_3_1">&#167;10.1.1.3.1</a>.</p>
<p class="inwebparagraph"><a id="SP10_1_1_4"></a><b>&#167;10.1.1.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Produce the tokens which were intentionally not recognisable as something</span> <span class="cwebmacronumber">10.1.1.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">unknowns</span><span class="plain"> = 0;</span>
<span class="reserved">inv_token_problem_token</span><span class="plain"> *</span><span class="identifier">itpt</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">itpt</span><span class="plain">, </span><span class="reserved">inv_token_problem_token</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;as_parsed</span><span class="plain">, </span><span class="constant">UNKNOWN_NT</span><span class="plain">)) &amp;&amp; (</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;new_name</span><span class="plain">))</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;already_described</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;already_described</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="identifier">unknowns</span><span class="plain"> &lt; 5) {</span>
<span class="identifier">Problems::quote_wording_tinted_red</span><span class="plain">(++</span><span class="identifier">unknowns</span><span class="plain">,</span>
<span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;problematic_text</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">unknowns</span><span class="plain"> &gt; 0) {</span>
<span class="identifier">Problems::issue_problem_begin</span><span class="plain">(</span><span class="string">"*"</span><span class="plain">);</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">chunk</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">unknowns</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> 1: </span><span class="identifier">chunk</span><span class="plain"> = </span><span class="string">"The name '%1' doesn't yet exist."</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> 2: </span><span class="identifier">chunk</span><span class="plain"> = </span><span class="string">"The names '%1' and '%2' don't yet exist."</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> 3: </span><span class="identifier">chunk</span><span class="plain"> = </span><span class="string">"The names '%1', '%2' and '%3' don't yet exist."</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> 4: </span><span class="identifier">chunk</span><span class="plain"> = </span><span class="string">"The names '%1', '%2', '%3' and '%4' don't yet exist."</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">chunk</span><span class="plain"> = </span><span class="string">"The names '%1', '%2', '%3', '%4', and so on, don't yet exist."</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span><span class="identifier">chunk</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_1_1">&#167;10.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP10_1_1_5"></a><b>&#167;10.1.1.5. </b><code class="display">
&lt;<span class="cwebmacrodefn">Produce the tokens which weren't recognisable as something</span> <span class="cwebmacronumber">10.1.1.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">unknowns</span><span class="plain"> = 0;</span>
<span class="reserved">inv_token_problem_token</span><span class="plain"> *</span><span class="identifier">itpt</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">itpt</span><span class="plain">, </span><span class="reserved">inv_token_problem_token</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;as_parsed</span><span class="plain">, </span><span class="constant">UNKNOWN_NT</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;new_name</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">))</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;already_described</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;already_described</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="identifier">unknowns</span><span class="plain"> &lt; 5) {</span>
<span class="identifier">Problems::quote_wording_tinted_red</span><span class="plain">(++</span><span class="identifier">unknowns</span><span class="plain">,</span>
<span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;problematic_text</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">unknowns</span><span class="plain"> &gt; 0) {</span>
<span class="identifier">Problems::issue_problem_begin</span><span class="plain">(</span><span class="string">"*"</span><span class="plain">);</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">chunk</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">unknowns</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> 1: </span><span class="identifier">chunk</span><span class="plain"> = </span><span class="string">"But I didn't recognise '%1'."</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> 2: </span><span class="identifier">chunk</span><span class="plain"> = </span><span class="string">"But I didn't recognise '%1' or '%2'."</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> 3: </span><span class="identifier">chunk</span><span class="plain"> = </span><span class="string">"But I didn't recognise '%1', '%2' or '%3'."</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> 4: </span><span class="identifier">chunk</span><span class="plain"> = </span><span class="string">"But I didn't recognise '%1', '%2', '%3' or '%4'."</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">chunk</span><span class="plain"> = </span><span class="string">"But I didn't recognise '%1', '%2', '%3', '%4' and so on."</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span><span class="identifier">chunk</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_1_1">&#167;10.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP10_1_1_6"></a><b>&#167;10.1.1.6. </b><code class="display">
&lt;<span class="cwebmacrodefn">Produce a note about real versus integer</span> <span class="cwebmacronumber">10.1.1.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::issue_problem_begin</span><span class="plain">(</span><span class="string">"*"</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">" %PNote that Inform's kinds 'number' and 'real number' are not "</span>
<span class="string">"interchangeable. A 'number' like 7 can be used where a 'real "</span>
<span class="string">"number' is expected - it becomes 7.000 - but not vice versa. "</span>
<span class="string">"Use 'R to the nearest whole number' if you want to make a "</span>
<span class="string">"conversion."</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="#SP10_1_1">&#167;10.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. (3) Context switching. </b>After those epic preliminaries, we finally do some typechecking.
</p>
<p class="inwebparagraph">The scheme here is that our expectations of <code class="display"><span class="extract">p</span></code> depend on the context, and
this is defined by some node higher in the current subtree than <code class="display"><span class="extract">p</span></code>, which
we will call <code class="display"><span class="extract">context</span></code>. Most of the time this is the parent of <code class="display"><span class="extract">p</span></code>, but
sometimes the grandparent or great-grandparent; and at the start of the
recursion, when no context has appeared yet, it will be null. In effect,
then, the tree we're checking contains its own instructions on how it
should be checked. For example, the subtree
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">CONDITION_CONTEXT_NT</span>
<span class="plain"> p</span>
</pre>
<p class="inwebparagraph">tells us that when we reach <code class="display"><span class="extract">p</span></code> it should be checked as a condition.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::typecheck_recursive_inner</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="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">context</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">consider_alternatives</span><span class="plain">) {</span>
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(3)"</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="identifier">node_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CONDITION_CONTEXT_NT</span><span class="plain">: </span>&lt;<span class="cwebmacro">Switch context</span> <span class="cwebmacronumber">11.1</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">RVALUE_CONTEXT_NT</span><span class="plain">: </span>&lt;<span class="cwebmacro">Switch context</span> <span class="cwebmacronumber">11.1</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">MATCHING_RVALUE_CONTEXT_NT</span><span class="plain">: </span>&lt;<span class="cwebmacro">Switch context to an rvalue matching a description</span> <span class="cwebmacronumber">11.5</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">SPECIFIC_RVALUE_CONTEXT_NT</span><span class="plain">: </span>&lt;<span class="cwebmacro">Switch context to an rvalue matching a value</span> <span class="cwebmacronumber">11.6</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">VOID_CONTEXT_NT</span><span class="plain">: </span>&lt;<span class="cwebmacro">Switch to a void context</span> <span class="cwebmacronumber">11.7</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">LVALUE_CONTEXT_NT</span><span class="plain">: </span>&lt;<span class="cwebmacro">Switch context to an lvalue</span> <span class="cwebmacronumber">11.2</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">LVALUE_TR_CONTEXT_NT</span><span class="plain">: </span>&lt;<span class="cwebmacro">Switch context to a table reference lvalue</span> <span class="cwebmacronumber">11.3</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">LVALUE_LOCAL_CONTEXT_NT</span><span class="plain">: </span>&lt;<span class="cwebmacro">Switch context to an existing local variable lvalue</span> <span class="cwebmacronumber">11.4</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">NEW_LOCAL_CONTEXT_NT</span><span class="plain">: </span>&lt;<span class="cwebmacro">Deal with a new local variable name</span> <span class="cwebmacronumber">11.8</span>&gt;<span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span>&lt;<span class="cwebmacro">Typecheck within current context</span> <span class="cwebmacronumber">11.9</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">; </span> <span class="comment">to prevent compiler warnings: unreachable in fact</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::typecheck_recursive_inner is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP11_1"></a><b>&#167;11.1. </b>When we find a node like <code class="display"><span class="extract">CONDITION_CONTEXT_NT</span></code>, that becomes the new context
and we move down to its only child.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">SWITCH_CONTEXT_AND_RECURSE</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) </span><span class="functiontext">Dash::typecheck_recursive</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">)</span>
</pre>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Switch context</span> <span class="cwebmacronumber">11.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">SWITCH_CONTEXT_AND_RECURSE</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a> (twice).</p>
<p class="inwebparagraph"><a id="SP11_2"></a><b>&#167;11.2. </b>Other context switches are essentially the same thing, plus a check that
the value meets some extra requirement. For example:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Switch context to an lvalue</span> <span class="cwebmacronumber">11.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="identifier">SWITCH_CONTEXT_AND_RECURSE</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="functiontext">ParseTreeUsage::is_lvalue</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Issue problem for not being an lvalue</span> <span class="cwebmacronumber">11.2.1</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11_3"></a><b>&#167;11.3. </b>More specifically:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Switch context to a table reference lvalue</span> <span class="cwebmacronumber">11.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="identifier">SWITCH_CONTEXT_AND_RECURSE</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::is</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, </span><span class="constant">TABLE_ENTRY_NT</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Issue problem for not being a table reference</span> <span class="cwebmacronumber">11.3.1</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11_4"></a><b>&#167;11.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Switch context to an existing local variable lvalue</span> <span class="cwebmacronumber">11.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="identifier">SWITCH_CONTEXT_AND_RECURSE</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::is</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, </span><span class="constant">LOCAL_VARIABLE_NT</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Issue problem for not being an existing local</span> <span class="cwebmacronumber">11.4.1</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11_5"></a><b>&#167;11.5. </b>Suppose we are matching the parameter of a phrase like this:
</p>
<blockquote>
<p>To inspect (D - an open door): ...</p>
</blockquote>
<p class="inwebparagraph">and typechecking the following invocation:
</p>
<blockquote>
<p>inspect the Marble Portal;</p>
</blockquote>
<p class="inwebparagraph">Then we would have <code class="display"><span class="extract">p</span></code> set to some value &mdash; here "the Marble Portal" &mdash;
and the <code class="display"><span class="extract">MATCHING_RVALUE_CONTEXT_NT</span></code> node would point to a description node
for open doors. We must see if <code class="display"><span class="extract">p</span></code> matches that. Any match can be at best at
the "sometimes" level. We can prove the Marble Portal is a door at compile
time, but we can't prove it's open until run-time.
</p>
<p class="inwebparagraph">Note that we switch context and recurse first, then make the supplementary
check afterwards, when we know the kinds at least must be right.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Switch context to an rvalue matching a description</span> <span class="cwebmacronumber">11.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="identifier">SWITCH_CONTEXT_AND_RECURSE</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">rv</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">)</span>
<span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext">Dash::worst_case</span><span class="plain">(</span><span class="identifier">rv</span><span class="plain">,</span>
<span class="functiontext">Dash::compatible_with_description</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">,</span>
<span class="identifier">ParseTree::get_token_to_be_parsed_against</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)));</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11_6"></a><b>&#167;11.6. </b>This is something else that wouldn't appear in a typical typechecker.
Here we are dealing with a phrase specification such as:
</p>
<blockquote>
<p>To attract (N - 10) things: ...</p>
</blockquote>
<p class="inwebparagraph">where the "N" argument will be accepted if and only if it's the value 10.
The fact that Inform allows this is further evidence of the slippery way
that natural language doesn't distinguish values from types; early designs
of Inform didn't allow it, but many people reported this as a bug.
</p>
<p class="inwebparagraph">Again we switch context and recurse first. We can't safely test pointer
values, such as texts, for equality at compile time &mdash; for one thing, we
don't know what text substitutions will then expand to &mdash; so the value
test only forces us towards never or always when the constants being
compared are word values.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Switch context to an rvalue matching a value</span> <span class="cwebmacronumber">11.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="identifier">SWITCH_CONTEXT_AND_RECURSE</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">rv</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Kinds::Behaviour::uses_pointer_values</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, </span><span class="constant">CONSTANT_NT</span><span class="plain">))) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">val</span><span class="plain"> = </span><span class="identifier">ParseTree::get_token_to_be_parsed_against</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="functiontext">Rvalues::compare_CONSTANT</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">)))</span>
&lt;<span class="cwebmacro">Issue problem for being the wrong rvalue</span> <span class="cwebmacronumber">11.6.1</span>&gt;<span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext">Dash::worst_case</span><span class="plain">(</span><span class="identifier">rv</span><span class="plain">, </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"dropping to sometimes level for value comparison\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11_7"></a><b>&#167;11.7. </b>I would ideally like to remove void contexts from Dash entirely, but was
forced to retain them by the popularity of the Hypothetical Questions
extension, which made use of the old undocumented <code class="display"><span class="extract">phrase</span></code> token.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Switch to a void context</span> <span class="cwebmacronumber">11.7</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="identifier">SWITCH_CONTEXT_AND_RECURSE</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">rv</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (!(</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, </span><span class="constant">PHRASE_TO_DECIDE_VALUE_NT</span><span class="plain">))) {</span>
&lt;<span class="cwebmacro">Issue problem for not being a phrase</span> <span class="cwebmacronumber">11.7.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11_2_1"></a><b>&#167;11.2.1. </b>A whole set of problem messages arise out of contextual failures:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem for not being an lvalue</span> <span class="cwebmacronumber">11.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</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_ValueAsStorageItem</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but '%2' is a value, not a place where a value is "</span>
<span class="string">"stored. "</span>
<span class="string">"%PFor example, if 'The tally is a number that varies.', then "</span>
<span class="string">"I can 'increment the tally', but I can't 'increment 37' - the "</span>
<span class="string">"number 37 is always what it is. Similarly, I can't 'increment "</span>
<span class="string">"the number of people'. Phrases like 'increment' work only on "</span>
<span class="string">"stored values, like values that vary, or table entries."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_2">&#167;11.2</a>.</p>
<p class="inwebparagraph"><a id="SP11_3_1"></a><b>&#167;11.3.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem for not being a table reference</span> <span class="cwebmacronumber">11.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</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_ValueAsTableReference</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but '%2' is a value, not a reference to an entry "</span>
<span class="string">"in a table."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_3">&#167;11.3</a>.</p>
<p class="inwebparagraph"><a id="SP11_4_1"></a><b>&#167;11.4.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem for not being an existing local</span> <span class="cwebmacronumber">11.4.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TEST_DASH_MODE</span><span class="plain">(</span><span class="constant">ISSUE_LOCAL_PROBLEMS_DMODE</span><span class="plain">)) {</span>
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</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="functiontext">Specifications::is_kind_like</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">))</span>
<span class="identifier">Problems::quote_text</span><span class="plain">(3, </span><span class="string">"a kind of value"</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="functiontext">Problems::quote_kind_of</span><span class="plain">(3, </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</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_ExistingVarNotFound</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the sentence %1, I was expecting that '%2' would be the "</span>
<span class="string">"name of a temporary value, but it turned out to be %3."</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">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_4">&#167;11.4</a>.</p>
<p class="inwebparagraph"><a id="SP11_6_1"></a><b>&#167;11.6.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem for being the wrong rvalue</span> <span class="cwebmacronumber">11.6.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">));</span>
<span class="functiontext">Problems::quote_spec</span><span class="plain">(3, </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_spec</span><span class="plain">(4, </span><span class="identifier">val</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_NotExactValueWanted</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the sentence %1, I was expecting that '%2' would be the specific "</span>
<span class="string">"value '%4'."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_6">&#167;11.6</a>.</p>
<p class="inwebparagraph"><a id="SP11_7_1"></a><b>&#167;11.7.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem for not being a phrase</span> <span class="cwebmacronumber">11.7.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</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">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the sentence %1, I was expecting that '%2' would be a phrase."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_7">&#167;11.7</a>.</p>
<p class="inwebparagraph"><a id="SP11_8"></a><b>&#167;11.8. New variables. </b>The following doesn't switch context and recurse down: there's nothing
to recurse down to, since all we have is a name for a new variable. Instead
we deal with that right away.
</p>
<p class="inwebparagraph">It might seem rather odd that the typechecker should be the part of Inform
which creates local variables. Surely that's a sign that the parsing went
wrong, so how did things get to this stage?
</p>
<p class="inwebparagraph">In a C-like language, where variables are predeclared, that would be true.
But in Inform, a phrase like:
</p>
<blockquote>
<p>let the monster be a random pterodactyl;</p>
</blockquote>
<p class="inwebparagraph">can be valid even where "the monster" is text not known to the S-parser
as yet &mdash; indeed, that's how local variables are made. It's the typechecker
which sorts this out, because only the typechecker can decide which of the
subtly different forms of "let" is being used.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Deal with a new local variable name</span> <span class="cwebmacronumber">11.8</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">ParseTree::get_kind_required_by_context</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">check</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">check</span><span class="plain">, </span><span class="identifier">AMBIGUITY_NT</span><span class="plain">)) </span><span class="identifier">check</span><span class="plain"> = </span><span class="identifier">check</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">LocalVariables::permit_as_new_local</span><span class="plain">(</span><span class="identifier">check</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kind_of_var_to_create</span><span class="plain">) *</span><span class="identifier">kind_of_var_to_create</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Issue a problem for an inappropriate variable name</span> <span class="cwebmacronumber">11.8.1</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11_8_1"></a><b>&#167;11.8.1. </b>This problem message is never normally seen using the definitions in the
Standard Rules because the definitions made there are such that other
problems appear first. So the only way to see this message is to declare an
unambiguous phrase with one of its tokens requiring a variable of a
species; and then to misuse that phrase.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem for an inappropriate variable name</span> <span class="cwebmacronumber">11.8.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</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="functiontext">Specifications::is_kind_like</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">))</span>
<span class="identifier">Problems::quote_text</span><span class="plain">(3, </span><span class="string">"a kind of value"</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="functiontext">Problems::quote_kind_of</span><span class="plain">(3, </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_KindOfVariable</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the sentence %1, I was expecting that '%2' would be a new "</span>
<span class="string">"variable name (to hold %4), but it turned out to be %3."</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="#SP11_8">&#167;11.8</a>.</p>
<p class="inwebparagraph"><a id="SP11_9"></a><b>&#167;11.9. (4) Typechecking within current context. </b>Everything else, then, passes through here, with the context now set either
to <code class="display"><span class="extract">NULL</span></code> (meaning no expectations) or to some ancestor of <code class="display"><span class="extract">p</span></code> in the parse
tree.
</p>
<p class="inwebparagraph">Level 4 forks rapidly into three branches: (4A), for ambiguous readings;
(4I), for single invocations; and (4S), for single readings other than
invocations. Here's the code which does the switching:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Typecheck within current context</span> <span class="cwebmacronumber">11.9</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_needed</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="identifier">condition_context</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">context</span><span class="plain">) {</span>
<span class="identifier">kind_needed</span><span class="plain"> = </span><span class="identifier">ParseTree::get_kind_required_by_context</span><span class="plain">(</span><span class="identifier">context</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">context</span><span class="plain">, </span><span class="constant">CONDITION_CONTEXT_NT</span><span class="plain">)) ||</span>
<span class="plain">(</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">context</span><span class="plain">, </span><span class="constant">LOGICAL_AND_NT</span><span class="plain">)) ||</span>
<span class="plain">(</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">context</span><span class="plain">, </span><span class="constant">LOGICAL_OR_NT</span><span class="plain">)) ||</span>
<span class="plain">(</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">context</span><span class="plain">, </span><span class="constant">LOGICAL_NOT_NT</span><span class="plain">)) ||</span>
<span class="plain">(</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">context</span><span class="plain">, </span><span class="constant">LOGICAL_TENSE_NT</span><span class="plain">)))</span>
<span class="identifier">condition_context</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4)"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">outcome</span><span class="plain"> = </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">consider_alternatives</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="identifier">next_alternative</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Resolve an ambiguous reading</span> <span class="cwebmacronumber">11.9.2</span>&gt;
<span class="reserved">else</span>
&lt;<span class="cwebmacro">Verify an unambiguous reading</span> <span class="cwebmacronumber">11.9.1</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">outcome</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1"></a><b>&#167;11.9.1. </b>For a phrase node, we pass the buck down to its invocation list. For an
invocation list, we pass the buck down to its invocation (which may or
may not be the first in a chain of alternatives), which means we end up
in (4I) either directly or via (4A). For everything else, it's (4S) for us.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Verify an unambiguous reading</span> <span class="cwebmacronumber">11.9.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="identifier">node_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">PHRASE_TO_DECIDE_VALUE_NT</span><span class="plain">:</span>
<span class="identifier">outcome</span><span class="plain"> = </span><span class="functiontext">Dash::typecheck_recursive</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, </span><span class="identifier">context</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="reserved">case</span><span class="plain"> </span><span class="constant">INVOCATION_LIST_NT</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="constant">INVOCATION_LIST_SAY_NT</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="identifier">AMBIGUITY_NT</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span>&lt;<span class="cwebmacro">Unknown found text occurs as a command</span> <span class="cwebmacronumber">11.9.1.3</span>&gt;<span class="plain">;</span>
<span class="constant">BEGIN_DASH_MODE</span><span class="plain">;</span>
<span class="identifier">DASH_MODE_INVL</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="identifier">outcome</span><span class="plain"> = </span><span class="functiontext">Dash::typecheck_recursive</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, </span><span class="identifier">context</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="constant">END_DASH_MODE</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">INVOCATION_NT</span><span class="plain">: </span>&lt;<span class="cwebmacro">Step (4I) Verify an invocation</span> <span class="cwebmacronumber">11.9.1.1</span>&gt;<span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span>&lt;<span class="cwebmacro">Step (4S) Verify anything else</span> <span class="cwebmacronumber">11.9.1.2</span>&gt;<span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9">&#167;11.9</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_2"></a><b>&#167;11.9.2. </b>(4A) Ambiguities.
Ambiguities presently consist of chains of invocation nodes listed in
the tree as alternatives.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Resolve an ambiguous reading</span> <span class="cwebmacronumber">11.9.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4A)"</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">list_of_possible_readings</span><span class="plain">[</span><span class="constant">MAX_INVOCATIONS_PER_PHRASE</span><span class="plain">];</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_of_possible_readings</span><span class="plain"> = 0;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_of_passed_readings</span><span class="plain"> = 0;</span>
&lt;<span class="cwebmacro">Step (4A.a) Set up the list of readings to test</span> <span class="cwebmacronumber">11.9.2.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Step (4A.b) Recurse Dash to try each reading in turn</span> <span class="cwebmacronumber">11.9.2.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::problems_have_been_issued</span><span class="plain">()) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_of_passed_readings</span><span class="plain"> &gt; 0) </span>&lt;<span class="cwebmacro">Step (4A.c) Preserve successful readings</span> <span class="cwebmacronumber">11.9.2.3</span>&gt;
<span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Step (4A.d) Give up with no readings possible</span> <span class="cwebmacronumber">11.9.2.4</span>&gt;<span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Ambiguity resolved to: $E"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9">&#167;11.9</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_2_1"></a><b>&#167;11.9.2.1. </b>Phrase definitions are kept in a linked list with a total ordering which
properly contains the partial ordering in which P_1&lt;= P_2 if they are
lexically identical and if each parameter of P_1 provably, at compile time,
also satisfies the requirements for the corresponding parameter of P_2.
They have already been lexically parsed in that order, so the list of
invocations (which will have accumulated during parsing) is also in that
same order. Now this is nearly the correct order for type-checking. But we
make one last adjustment: the phrase being compiled is moved to the back of
the list. This is to make recursion always the last thing checked, so that
later rules can override earlier ones but still make use of them.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4A.a) Set up the list of readings to test</span> <span class="cwebmacronumber">11.9.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4A.a)"</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">alt</span><span class="plain">;</span>
<span class="identifier">LOOP_THROUGH_ALTERNATIVES</span><span class="plain">(</span><span class="identifier">alt</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::is</span><span class="plain">(</span><span class="identifier">alt</span><span class="plain">, </span><span class="constant">INVOCATION_NT</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">ParseTree::get_phrase_invoked</span><span class="plain">(</span><span class="identifier">alt</span><span class="plain">) != </span><span class="identifier">phrase_being_compiled</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Add this reading to the list of test cases</span> <span class="cwebmacronumber">11.9.2.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">LOOP_THROUGH_ALTERNATIVES</span><span class="plain">(</span><span class="identifier">alt</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::is</span><span class="plain">(</span><span class="identifier">alt</span><span class="plain">, </span><span class="constant">INVOCATION_NT</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">ParseTree::get_phrase_invoked</span><span class="plain">(</span><span class="identifier">alt</span><span class="plain">) != </span><span class="identifier">phrase_being_compiled</span><span class="plain">)))</span>
&lt;<span class="cwebmacro">Add this reading to the list of test cases</span> <span class="cwebmacronumber">11.9.2.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Resolving %d possible readings:\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">no_of_possible_readings</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">no_of_possible_readings</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Possibility (P%d) $e\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">list_of_possible_readings</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_2">&#167;11.9.2</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_2_1_1"></a><b>&#167;11.9.2.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Add this reading to the list of test cases</span> <span class="cwebmacronumber">11.9.2.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_of_possible_readings</span><span class="plain"> &gt;= </span><span class="constant">MAX_INVOCATIONS_PER_PHRASE</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"overrun"</span><span class="plain">);</span>
<span class="identifier">list_of_possible_readings</span><span class="plain">[</span><span class="identifier">no_of_possible_readings</span><span class="plain">++] = </span><span class="identifier">alt</span><span class="plain">;</span>
<span class="functiontext">Dash::clear_flags</span><span class="plain">(</span><span class="identifier">alt</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_2_1">&#167;11.9.2.1</a> (twice).</p>
<p class="inwebparagraph"><a id="SP11_9_2_2"></a><b>&#167;11.9.2.2. </b>Now we work through the list of tests. We must produce at least one reading
passing at least at the "sometimes" level marked by the <code class="display"><span class="extract">UNPROVEN_DASHFLAG</span></code>, or
else the whole specification fails its match. The first proven match stops our
work, since we can never need lower-priority interpretations.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4A.b) Recurse Dash to try each reading in turn</span> <span class="cwebmacronumber">11.9.2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4A.b)"</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">ref</span><span class="plain"> = 0; </span><span class="identifier">ref</span><span class="plain">&lt;</span><span class="identifier">no_of_possible_readings</span><span class="plain">; </span><span class="identifier">ref</span><span class="plain">++) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain"> = </span><span class="identifier">list_of_possible_readings</span><span class="plain">[</span><span class="identifier">ref</span><span class="plain">];</span>
&lt;<span class="cwebmacro">Test the current reading and set its results flags accordingly</span> <span class="cwebmacronumber">11.9.2.2.1</span>&gt;<span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(P%d) %s: $e\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">ref</span><span class="plain">, </span><span class="functiontext">Dash::verdict_to_text</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">), </span><span class="identifier">inv</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">PASSED_DASHFLAG</span><span class="plain">)) {</span>
<span class="identifier">no_of_passed_readings</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">UNPROVEN_DASHFLAG</span><span class="plain">) == </span><span class="identifier">FALSE</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="functiontext">Dash::problems_have_been_issued</span><span class="plain">()) </span><span class="reserved">break</span><span class="plain">; </span> <span class="comment">to prevent duplication of problem messages</span>
<span class="plain">}</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"List %s: "</span><span class="plain">, (</span><span class="identifier">no_of_passed_readings</span><span class="plain"> &gt; 0)?</span><span class="string">"passed"</span><span class="plain">:</span><span class="string">"failed"</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">no_of_possible_readings</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain"> = </span><span class="identifier">list_of_possible_readings</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">];</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"%s "</span><span class="plain">, </span><span class="functiontext">Dash::quick_verdict_to_text</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"|\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_2">&#167;11.9.2</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_2_2_1"></a><b>&#167;11.9.2.2.1. </b>We tell Dash to run silently unless grosser-than-gross problems arise, and
also tell it to check the reading with no alternatives considered. (If we
let it consider alternatives, that would be circular: we'd end up here
again, and so on forever.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Test the current reading and set its results flags accordingly</span> <span class="cwebmacronumber">11.9.2.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(P%d) Trying &lt;%W&gt;: $e\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">ref</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">), </span><span class="identifier">inv</span><span class="plain">);</span>
<span class="constant">BEGIN_DASH_MODE</span><span class="plain">;</span>
<span class="identifier">DASH_MODE_EXIT</span><span class="plain">(</span><span class="constant">ISSUE_PROBLEMS_DMODE</span><span class="plain">);</span>
<span class="comment">DASH_MODE_EXIT(ISSUE_INTERESTING_PROBLEMS_DMODE);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext">Dash::typecheck_recursive</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">context</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="constant">END_DASH_MODE</span><span class="plain">;</span>
<span class="functiontext">Dash::set_flag</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">TESTED_DASHFLAG</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rv</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) {</span>
<span class="functiontext">Dash::set_flag</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">PASSED_DASHFLAG</span><span class="plain">);</span>
<span class="identifier">outcome</span><span class="plain"> = </span><span class="functiontext">Dash::worst_case</span><span class="plain">(</span><span class="identifier">outcome</span><span class="plain">, </span><span class="identifier">rv</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_2_2">&#167;11.9.2.2</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_2_3"></a><b>&#167;11.9.2.3. </b>This is the happy ending, in which the list can probably be passed, though
there are still a handful of pitfalls.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4A.c) Preserve successful readings</span> <span class="cwebmacronumber">11.9.2.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4A.c)"</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Step (4A.c.1) Winnow the reading list down to the survivors</span> <span class="cwebmacronumber">11.9.2.3.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Step (4A.c.2) Infer the kind of any requested local variable</span> <span class="cwebmacronumber">11.9.2.3.2</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_2">&#167;11.9.2</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_2_3_1"></a><b>&#167;11.9.2.3.1. </b>To recap, after checking through the possible readings we have something
like this as the result:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">f ? f g ? ? p - - -</span>
</pre>
<p class="inwebparagraph">We can now throw away the <code class="display"><span class="extract">f</span></code>, <code class="display"><span class="extract">g</span></code> and <code class="display"><span class="extract">-</span></code> readings &mdash; failed, grossly failed,
or never reached &mdash; to leave just those which will be compiled:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">? ? ? p</span>
</pre>
<p class="inwebparagraph">If compiled this will result in run-time code to check if the arguments
allow the first invocation and run it if so; then the second; then the third;
and, if those three fell through, run the fourth invocation without further
checking.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4A.c.1) Winnow the reading list down to the survivors</span> <span class="cwebmacronumber">11.9.2.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4A.c.1)"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">invocational</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="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">Dash_ambiguity_list</span><span class="plain">, </span><span class="identifier">AMBIGUITY_NT</span><span class="plain">)) </span><span class="identifier">invocational</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Winnow %s from $T\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="plain">(</span><span class="identifier">invocational</span><span class="plain">)?</span><span class="string">"invocationally"</span><span class="plain">:</span><span class="string">"regularly"</span><span class="plain">, </span><span class="identifier">Dash_ambiguity_list</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">invocational</span><span class="plain">) </span><span class="identifier">Dash_ambiguity_list</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">last_survivor</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="reserved">int</span><span class="plain"> </span><span class="identifier">ref</span><span class="plain"> = 0; </span><span class="identifier">ref</span><span class="plain">&lt;</span><span class="identifier">no_of_possible_readings</span><span class="plain">; </span><span class="identifier">ref</span><span class="plain">++) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain"> = </span><span class="identifier">list_of_possible_readings</span><span class="plain">[</span><span class="identifier">ref</span><span class="plain">];</span>
<span class="identifier">inv</span><span class="plain">-&gt;</span><span class="identifier">next_alternative</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">PASSED_DASHFLAG</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">invocational</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">last_survivor</span><span class="plain">) </span><span class="identifier">last_survivor</span><span class="plain">-&gt;</span><span class="identifier">next_alternative</span><span class="plain"> = </span><span class="identifier">inv</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">Dash_ambiguity_list</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">inv</span><span class="plain">;</span>
<span class="identifier">last_survivor</span><span class="plain"> = </span><span class="identifier">inv</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">link</span><span class="plain"> = </span><span class="identifier">Dash_ambiguity_list</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="identifier">ParseTree::copy</span><span class="plain">(</span><span class="identifier">Dash_ambiguity_list</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">);</span>
<span class="identifier">Dash_ambiguity_list</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">link</span><span class="plain">;</span>
<span class="identifier">Dash_ambiguity_list</span><span class="plain">-&gt;</span><span class="identifier">next_alternative</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="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">invocational</span><span class="plain">) {</span>
<span class="identifier">p</span><span class="plain"> = </span><span class="identifier">Dash_ambiguity_list</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">nfi</span><span class="plain"> = -1, </span><span class="identifier">number_ambiguity</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain">;</span>
<span class="identifier">LOOP_THROUGH_ALTERNATIVES</span><span class="plain">(</span><span class="identifier">inv</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::is</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">INVOCATION_NT</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">nti</span><span class="plain"> = </span><span class="functiontext">Invocations::get_no_tokens</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nfi</span><span class="plain"> == -1) </span><span class="identifier">nfi</span><span class="plain"> = </span><span class="identifier">nti</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nfi</span><span class="plain"> != </span><span class="identifier">nti</span><span class="plain">) </span><span class="identifier">number_ambiguity</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">number_ambiguity</span><span class="plain">) </span>&lt;<span class="cwebmacro">Issue the number ambiguity problem message</span> <span class="cwebmacronumber">11.9.2.3.1.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"After winnowing, CS is $T\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_2_3">&#167;11.9.2.3</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_2_3_1_1"></a><b>&#167;11.9.2.3.1.1. </b>This is another sort of error which couldn't happen with a conventional
programming language &mdash; in C, for instance, it's syntactically obvious
how many arguments a function call has, because the brackets and commas
are unambiguous. But in Inform, there are no reserved tokens of syntax
acting like that. So we could easily have two accepted invocations in the
list which have different numbers of arguments to each other, and there's
no way safely to adjudicate that at run-time.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue the number ambiguity problem message</span> <span class="cwebmacronumber">11.9.2.3.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</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="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_UnequalValueAmbiguity</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The phrase %1 is ambiguous in a way that I can't disentangle. "</span>
<span class="string">"It has more than one plausible interpretation, such that it "</span>
<span class="string">"would only be possible to tell which is valid at run-time: "</span>
<span class="string">"ordinarily that would be fine, but because the different "</span>
<span class="string">"interpretations are so different (and involve different "</span>
<span class="string">"numbers of values being used) there's no good way to cope. "</span>
<span class="string">"Try rewording one of the phrases which caused this clash: "</span>
<span class="string">"there's a good chance the problem will then go away."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_2_3_1">&#167;11.9.2.3.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_2_3_2"></a><b>&#167;11.9.2.3.2. </b>If an invocation passes, and asks to create a local variable, we need
to mark the tree accordingly. If there's just one invocation then (4I)
handles this, but if there's ambiguity, we handle it here, and only
for the surviving nodes.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4A.c.2) Infer the kind of any requested local variable</span> <span class="cwebmacronumber">11.9.2.3.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4A.c.2)"</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain">;</span>
<span class="identifier">LOOP_THROUGH_ALTERNATIVES</span><span class="plain">(</span><span class="identifier">inv</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::is</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">INVOCATION_NT</span><span class="plain">))</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::set_up_any_local_required</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">) == </span><span class="identifier">NEVER_MATCH</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_2_3">&#167;11.9.2.3</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_2_4"></a><b>&#167;11.9.2.4. </b>And this is the unhappy ending:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4A.d) Give up with no readings possible</span> <span class="cwebmacronumber">11.9.2.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4A.d)"</span><span class="plain">);</span>
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Invocations::length_of_list</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) == 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"All possibilities failed: issuing problem\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Dash::failed</span><span class="plain">(</span><span class="identifier">list_of_possible_readings</span><span class="plain">, </span><span class="identifier">no_of_possible_readings</span><span class="plain">,</span>
<span class="identifier">context</span><span class="plain">, </span><span class="identifier">kind_needed</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_2">&#167;11.9.2</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1"></a><b>&#167;11.9.1.1. </b>(4I) Invocations.
Invocations are the hardest nodes to check, but here at least we can forget
all about the ambiguities arising from multiple possibilities, and look at
just a single one.
</p>
<p class="inwebparagraph">In the event of an interesting problem message, we mark an invocation as being
interestingly problematic, but we keep going, since other invocations might be
better. Only if everything fails will we retrace our steps and actually throw
the problem.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I) Verify an invocation</span> <span class="cwebmacronumber">11.9.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I)"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_gross_problems_thrown_before</span><span class="plain"> = </span><span class="identifier">no_gross_problems_thrown</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_interesting_problems_thrown_before</span><span class="plain"> = </span><span class="identifier">no_interesting_problems_thrown</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">qualified</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="functiontext">Phrases::Parser::parse_within_inv</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">);</span>
<span class="functiontext">Dash::set_flag</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">TESTED_DASHFLAG</span><span class="plain">);</span>
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain"> = </span><span class="identifier">ParseTree::get_phrase_invoked</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ph</span><span class="plain">) {</span>
<span class="identifier">ParseTree::set_kind_resulting</span><span class="plain">(</span><span class="identifier">inv</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">-</span><span class="element">&gt;type_data</span><span class="plain">)));</span>
<span class="comment">are the arguments of the right kind?</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) </span>&lt;<span class="cwebmacro">Step (4I.a) Take care of arithmetic phrases</span> <span class="cwebmacronumber">11.9.1.1.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) </span>&lt;<span class="cwebmacro">Step (4I.b) Take care of non-arithmetic phrases</span> <span class="cwebmacronumber">11.9.1.1.3</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) </span>&lt;<span class="cwebmacro">Step (4I.c) Match type templates in the argument specifications</span> <span class="cwebmacronumber">11.9.1.1.4</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) </span>&lt;<span class="cwebmacro">Step (4I.d) Match kinds in assignment phrases</span> <span class="cwebmacronumber">11.9.1.1.5</span>&gt;<span class="plain">;</span>
<span class="comment">if this evaluates something, is it a value of the right kind?</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) </span>&lt;<span class="cwebmacro">Step (4I.e) Check kind of value returned</span> <span class="cwebmacronumber">11.9.1.1.6</span>&gt;<span class="plain">;</span>
<span class="comment">are there any special rules about invoking this phrase?</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) </span>&lt;<span class="cwebmacro">Step (4I.f) Check any phrase options</span> <span class="cwebmacronumber">11.9.1.1.7</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) </span>&lt;<span class="cwebmacro">Step (4I.g) Worry about self in say property of</span> <span class="cwebmacronumber">11.9.1.1.8</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) </span>&lt;<span class="cwebmacro">Step (4I.h) Worry about using a phrase outside of the control structure it belongs to</span> <span class="cwebmacronumber">11.9.1.1.9</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) </span>&lt;<span class="cwebmacro">Step (4I.i) Disallow any phrases which are now deprecated</span> <span class="cwebmacronumber">11.9.1.1.10</span>&gt;<span class="plain">;</span>
<span class="comment">should we mark to create a let variable here?</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) &amp;&amp; (</span><span class="identifier">consider_alternatives</span><span class="plain">))</span>
<span class="identifier">outcome</span><span class="plain"> = </span><span class="functiontext">Dash::worst_case</span><span class="plain">(</span><span class="identifier">outcome</span><span class="plain">, </span><span class="functiontext">Dash::set_up_any_local_required</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="comment">the outcome is now definitely known</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">outcome</span><span class="plain"> == </span><span class="identifier">NEVER_MATCH</span><span class="plain">) </span>&lt;<span class="cwebmacro">Step (4I.j) Cope with failure</span> <span class="cwebmacronumber">11.9.1.1.11</span>&gt;
<span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Step (4I.k) Cope with success</span> <span class="cwebmacronumber">11.9.1.1.12</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1">&#167;11.9.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_1"></a><b>&#167;11.9.1.1.1. </b>Most problem messages issued by (4I) will be of a sort called "interesting",
and will use the following macro.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">THIS_IS_AN_INTERESTING_PROBLEM</span>
<span class="identifier">outcome</span><span class="plain"> = </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="identifier">no_interesting_problems_thrown</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TEST_DASH_MODE</span><span class="plain">(</span><span class="constant">ISSUE_INTERESTING_PROBLEMS_DMODE</span><span class="plain">))</span>
</pre>
<p class="inwebparagraph"><a id="SP11_9_1_1_2"></a><b>&#167;11.9.1.1.2. </b>"Polymorphic" here means that the phrase (i) produces a value, and (ii) that
the kind of this value depends on the kinds of its arguments. Inform supports
only a few polymorphic phrases, all clearly declared as such in the Standard
Rules, and they come in two sorts: those marked with a "polymorphism exception",
and those marked as "arithmetic operations".
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I.a) Take care of arithmetic phrases</span> <span class="cwebmacronumber">11.9.1.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.a)"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Phrases::TypeData::arithmetic_operation</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">) == </span><span class="identifier">TOTAL_OPERATION</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Step (4I.a.1) "Total P of O" has kind the kind of P</span> <span class="cwebmacronumber">11.9.1.1.2.1</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Phrases::TypeData::is_arithmetic_phrase</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">)) </span>&lt;<span class="cwebmacro">Step (4I.a.2) Dimension-check arithmetic phrases</span> <span class="cwebmacronumber">11.9.1.1.2.2</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1">&#167;11.9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_2_1"></a><b>&#167;11.9.1.1.2.1. </b>For instance, the kind of "total carrying capacity of people in the Dining
Room" is a number, because the kind of the property "carrying capacity" is
"number".
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I.a.1) "Total P of O" has kind the kind of P</span> <span class="cwebmacronumber">11.9.1.1.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.a.1)"</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="functiontext">Invocations::get_token_as_parsed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, 0);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext">Dash::typecheck_recursive</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">NULL</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="identifier">rv</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Rvalues::is_CONSTANT_construction</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">CON_property</span><span class="plain">))) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_property</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="functiontext">Properties::is_value_property</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">))</span>
<span class="identifier">ParseTree::set_kind_resulting</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="functiontext">Properties::Valued::kind</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">));</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="constant">THIS_IS_AN_INTERESTING_PROBLEM</span><span class="plain"> {</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TotalEitherOr</span><span class="plain">),</span>
<span class="string">"this seems to be an attempt to total up an either/or property"</span><span class="plain">,</span>
<span class="string">"and by definition such a property has nothing to total."</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Fail the invocation for totalling something other than a property</span> <span class="cwebmacronumber">11.9.1.1.2.1.1</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1_2">&#167;11.9.1.1.2</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_2_1_1"></a><b>&#167;11.9.1.1.2.1.1. </b>The problem message here is to help what turns out to be quite a popular
mistake. (Perhaps we should simply implement column-totalling and be done
with it.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Fail the invocation for totalling something other than a property</span> <span class="cwebmacronumber">11.9.1.1.2.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.a.1) failed as nonproperty"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">ParseTree::get_kind_of_value</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">)) == </span><span class="identifier">CON_table_column</span><span class="plain">) {</span>
<span class="constant">THIS_IS_AN_INTERESTING_PROBLEM</span><span class="plain"> {</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TotalTableColumn</span><span class="plain">),</span>
<span class="string">"this seems to be an attempt to total up the column of a table"</span><span class="plain">,</span>
<span class="string">"whereas it's only legal to use 'total' for properties."</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">outcome</span><span class="plain"> = </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1_2_1">&#167;11.9.1.1.2.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_2_2"></a><b>&#167;11.9.1.1.2.2. </b>For instance, the following blocks an attempt to add a number to a text.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I.a.2) Dimension-check arithmetic phrases</span> <span class="cwebmacronumber">11.9.1.1.2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.a.2)"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">op_number</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">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Arithmetic operation &lt;op-%d&gt;\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">op_number</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain">, *</span><span class="identifier">R</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_wanted</span><span class="plain">, *</span><span class="identifier">left_kind</span><span class="plain">, *</span><span class="identifier">right_kind</span><span class="plain">, *</span><span class="identifier">kind_produced</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Work out the kinds of the operands, and what we want, and what we get</span> <span class="cwebmacronumber">11.9.1.1.2.2.1</span>&gt;<span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"$u (~) $u = $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">left_kind</span><span class="plain">, </span><span class="identifier">right_kind</span><span class="plain">, </span><span class="identifier">kind_produced</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kind_produced</span><span class="plain">) </span><span class="identifier">ParseTree::set_kind_resulting</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">kind_produced</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Fail the invocation for a dimensional problem</span> <span class="cwebmacronumber">11.9.1.1.2.2.2</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1_2">&#167;11.9.1.1.2</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_2_2_1"></a><b>&#167;11.9.1.1.2.2.1. </b>For the way this is actually worked out, see the section on "Dimensions".
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Work out the kinds of the operands, and what we want, and what we get</span> <span class="cwebmacronumber">11.9.1.1.2.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">L</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, 0);</span>
<span class="identifier">left_kind</span><span class="plain"> = </span><span class="functiontext">Dash::fix_arithmetic_operand</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Dimensions::arithmetic_op_is_unary</span><span class="plain">(</span><span class="identifier">op_number</span><span class="plain">)) {</span>
<span class="identifier">R</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">right_kind</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">R</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, 1);</span>
<span class="identifier">right_kind</span><span class="plain"> = </span><span class="functiontext">Dash::fix_arithmetic_operand</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (((</span><span class="identifier">left_kind</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Behaviour::is_quasinumerical</span><span class="plain">(</span><span class="identifier">left_kind</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) ||</span>
<span class="plain">((</span><span class="identifier">right_kind</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Behaviour::is_quasinumerical</span><span class="plain">(</span><span class="identifier">right_kind</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)))</span>
<span class="identifier">kind_produced</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">else</span>
<span class="identifier">kind_produced</span><span class="plain"> = </span><span class="identifier">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">left_kind</span><span class="plain">, </span><span class="identifier">right_kind</span><span class="plain">, </span><span class="identifier">op_number</span><span class="plain">);</span>
<span class="identifier">kind_wanted</span><span class="plain"> = </span><span class="identifier">kind_needed</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1_2_2">&#167;11.9.1.1.2.2</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_2_2_2"></a><b>&#167;11.9.1.1.2.2.2. </b>Note that "value" &mdash; the vaguest kind of all &mdash; might come up here as
a result of some problem evaluating one of the operands, which has already been
reported in a problem message; so we only issue this problem message when
L and R are more definite.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Fail the invocation for a dimensional problem</span> <span class="cwebmacronumber">11.9.1.1.2.2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">left_kind</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">left_kind</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">right_kind</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">right_kind</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="constant">THIS_IS_AN_INTERESTING_PROBLEM</span><span class="plain"> {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"So the inv subtree is:\</span><span class="plain">n</span><span class="string">$T\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">);</span>
<span class="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_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">));</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(3, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">));</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">left_kind</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(5, </span><span class="identifier">right_kind</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">op_number</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PLUS_OPERATION</span><span class="plain">: </span><span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"adding"</span><span class="plain">); </span><span class="identifier">Problems::quote_text</span><span class="plain">(7, </span><span class="string">"to"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">MINUS_OPERATION</span><span class="plain">: </span><span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"subtracting"</span><span class="plain">); </span><span class="identifier">Problems::quote_text</span><span class="plain">(7, </span><span class="string">"from"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TIMES_OPERATION</span><span class="plain">: </span><span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"multiplying"</span><span class="plain">); </span><span class="identifier">Problems::quote_text</span><span class="plain">(7, </span><span class="string">"by"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">DIVIDE_OPERATION</span><span class="plain">:</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">REMAINDER_OPERATION</span><span class="plain">: </span><span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"dividing"</span><span class="plain">); </span><span class="identifier">Problems::quote_text</span><span class="plain">(7, </span><span class="string">"by"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">APPROXIMATION_OPERATION</span><span class="plain">: </span><span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"rounding"</span><span class="plain">); </span><span class="identifier">Problems::quote_text</span><span class="plain">(7, </span><span class="string">"to"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</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_BadArithmetic</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but that seems to involve %6 %4 ('%2') %7 %5 ('%3'), "</span>
<span class="string">"which is not good arithmetic."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">outcome</span><span class="plain"> = </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1_2_2">&#167;11.9.1.1.2.2</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_3"></a><b>&#167;11.9.1.1.3. </b>This is the general case: almost all phrases fall into this category,
including all phrases created outside the Standard Rules.
</p>
<p class="inwebparagraph">The deal is simply that every argument must match its specification. For
instance, if <code class="display"><span class="extract">inv</span></code> is an invocation of this phrase:
</p>
<blockquote>
<p>To truncate (L - a list of values) to (N - a number) entries: ...</p>
</blockquote>
<p class="inwebparagraph">...then token 0 must match "list of values", and token 1 must match "number".
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I.b) Take care of non-arithmetic phrases</span> <span class="cwebmacronumber">11.9.1.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Phrases::TypeData::is_arithmetic_phrase</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.b)"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">exit_at_once</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="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="functiontext">Invocations::get_no_tokens</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(4I.b) trying argument %d (prior to this, best possible: %d)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">i</span><span class="plain">, </span><span class="identifier">outcome</span><span class="plain">);</span>
<span class="functiontext">Invocations::set_token_check_to_do</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Type-check a single token from the list</span> <span class="cwebmacronumber">11.9.1.1.3.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">exit_at_once</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(4I.b) argument type matching %s\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="plain">(</span><span class="identifier">outcome</span><span class="plain">==</span><span class="identifier">NEVER_MATCH</span><span class="plain">)?</span><span class="string">"failed"</span><span class="plain">:</span><span class="string">"passed"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1">&#167;11.9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_3_1"></a><b>&#167;11.9.1.1.3.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Type-check a single token from the list</span> <span class="cwebmacronumber">11.9.1.1.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">ith_spec</span><span class="plain"> = </span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.token_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.to_match</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.token_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.construct</span><span class="plain"> == </span><span class="constant">KIND_NAME_PT_CONSTRUCT</span><span class="plain">) &amp;&amp; (</span><span class="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Cautiously reparse this as a name of a kind of value</span> <span class="cwebmacronumber">11.9.1.1.3.1.1</span>&gt;
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">save_kcm</span><span class="plain"> = </span><span class="identifier">kind_checker_mode</span><span class="plain">;</span>
<span class="identifier">kind_checker_mode</span><span class="plain"> = </span><span class="identifier">MATCH_KIND_VARIABLES_AS_UNIVERSAL</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">create</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="constant">BEGIN_DASH_MODE</span><span class="plain">;</span>
<span class="identifier">DASH_MODE_EXIT</span><span class="plain">(</span><span class="constant">ISSUE_PROBLEMS_DMODE</span><span class="plain">);</span>
<span class="identifier">DASH_MODE_CREATE</span><span class="plain">(&amp;</span><span class="identifier">create</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext">Dash::typecheck_recursive</span><span class="plain">(</span><span class="functiontext">Invocations::get_token</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">), </span><span class="identifier">context</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="constant">END_DASH_MODE</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">rv</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">:</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(4I.b) on %W failed at token %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</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">outcome</span><span class="plain"> = </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::problems_have_been_issued</span><span class="plain">()) </span><span class="identifier">exit_at_once</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="reserved">case</span><span class="plain"> </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">:</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(4I.b) on %W qualified at token %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</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="functiontext">Invocations::set_token_check_to_do</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">ith_spec</span><span class="plain">);</span>
<span class="identifier">qualified</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="identifier">kind_checker_mode</span><span class="plain"> = </span><span class="identifier">save_kcm</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">create</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Routines::Compile::disallow_let</span><span class="plain">()) &amp;&amp; (</span><span class="functiontext">Phrases::TypeData::is_a_let_assignment</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">))) {</span>
<span class="constant">THIS_IS_AN_INTERESTING_PROBLEM</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="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_LetCreatedInIf</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but when a temporary value is created "</span>
<span class="string">"inside an 'if ..., ...' or an 'otherwise ...', it only "</span>
<span class="string">"lasts until that line is complete - which means it "</span>
<span class="string">"can never be used for anything, because it goes away "</span>
<span class="string">"as soon as created. To make something more durable, "</span>
<span class="string">"create it before the 'if' or 'otherwise'."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="functiontext">Invocations::set_token_variable_kind</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">create</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="#SP11_9_1_1_3">&#167;11.9.1.1.3</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_3_1_1"></a><b>&#167;11.9.1.1.3.1.1. </b>The following is a delicate manoeuvre, but luckily it takes action only very
rarely and in very specific circumstances. We allow a very limited use
of second-order logic in using the name of a kind as if it were a value,
even though Inform is really not set up for this. The point is to allow:
</p>
<blockquote>
<p>let (name - nonexisting variable) be (K - name of kind of word value);</p>
</blockquote>
<p class="inwebparagraph">where the "K" parameter would match [1] but not [2], [3] or [4] from:
</p>
<blockquote>
<p>[1] let X be a number;</p>
</blockquote>
<blockquote>
<p>[2] let X be text;</p>
</blockquote>
<blockquote>
<p>[3] let X be 21;</p>
</blockquote>
<blockquote>
<p>[4] let X be \{1, 2, 3\};</p>
</blockquote>
<p class="inwebparagraph">What all of this has to do with being <code class="display"><span class="extract">UNKNOWN_NT</span></code> is that text parsed in the
expectation of a value will usually not recognise something like "a list
of numbers", so that would be here as <code class="display"><span class="extract">UNKNOWN_NT</span></code>. We take the otherwise
unheard-of measure of reparsing the text, but we only impose the result
if the match can definitely be made successfully.
</p>
<p class="inwebparagraph">We have to be very careful to take action only on [5] and not [6]:
</p>
<blockquote>
<p>[5] let L be a list of scenes;</p>
</blockquote>
<blockquote>
<p>[6] let L be the list of scenes;</p>
</blockquote>
<p class="inwebparagraph">[5] creates L as an empty list, whereas [6] creates it as the list made up
of all scenes. We can tell these apart since [6] will have a valid phrase
in <code class="display"><span class="extract">ith_token</span></code>, an invocation of "the list of K", whereas [5] won't.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Cautiously reparse this as a name of a kind of value</span> <span class="cwebmacronumber">11.9.1.1.3.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">outcome</span><span class="plain"> = </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">ith_token</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token_as_parsed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(4I.b) thinking about reparsing: $P\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">ith_token</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">warned_already</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">ith_token</span><span class="plain">, </span><span class="identifier">AMBIGUITY_NT</span><span class="plain">)) </span><span class="identifier">ith_token</span><span class="plain"> = </span><span class="identifier">ith_token</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">ith_token</span><span class="plain">, </span><span class="constant">UNKNOWN_NT</span><span class="plain">)) ||</span>
<span class="plain">(</span><span class="functiontext">Specifications::is_description</span><span class="plain">(</span><span class="identifier">ith_token</span><span class="plain">)) ||</span>
<span class="plain">(</span><span class="functiontext">Rvalues::is_CONSTANT_construction</span><span class="plain">(</span><span class="identifier">ith_token</span><span class="plain">, </span><span class="identifier">CON_property</span><span class="plain">)) ||</span>
<span class="plain">(</span><span class="functiontext">Specifications::is_kind_like</span><span class="plain">(</span><span class="identifier">ith_token</span><span class="plain">)) ||</span>
<span class="plain">((</span><span class="functiontext">Phrases::TypeData::is_a_let_assignment</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">ith_token</span><span class="plain">, </span><span class="constant">PHRASE_TO_DECIDE_VALUE_NT</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="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">ith_token</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">reparsed</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">type</span><span class="plain">-</span><span class="identifier">expression</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) </span><span class="identifier">reparsed</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Specifications::is_kind_like</span><span class="plain">(</span><span class="identifier">reparsed</span><span class="plain">))</span>
<span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">reparsed</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) &amp;&amp; (&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">kind</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">))) </span><span class="identifier">K</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">if</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="reserved">if</span><span class="plain"> ((&lt;</span><span class="identifier">value</span><span class="plain">-</span><span class="reserved">property</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Properties::Valued::coincides_with_kind</span><span class="plain">(&lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;)))</span>
<span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Properties::Valued::kind</span><span class="plain">(&lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;);</span>
<span class="plain">}</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(4I.b) reparsed as: $u (vs spec $P)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">ith_spec</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Specifications::is_kind_like</span><span class="plain">(</span><span class="identifier">ith_spec</span><span class="plain">))) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">ikind</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">ith_spec</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">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">ikind</span><span class="plain">) == </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(4I.b) allows name-of token: $P\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">reparsed</span><span class="plain">);</span>
<span class="functiontext">Invocations::set_token_as_parsed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">ParseTree::duplicate</span><span class="plain">(</span><span class="identifier">reparsed</span><span class="plain">));</span>
<span class="identifier">outcome</span><span class="plain"> = </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain"> {</span>
<span class="identifier">warned_already</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="identifier">ikind</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_NameOfKindMismatch</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but although '%2' is the name of a kind, "</span>
<span class="string">"it isn't the name of a kind of %3, which this phrase needs."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="constant">THIS_IS_A_GROSSER_THAN_GROSS_PROBLEM</span><span class="plain"> {</span>
<span class="identifier">warned_already</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="identifier">ikind</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_BadLocalKOV</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but although '%2' is the name of a kind, "</span>
<span class="string">"it isn't a definite kind and is instead a general "</span>
<span class="string">"description which might apply to many different kinds. "</span>
<span class="string">"(For example, 'let R be a relation' is vague because it doesn't "</span>
<span class="string">"make clear what R will relate - 'let R be a relation of numbers' "</span>
<span class="string">"would be fine.)"</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">ith_token</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token_as_parsed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((!</span><span class="functiontext">Specifications::is_kind_like</span><span class="plain">(</span><span class="identifier">ith_token</span><span class="plain">)) &amp;&amp; (</span><span class="identifier">warned_already</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain"> {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">ith_token</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_NameOfKindIsnt</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but although '%2' does have a meaning, "</span>
<span class="string">"it isn't the name of a kind, which this phrase needs."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</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="#SP11_9_1_1_3_1">&#167;11.9.1.1.3.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_4"></a><b>&#167;11.9.1.1.4. </b>For templates and the meaning of <code class="display"><span class="extract">kind_checker_mode</span></code>, see the section
on "Kind Checking". But basically this handles the matching of an invocation
against a definition like:
</p>
<blockquote>
<p>To remove (N - value of kind K) from (L - list of Ks): ...</p>
</blockquote>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I.c) Match type templates in the argument specifications</span> <span class="cwebmacronumber">11.9.1.1.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.c)"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">exit_at_once</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">kind_variable_declaration</span><span class="plain"> *</span><span class="identifier">kvd_marker</span><span class="plain"> = </span><span class="identifier">LAST_OBJECT</span><span class="plain">(</span><span class="identifier">kind_variable_declaration</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Phrases::TypeData::contains_variables</span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data</span><span class="plain">))) {</span>
<span class="identifier">kind_variable_declaration</span><span class="plain"> *</span><span class="identifier">save_most_recent_interpretation</span><span class="plain"> = </span><span class="identifier">most_recent_interpretation</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pass</span><span class="plain">, </span><span class="identifier">save_kcm</span><span class="plain"> = </span><span class="identifier">kind_checker_mode</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pass</span><span class="plain"> = 1; </span><span class="identifier">pass</span><span class="plain"> &lt;= 2; </span><span class="identifier">pass</span><span class="plain">++) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(4I.c) prototype check pass %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">pass</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="identifier">MATCHING_DA</span><span class="plain">)) </span><span class="identifier">Kinds::Compare::show_variables</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pass</span><span class="plain"> == 1) </span><span class="identifier">kind_checker_mode</span><span class="plain"> = </span><span class="identifier">MATCH_KIND_VARIABLES_INFERRING_VALUES</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">kind_checker_mode</span><span class="plain"> = </span><span class="identifier">MATCH_KIND_VARIABLES_AS_VALUES</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="functiontext">Invocations::get_no_tokens</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.token_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.token_kind</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.token_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.construct</span><span class="plain"> != </span><span class="constant">NEW_LOCAL_PT_CONSTRUCT</span><span class="plain">)) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">token_spec</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token_as_parsed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_read</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">token_spec</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Token %d: $P: kind $u: template $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">,</span>
<span class="identifier">token_spec</span><span class="plain">, </span><span class="identifier">kind_read</span><span class="plain">, </span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.token_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.token_kind</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">kind_read</span><span class="plain">, </span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.token_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.token_kind</span><span class="plain">)) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">:</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(4I.c) failed at token %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="identifier">outcome</span><span class="plain"> = </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::problems_have_been_issued</span><span class="plain">()) </span><span class="identifier">exit_at_once</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="reserved">case</span><span class="plain"> </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">:</span>
<span class="identifier">outcome</span><span class="plain"> = </span><span class="functiontext">Dash::worst_case</span><span class="plain">(</span><span class="identifier">outcome</span><span class="plain">, </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">);</span>
<span class="comment">we won't use <code class="display"><span class="extract">with_qualifications</span></code> &mdash; we don't know exactly what they are</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(4I.c) dropping to sometimes at token %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">:</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">exit_at_once</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">exit_at_once</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pass</span><span class="plain"> == 1) &amp;&amp; (</span><span class="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">)) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(4I.c) prototype check passed\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">most_recent_interpretation</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">kind_variable_declaration</span><span class="plain"> *</span><span class="identifier">kvdm</span><span class="plain"> = </span><span class="identifier">kvd_marker</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kvdm</span><span class="plain">) </span><span class="identifier">kvdm</span><span class="plain"> = </span><span class="identifier">NEXT_OBJECT</span><span class="plain">(</span><span class="identifier">kvdm</span><span class="plain">, </span><span class="identifier">kind_variable_declaration</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">kvdm</span><span class="plain"> = </span><span class="identifier">FIRST_OBJECT</span><span class="plain">(</span><span class="identifier">kind_variable_declaration</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">kvdm</span><span class="plain">) {</span>
<span class="identifier">kvdm</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">most_recent_interpretation</span><span class="plain">;</span>
<span class="identifier">most_recent_interpretation</span><span class="plain"> = </span><span class="identifier">kvdm</span><span class="plain">;</span>
<span class="identifier">kvdm</span><span class="plain"> = </span><span class="identifier">NEXT_OBJECT</span><span class="plain">(</span><span class="identifier">kvdm</span><span class="plain">, </span><span class="identifier">kind_variable_declaration</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">kind_checker_mode</span><span class="plain"> = </span><span class="identifier">save_kcm</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) </span><span class="identifier">ParseTree::set_kind_variable_declarations</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">most_recent_interpretation</span><span class="plain">);</span>
<span class="identifier">most_recent_interpretation</span><span class="plain"> = </span><span class="identifier">save_most_recent_interpretation</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::contains</span><span class="plain">(</span><span class="identifier">ParseTree::get_kind_resulting</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">), </span><span class="identifier">CON_KIND_VARIABLE</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">changed</span><span class="plain"> = </span><span class="identifier">FALSE</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">Kinds::substitute</span><span class="plain">(</span><span class="identifier">ParseTree::get_kind_resulting</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">), </span><span class="identifier">NULL</span><span class="plain">, &amp;</span><span class="identifier">changed</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">changed</span><span class="plain">) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(4I.c) amended kind returned to $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_kind_resulting</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Disallow an undeclared kind variable as return kind</span> <span class="cwebmacronumber">11.9.1.1.4.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1">&#167;11.9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_4_1"></a><b>&#167;11.9.1.1.4.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Disallow an undeclared kind variable as return kind</span> <span class="cwebmacronumber">11.9.1.1.4.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_A_GROSSER_THAN_GROSS_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</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">BelievedImpossible</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the line %1, you seem to be using '%2' to produce a value, but "</span>
<span class="string">"it's not clear what kind of value this will be. It seems to use "</span>
<span class="string">"a phrase which has been declared wrongly, because the kind it decides "</span>
<span class="string">"is given only by a symbol which isn't otherwise defined."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="identifier">outcome</span><span class="plain"> = </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1_4">&#167;11.9.1.1.4</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_5"></a><b>&#167;11.9.1.1.5. </b>Although we don't implement it with prototypes as such, there's a
similar constraint on the arguments of an assignment. If we are checking an
invocation against:
</p>
<blockquote>
<p>To let (t - existing variable) be (u - value): ...</p>
</blockquote>
<p class="inwebparagraph">then we have so far checked that argument 0 is indeed the name of a variable
which already exists. But suppose the invocation is
</p>
<blockquote>
<p>let N be "there'll be no mutant enemy";</p>
</blockquote>
<p class="inwebparagraph">where N has already been created as a variable of kind "number". This clearly
has to be rejected, as it would violate type-safety. Step (4I.d) therefore
makes sure that all assignments match the kind of the new value against the
kind of the storage item to which it is being written.
</p>
<p class="inwebparagraph">A reasonable question might be why we don't implement this using the prototype
system of (4I.c), thus removing a rule from this already-complex algorithm, say by
</p>
<blockquote>
<p>To let (var - K variable) be (val - value of kind K): ...</p>
</blockquote>
<p class="inwebparagraph">The answer is that this would indeed work nicely for valid source text, but that
we would get less helpful problem messages in the all-too-likely case of a
mistake having been made.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I.d) Match kinds in assignment phrases</span> <span class="cwebmacronumber">11.9.1.1.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.d)"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Phrases::TypeData::is_assignment_phrase</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">)) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">target</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token_as_parsed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, 0);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">new_value</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token_as_parsed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, 1);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">target_spec</span><span class="plain"> = </span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.token_sequence</span><span class="plain">[0]</span><span class="element">.to_match</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">new_value_spec</span><span class="plain"> = </span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.token_sequence</span><span class="plain">[1]</span><span class="element">.to_match</span><span class="plain">;</span>
<span class="reserved">local_variable</span><span class="plain"> *</span><span class="identifier">lvar</span><span class="plain"> = </span><span class="functiontext">Lvalues::get_local_variable_if_any</span><span class="plain">(</span><span class="identifier">target</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">lvar</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">LocalVariables::protected</span><span class="plain">(</span><span class="identifier">lvar</span><span class="plain">)))</span>
<span class="identifier">outcome</span><span class="plain"> = </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::le</span><span class="plain">(</span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">target_spec</span><span class="plain">), </span><span class="identifier">K_object</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Step (4I.d.1) Police an assignment to an object</span> <span class="cwebmacronumber">11.9.1.1.5.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.token_sequence</span><span class="plain">[0]</span><span class="element">.construct</span><span class="plain"> != </span><span class="constant">NEW_LOCAL_PT_CONSTRUCT</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Step (4I.d.2) Police an assignment to a storage item</span> <span class="cwebmacronumber">11.9.1.1.5.2</span>&gt;<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="#SP11_9_1_1">&#167;11.9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_5_1"></a><b>&#167;11.9.1.1.5.1. </b>It doesn't always look like an assignment, but a phrase such as:
</p>
<blockquote>
<p>change the Marble Door to open;</p>
</blockquote>
<p class="inwebparagraph">has similar type-checking needs.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I.d.1) Police an assignment to an object</span> <span class="cwebmacronumber">11.9.1.1.5.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.d.1)"</span><span class="plain">);</span>
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">target_wo</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_object_instance</span><span class="plain">(</span><span class="identifier">target</span><span class="plain">);</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</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="identifier">make_check</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">ParseTree::get_kind_of_value</span><span class="plain">(</span><span class="identifier">new_value_spec</span><span class="plain">), </span><span class="identifier">K_value</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Maybe we're changing an object to a value of a kind coinciding with a property</span> <span class="cwebmacronumber">11.9.1.1.5.1.1</span>&gt;<span class="character">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Rvalues::is_CONSTANT_construction</span><span class="plain">(</span><span class="identifier">new_value_spec</span><span class="plain">, </span><span class="identifier">CON_property</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Maybe we're changing an object to a named either/or property or condition state</span> <span class="cwebmacronumber">11.9.1.1.5.1.2</span>&gt;<span class="character">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">make_check</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Check that the property exists and that the object is allowed to have it</span> <span class="cwebmacronumber">11.9.1.1.5.1.3</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1_5">&#167;11.9.1.1.5</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_5_1_1"></a><b>&#167;11.9.1.1.5.1.1. </b>There are actually two definitions like this in the Standard Rules:
</p>
<blockquote>
<p>[1] To change (o - object) to (w - value): ...</p>
</blockquote>
<blockquote>
<p>[2] To change (o - object) to (p - property): ...</p>
</blockquote>
<p class="inwebparagraph">Here's the code for [1], the less obvious case. This is needed for something like
</p>
<blockquote>
<p>change the canvas to blue;</p>
</blockquote>
<p class="inwebparagraph">where "blue" is a constant colour, and "colour" is both a kind and also a
property. (This case really is an assignment &mdash; it assigns the value "blue"
to the colour property of the canvas.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Maybe we're changing an object to a value of a kind coinciding with a property</span> <span class="cwebmacronumber">11.9.1.1.5.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.d.1.a)"</span><span class="plain">);</span>
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_instance</span><span class="plain">(</span><span class="identifier">new_value</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">I</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">outcome</span><span class="plain"> = </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">prn</span><span class="plain"> = </span><span class="functiontext">Properties::Conditions::get_coinciding_property</span><span class="plain">(</span><span class="functiontext">Instances::to_kind</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">prn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">outcome</span><span class="plain"> = </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">make_check</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1_5_1">&#167;11.9.1.1.5.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_5_1_2"></a><b>&#167;11.9.1.1.5.1.2. </b>And here's the simpler case, [2]. A small quirk here is that it will also pick
up "change the Atrium to spiffy" in the following:
</p>
<blockquote>
<p>Atrium is a room. The Atrium can be spiffy, cool or lame.</p>
</blockquote>
<blockquote>
<p>When play begins: change the Atrium to spiffy.</p>
</blockquote>
<p class="inwebparagraph">...where "spiffy" is deemed a property rather than a constant value of a kind
because of the way the condition of the Atrium is declared. This is a little
bit horrid, but works fine in practice. (If we try to accommodate this case
within (1.2.4.1a), which might seem more logical, we run into trouble because
the property name is cast to a property value of <code class="display"><span class="extract">self</span></code> when being typechecked
against "value".)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Maybe we're changing an object to a named either/or property or condition state</span> <span class="cwebmacronumber">11.9.1.1.5.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.d.1.b)"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Rvalues::is_CONSTANT_construction</span><span class="plain">(</span><span class="identifier">new_value</span><span class="plain">, </span><span class="identifier">CON_property</span><span class="plain">))</span>
<span class="identifier">prn</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_property</span><span class="plain">(</span><span class="identifier">new_value</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Descriptions::number_of_adjectives_applied_to</span><span class="plain">(</span><span class="identifier">new_value</span><span class="plain">) == 1) {</span>
<span class="identifier">adjectival_phrase</span><span class="plain"> *</span><span class="identifier">aph</span><span class="plain"> = </span><span class="identifier">AdjectiveUsages::get_aph</span><span class="plain">(</span><span class="functiontext">Descriptions::first_adjective_usage</span><span class="plain">(</span><span class="identifier">new_value</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Adjectives::Meanings::has_ENUMERATIVE_meaning</span><span class="plain">(</span><span class="identifier">aph</span><span class="plain">))</span>
<span class="identifier">prn</span><span class="plain"> = </span><span class="functiontext">Properties::Conditions::get_coinciding_property</span><span class="plain">(</span><span class="functiontext">Instances::to_kind</span><span class="plain">(</span><span class="functiontext">Adjectives::Meanings::has_ENUMERATIVE_meaning</span><span class="plain">(</span><span class="identifier">aph</span><span class="plain">)));</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Adjectives::Meanings::has_EORP_meaning</span><span class="plain">(</span><span class="identifier">aph</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">))</span>
<span class="identifier">prn</span><span class="plain"> = </span><span class="functiontext">Adjectives::Meanings::has_EORP_meaning</span><span class="plain">(</span><span class="identifier">aph</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">make_check</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1_5_1">&#167;11.9.1.1.5.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_5_1_3"></a><b>&#167;11.9.1.1.5.1.3. </b>We do something quite interesting here, if the object is not explicitly
named: we deliberately allow an assignment which may not be type-safe, and
without even dropping to the "sometimes" level. This is for phrases like so:
</p>
<blockquote>
<p>change the item to closed;</p>
</blockquote>
<p class="inwebparagraph">Here the author seems to know what he's doing, and is pretty sure that the
current contents of "item" will accept closure. All we can prove is that
"item" contains an object (or perhaps <code class="display"><span class="extract">nothing</span></code>, the non-object). But
we allow the assignment because it will compile to code which will issue
a helpful run-time problem message if it goes wrong.
</p>
<p class="inwebparagraph">Now that "change" has been removed, as of January 2011, it looks as if
this case in the type-checker is never exercised.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Check that the property exists and that the object is allowed to have it</span> <span class="cwebmacronumber">11.9.1.1.5.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Property appears to be $Y\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="constant">THIS_IS_AN_INTERESTING_PROBLEM</span><span class="plain"> {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">target</span><span class="plain">));</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(3, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">new_value</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">BelievedImpossible</span><span class="plain">)); </span> <span class="comment">the parser seems not to allow these</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, asking to change the object '%2'. This would "</span>
<span class="string">"make sense if '%3' were an either/or property like 'open' "</span>
<span class="string">"(or perhaps a named property value like 'blue') - but it "</span>
<span class="string">"isn't, so the change makes no sense."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">target_wo</span><span class="plain">) &amp;&amp; (</span><span class="identifier">prn</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">World::Permissions::find</span><span class="plain">(</span><span class="functiontext">Instances::as_subject</span><span class="plain">(</span><span class="identifier">target_wo</span><span class="plain">), </span><span class="identifier">prn</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">)) {</span>
<span class="constant">THIS_IS_AN_INTERESTING_PROBLEM</span><span class="plain"> {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">target</span><span class="plain">));</span>
<span class="functiontext">Problems::quote_property</span><span class="plain">(3, </span><span class="identifier">prn</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">BelievedImpossible</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but '%2' is not allowed to have the property '%3'."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</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="#SP11_9_1_1_5_1">&#167;11.9.1.1.5.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_5_2"></a><b>&#167;11.9.1.1.5.2. </b>This is more straightforward, with just a tiny glitch to make the rules
tougher on variables which hold text to be parsed. (Because the regular rules
for exchanging the subtly different forms of text which a double-quoted
literal can mean are too generous.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I.d.2) Police an assignment to a storage item</span> <span class="cwebmacronumber">11.9.1.1.5.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_wanted</span><span class="plain">, *</span><span class="identifier">kind_found</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Check assignment of $P to $P\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">new_value</span><span class="plain">, </span><span class="identifier">target</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="functiontext">Lvalues::get_storage_form</span><span class="plain">(</span><span class="identifier">target_spec</span><span class="plain">)) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">LOCAL_VARIABLE_NT</span><span class="plain">: </span><span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"the name of"</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">PROPERTY_VALUE_NT</span><span class="plain">: </span><span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"a property whose kind of value is"</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">NONLOCAL_VARIABLE_NT</span><span class="plain">: </span><span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"a variable whose kind of value is"</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">TABLE_ENTRY_NT</span><span class="plain">: </span><span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"a table entry whose kind of value is"</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">LIST_ENTRY_NT</span><span class="plain">: </span><span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"an entry in a list whose kind of value is"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"a stored value holding"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">kind_wanted</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">target</span><span class="plain">);</span>
<span class="identifier">kind_found</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">new_value</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">new_invl</span><span class="plain"> = </span><span class="identifier">new_value</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">new_invl</span><span class="plain">, </span><span class="constant">INVOCATION_LIST_NT</span><span class="plain">)) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">new_inv</span><span class="plain">;</span>
<span class="identifier">LOOP_THROUGH_ALTERNATIVES</span><span class="plain">(</span><span class="identifier">new_inv</span><span class="plain">, </span><span class="identifier">new_invl</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">new_inv</span><span class="plain">, </span><span class="constant">PASSED_DASHFLAG</span><span class="plain">)) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">new_inv</span><span class="plain">) </span><span class="identifier">kind_found</span><span class="plain"> = </span><span class="identifier">ParseTree::get_kind_resulting</span><span class="plain">(</span><span class="identifier">new_inv</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Kinds found: $u, wanted: $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">kind_found</span><span class="plain">, </span><span class="identifier">kind_wanted</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (((</span><span class="identifier">K_understanding</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">kind_wanted</span><span class="plain">, </span><span class="identifier">K_understanding</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">kind_found</span><span class="plain">, </span><span class="identifier">K_understanding</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">))</span>
<span class="plain">|| (</span><span class="identifier">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">kind_found</span><span class="plain">, </span><span class="identifier">kind_wanted</span><span class="plain">) == </span><span class="identifier">NEVER_MATCH</span><span class="plain">)) {</span>
<span class="constant">THIS_IS_AN_INTERESTING_PROBLEM</span><span class="plain"> {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">target</span><span class="plain">));</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">target</span><span class="plain">));</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(4, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">new_value</span><span class="plain">));</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(5, </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">new_value</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_ChangeToWrongValue</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but '%2' is supposed to be "</span>
<span class="string">"%6 %3, so it cannot be set equal to %4, whose kind is %5."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</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="#SP11_9_1_1_5">&#167;11.9.1.1.5</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_6"></a><b>&#167;11.9.1.1.6. </b>Suppose we have something like this:
</p>
<blockquote>
<p>award the current action points;</p>
</blockquote>
<p class="inwebparagraph">and we are typechecking <code class="display"><span class="extract">found</span></code> as "the current action" (a phrase deciding
a value) against <code class="display"><span class="extract">expected</span></code> as "number", the parameter expected in
"award (N - a number) points".
</p>
<p class="inwebparagraph">No matter how peculiar this invocation of <code class="display"><span class="extract">found</span></code> was, we have now successfully
worked out the kind of the value it would return if compiled, and this is
stored in <code class="display"><span class="extract">inv-&gt;kind_resulting</span></code>. We now check to see if this matches the kind
expected &mdash; in this example, it won't, because a stored action does not cast
to a number.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I.e) Check kind of value returned</span> <span class="cwebmacronumber">11.9.1.1.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.e)"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">outcome_test</span><span class="plain"> = </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kind_needed</span><span class="plain">) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Checking returned $u against desired $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">ParseTree::get_kind_resulting</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">), </span><span class="identifier">kind_needed</span><span class="plain">);</span>
<span class="identifier">outcome_test</span><span class="plain"> = </span><span class="identifier">Kinds::Compare::compatible</span><span class="plain">(</span>
<span class="identifier">ParseTree::get_kind_resulting</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">), </span><span class="identifier">kind_needed</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">outcome_test</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">: </span><span class="identifier">outcome</span><span class="plain"> = </span><span class="identifier">NEVER_MATCH</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">: </span><span class="identifier">outcome</span><span class="plain"> = </span><span class="functiontext">Dash::worst_case</span><span class="plain">(</span><span class="identifier">outcome</span><span class="plain">, </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1">&#167;11.9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_7"></a><b>&#167;11.9.1.1.7. </b>The final stage in type-checking a phrase is to ensure that any phrase
options are properly used.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I.f) Check any phrase options</span> <span class="cwebmacronumber">11.9.1.1.7</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.f)"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) &amp;&amp; (</span><span class="identifier">ParseTree::get_phrase_options_invoked</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">))) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">cso</span><span class="plain"> = </span><span class="functiontext">Phrases::Options::parse_invoked_options</span><span class="plain">(</span>
<span class="identifier">inv</span><span class="plain">, (</span><span class="identifier">TEST_DASH_MODE</span><span class="plain">(</span><span class="constant">ISSUE_PROBLEMS_DMODE</span><span class="plain">))?</span><span class="identifier">FALSE</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="identifier">cso</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="identifier">outcome</span><span class="plain"> = </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1">&#167;11.9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_8"></a><b>&#167;11.9.1.1.8. </b>A say phrase which involves a property of something implicitly changes
the scope for any vaguely described properties within the text supplied
as that property (if it is indeed text). We have to mark any such
property, and any such say. For instance, suppose we are typechecking
</p>
<blockquote>
<p>[1] "Oh, look: [initial appearance of the escritoire]"</p>
</blockquote>
<p class="inwebparagraph">and the initial appearance in question is:
</p>
<blockquote>
<p>[2] "A small, portable writing desk holding up to [carrying capacity] letters."</p>
</blockquote>
<p class="inwebparagraph">Printing text [2], it's important for the <code class="display"><span class="extract">self</span></code> object to be the
escritoire, which might not be the case otherwise; so during the printing
of [1], we have to change <code class="display"><span class="extract">self</span></code> temporarily and restore it afterwards.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I.g) Worry about self in say property of</span> <span class="cwebmacronumber">11.9.1.1.8</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.g)"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Phrases::TypeData::is_a_say_phrase</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Invocations::get_no_tokens</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">) == 1) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Lvalues::get_storage_form</span><span class="plain">(</span><span class="functiontext">Invocations::get_token_as_parsed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, 0)) == </span><span class="constant">PROPERTY_VALUE_NT</span><span class="plain">)) {</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="functiontext">Invocations::get_token_as_parsed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, 0), </span><span class="constant">record_as_self_ANNOT</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="functiontext">Invocations::mark_to_save_self</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1">&#167;11.9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_9"></a><b>&#167;11.9.1.1.9. </b>Some phrases are defined with a notation making them allowable only inside
loops, or other control structures; for instance,
</p>
<blockquote>
<p>To break -- in loop: ...</p>
</blockquote>
<p class="inwebparagraph">And here is where we check that "break" is indeed used only in a loop.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I.h) Worry about using a phrase outside of the control structure it belongs to</span> <span class="cwebmacronumber">11.9.1.1.9</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.h)"</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">wchar_t</span><span class="plain"> *</span><span class="identifier">required</span><span class="plain"> = </span><span class="functiontext">Phrases::TypeData::only_in</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">required</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wide::cmp</span><span class="plain">(</span><span class="identifier">required</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"loop"</span><span class="plain">) == 0) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Required to be inside loop body\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Frames::Blocks::inside_a_loop_body</span><span class="plain">() == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="constant">THIS_IS_AN_INTERESTING_PROBLEM</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="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_CantUseOutsideLoop</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"%1 makes sense only inside a 'while' or 'repeat' loop."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Required to be inside block '%w'\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">required</span><span class="plain">);</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">actual</span><span class="plain"> = </span><span class="functiontext">Frames::Blocks::name_of_current_block</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">actual</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Wide::cmp</span><span class="plain">(</span><span class="identifier">actual</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"unless"</span><span class="plain">) == 0)) </span><span class="identifier">actual</span><span class="plain"> = </span><span class="identifier">L</span><span class="string">"if"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">actual</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">Wide::cmp</span><span class="plain">(</span><span class="identifier">required</span><span class="plain">, </span><span class="identifier">actual</span><span class="plain">) != 0)) {</span>
<span class="constant">THIS_IS_AN_INTERESTING_PROBLEM</span><span class="plain"> {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wide_text</span><span class="plain">(2, </span><span class="identifier">required</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_CantUseOutsideStructure</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"%1 makes sense only inside a '%2' block."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1">&#167;11.9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_10"></a><b>&#167;11.9.1.1.10. </b><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I.i) Disallow any phrases which are now deprecated</span> <span class="cwebmacronumber">11.9.1.1.10</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_deprecated_features</span><span class="plain">) {</span>
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.i)"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ph</span><span class="plain">) &amp;&amp; (</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data.now_deprecated</span><span class="plain">)) {</span>
<span class="constant">THIS_IS_AN_INTERESTING_PROBLEM</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="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">)); </span> <span class="comment">too moving a target to test</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"'%1' uses a phrase which is now deprecated: you should rephrase "</span>
<span class="string">"to avoid the need for it. I'd normally allow this, but you have "</span>
<span class="string">"the 'Use no deprecated features' option set."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1">&#167;11.9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_11"></a><b>&#167;11.9.1.1.11. </b><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I.j) Cope with failure</span> <span class="cwebmacronumber">11.9.1.1.11</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.j) failure"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_gross_problems_thrown</span><span class="plain"> &gt; </span><span class="identifier">no_gross_problems_thrown_before</span><span class="plain">)</span>
<span class="functiontext">Dash::set_flag</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">GROSSLY_FAILED_DASHFLAG</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_interesting_problems_thrown</span><span class="plain"> &gt; </span><span class="identifier">no_interesting_problems_thrown_before</span><span class="plain">)</span>
<span class="functiontext">Dash::set_flag</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">INTERESTINGLY_FAILED_DASHFLAG</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">consider_alternatives</span><span class="plain">) &amp;&amp; (</span><span class="identifier">TEST_DASH_MODE</span><span class="plain">(</span><span class="constant">ISSUE_PROBLEMS_DMODE</span><span class="plain">)))</span>
<span class="functiontext">Dash::failed_one</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">context</span><span class="plain">, </span><span class="identifier">kind_needed</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_1">&#167;11.9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_1_12"></a><b>&#167;11.9.1.1.12. </b>Usage statistics are mainly interesting to the writers of Inform, to help us
to get some picture of how much phrases are used across a large corpus of
existing source text (e.g., the documentation examples, or the public
extensions).
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4I.k) Cope with success</span> <span class="cwebmacronumber">11.9.1.1.12</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4I.k) success"</span><span class="plain">);</span>
<span class="functiontext">Dash::set_flag</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">PASSED_DASHFLAG</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">qualified</span><span class="plain">) {</span>
<span class="functiontext">Dash::set_flag</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">UNPROVEN_DASHFLAG</span><span class="plain">);</span>
<span class="functiontext">Invocations::mark_unproven</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">);</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">wording</span><span class="plain"> </span><span class="identifier">NW</span><span class="plain"> = </span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;ph_documentation_symbol</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">NW</span><span class="plain">)) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">pds</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">pds</span><span class="plain">, </span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">Wordings::one_word</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">NW</span><span class="plain">)));</span>
<span class="identifier">Index::DocReferences::doc_mark_used</span><span class="plain">(</span><span class="identifier">pds</span><span class="plain">,</span>
<span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">)));</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">pds</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="#SP11_9_1_1">&#167;11.9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_2"></a><b>&#167;11.9.1.2. (4S) Verifying single non-invocation readings. </b>This is much easier, though that's because a lot of the work is delegated
to level 5.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4S) Verify anything else</span> <span class="cwebmacronumber">11.9.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4S.a)"</span><span class="plain">);</span>
<span class="identifier">LOG_INDENT</span><span class="plain">;</span>
<span class="identifier">outcome</span><span class="plain"> = </span><span class="functiontext">Dash::typecheck_single_node</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">kind_needed</span><span class="plain">, </span><span class="identifier">condition_context</span><span class="plain">);</span>
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Allow listed-in table references only where these are expected</span> <span class="cwebmacronumber">11.9.1.2.1</span>&gt;<span class="plain">;</span>
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4S.b)"</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">arg</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">; </span><span class="identifier">arg</span><span class="plain">; </span><span class="identifier">arg</span><span class="plain"> = </span><span class="identifier">arg</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">)</span>
<span class="identifier">outcome</span><span class="plain"> =</span>
<span class="functiontext">Dash::worst_case</span><span class="plain">(</span><span class="identifier">outcome</span><span class="plain">,</span>
<span class="functiontext">Dash::typecheck_recursive</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">, </span><span class="identifier">p</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="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">LIST_ENTRY_NT</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Step (4S.c) Check arguments of a list entry</span> <span class="cwebmacronumber">11.9.1.2.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">PROPERTY_VALUE_NT</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Step (4S.d) Check arguments of a property value</span> <span class="cwebmacronumber">11.9.1.2.3</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">TABLE_ENTRY_NT</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Step (4S.e) Check arguments of a table reference</span> <span class="cwebmacronumber">11.9.1.2.4</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1">&#167;11.9.1</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_2_1"></a><b>&#167;11.9.1.2.1. </b>The "C listed in T" form of table reference is illegal as a general value,
and allowed only in phrases using the <code class="display"><span class="extract">table-reference</span></code> token.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Allow listed-in table references only where these are expected</span> <span class="cwebmacronumber">11.9.1.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">TABLE_ENTRY_NT</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">ParseTree::no_children</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) == 2) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">kind_needed</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(!(</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">context</span><span class="plain">, </span><span class="constant">LVALUE_TR_CONTEXT_NT</span><span class="plain">)))) {</span>
<span class="constant">THIS_IS_A_GROSSER_THAN_GROSS_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_InexplicitTableEntryAsValue</span><span class="plain">),</span>
<span class="string">"this form of table entry can only be used in certain special phrases"</span><span class="plain">,</span>
<span class="string">"because it doesn't explicitly refer to a single value. (You can see "</span>
<span class="string">"which phrases in the Phrasebook index: it's allowed wherever a 'table "</span>
<span class="string">"entry' is wanted.)"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_2">&#167;11.9.1.2</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_2_2"></a><b>&#167;11.9.1.2.2. </b>For a list entry, we have to have a list and an index.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4S.c) Check arguments of a list entry</span> <span class="cwebmacronumber">11.9.1.2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4S.c)"</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K1</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K2</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::unary_construction_material</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="constant">THIS_IS_A_GROSSER_THAN_GROSS_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EntryOfNonList</span><span class="plain">),</span>
<span class="string">"that doesn't make sense to me as a list entry"</span><span class="plain">,</span>
<span class="string">"since the entry is taken from something which isn't a list."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">, </span><span class="identifier">K_number</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="constant">THIS_IS_A_GROSSER_THAN_GROSS_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_NonNumericListEntry</span><span class="plain">),</span>
<span class="string">"that doesn't make sense to me as a list entry"</span><span class="plain">,</span>
<span class="string">"because the indication of which entry is not a number. "</span>
<span class="string">"For instance, 'entry 3 of L' is allowed, but not 'entry "</span>
<span class="string">"\</span><span class="plain">"</span><span class="string">six\</span><span class="plain">"</span><span class="string"> of L'. (List entries are numbered 1, 2, 3, ...)"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_2">&#167;11.9.1.2</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_2_3"></a><b>&#167;11.9.1.2.3. </b>For a property value, we have to have a property and an owner (perhaps an
object, perhaps a value). If the owner is a value, we need to police the
availability of the property carefully, since no run-time checking can help
us there.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4S.d) Check arguments of a property value</span> <span class="cwebmacronumber">11.9.1.2.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4S.d)"</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">the_property</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K1</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">the_property</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">) != </span><span class="identifier">CON_property</span><span class="plain">) </span>&lt;<span class="cwebmacro">Issue a "not a property" problem message</span> <span class="cwebmacronumber">11.9.1.2.3.1</span>&gt;<span class="plain">;</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_property</span><span class="plain">(</span><span class="identifier">the_property</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prn</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 property name in type checking"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::is_either_or</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">)) </span>&lt;<span class="cwebmacro">Issue a "not a value property" problem message</span> <span class="cwebmacronumber">11.9.1.2.3.2</span>&gt;<span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">the_owner</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K2</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">the_owner</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K2</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="functiontext">Specifications::is_description</span><span class="plain">(</span><span class="identifier">the_owner</span><span class="plain">)))</span>
&lt;<span class="cwebmacro">Issue a problem message for being too vague about the owner</span> <span class="cwebmacronumber">11.9.1.2.3.3</span>&gt;<span class="plain">;</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">owning_subject</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::from_specification</span><span class="plain">(</span><span class="identifier">the_owner</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">owning_subject</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">owning_subject</span><span class="plain"> = </span><span class="functiontext">Kinds::Knowledge::as_subject</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">World::Permissions::find</span><span class="plain">(</span><span class="identifier">owning_subject</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) ||</span>
<span class="plain">((</span><span class="functiontext">Rvalues::is_object</span><span class="plain">(</span><span class="identifier">the_owner</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Rvalues::is_self_object_constant</span><span class="plain">(</span><span class="identifier">the_owner</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)))</span>
&lt;<span class="cwebmacro">Issue a problem message for not being allowed this property</span> <span class="cwebmacronumber">11.9.1.2.3.4</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_2">&#167;11.9.1.2</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_2_3_1"></a><b>&#167;11.9.1.2.3.1. </b>Inform constructs property-value specifications quite carefully, and I think
it's only possible for the typechecker to see one where the property isn't
a property when recovering from other problems.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue a "not a property" problem message</span> <span class="cwebmacronumber">11.9.1.2.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_A_GROSSER_THAN_GROSS_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(3, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">the_property</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">BelievedImpossible</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the sentence %1, it looks as if you intend '%2' to be a property "</span>
<span class="string">"of something, but there is no such property as '%3'."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_2_3">&#167;11.9.1.2.3</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_2_3_2"></a><b>&#167;11.9.1.2.3.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue a "not a value property" problem message</span> <span class="cwebmacronumber">11.9.1.2.3.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_A_GROSSER_THAN_GROSS_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</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_EitherOrAsValue</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the sentence %1, it looks as if you intend '%2' to be the value "</span>
<span class="string">"of a property of something, but that property has no value: it's "</span>
<span class="string">"something which an object either is or is not."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_2_3">&#167;11.9.1.2.3</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_2_3_3"></a><b>&#167;11.9.1.2.3.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem message for being too vague about the owner</span> <span class="cwebmacronumber">11.9.1.2.3.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_A_GROSSER_THAN_GROSS_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</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">owner_quoted</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">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">the_owner</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Descriptions::get_quantifier</span><span class="plain">(</span><span class="identifier">the_owner</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">))</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">the_owner</span><span class="plain">));</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">the_owner</span><span class="plain">)))</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(3, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">the_owner</span><span class="plain">));</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">owner_quoted</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Owner tree is $T\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">the_owner</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_PropertyOfKind2</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">owner_quoted</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)))</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the sentence %1, it looks as if you intend '%2' to be a property, "</span>
<span class="string">"but '%3' is not specific enough about who or what the owner is. "</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the sentence %1, it looks as if you intend to look up a property "</span>
<span class="string">"of something, but '%3' is not specific enough about who or what "</span>
<span class="string">"the owner is. "</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)))</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the sentence %1, it looks as if you intend '%2' to be a property, "</span>
<span class="string">"but you're not specific enough about who or what the owner is. "</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the sentence %1, it looks as if you intend to look up a property "</span>
<span class="string">"of something, but you're not specific enough about who or what "</span>
<span class="string">"the owner is. "</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"%PSometimes this mistake is made because Inform mostly doesn't understand "</span>
<span class="string">"the English language habit of referring to something indefinite by a "</span>
<span class="string">"common noun - for instance, writing 'change the carrying capacity of "</span>
<span class="string">"the container to 10' throws Inform because it doesn't understand "</span>
<span class="string">"that 'the container' means one which has been discussed recently."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_2_3">&#167;11.9.1.2.3</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_2_3_4"></a><b>&#167;11.9.1.2.3.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem message for not being allowed this property</span> <span class="cwebmacronumber">11.9.1.2.3.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_A_GROSSER_THAN_GROSS_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">prn</span><span class="plain">-</span><span class="element">&gt;name</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_subject</span><span class="plain">(3, </span><span class="identifier">owning_subject</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_LookedUpForbiddenProperty</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the sentence %1, you seem to be looking up the '%2' property, "</span>
<span class="string">"but '%3' is not allowed to have that property. "</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1_2_3">&#167;11.9.1.2.3</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_2_4"></a><b>&#167;11.9.1.2.4. </b>For a table entry, we have to have a list and an index.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (4S.e) Check arguments of a table reference</span> <span class="cwebmacronumber">11.9.1.2.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(4S.e)"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::no_children</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) == 4) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">col_kind</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">col_contents_kind</span><span class="plain"> = </span><span class="identifier">Kinds::unary_construction_material</span><span class="plain">(</span><span class="identifier">col_kind</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">key_kind</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Kinds: col $u, contents $u, key $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">col_kind</span><span class="plain">, </span><span class="identifier">col_contents_kind</span><span class="plain">, </span><span class="identifier">key_kind</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">col_kind</span><span class="plain">) != </span><span class="identifier">CON_table_column</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">col_contents_kind</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) {</span>
<span class="constant">THIS_IS_A_GROSSER_THAN_GROSS_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">),</span>
<span class="string">"that doesn't make sense to me as a table entry"</span><span class="plain">,</span>
<span class="string">"since the entry is taken from something which isn't a table."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">key_kind</span><span class="plain">, </span><span class="identifier">col_contents_kind</span><span class="plain">) == </span><span class="identifier">NEVER_MATCH</span><span class="plain">) {</span>
<span class="constant">THIS_IS_A_GROSSER_THAN_GROSS_PROBLEM</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_kind</span><span class="plain">(2, </span><span class="identifier">col_contents_kind</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="identifier">key_kind</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_TableCorrFruitless</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the sentence %1, you seem to be looking up a corresponding "</span>
<span class="string">"entry in a table: but it's fruitless to go looking for %3 "</span>
<span class="string">"in a column where each entry contains %2."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</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="#SP11_9_1_2">&#167;11.9.1.2</a>.</p>
<p class="inwebparagraph"><a id="SP11_9_1_3"></a><b>&#167;11.9.1.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Unknown found text occurs as a command</span> <span class="cwebmacronumber">11.9.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_A_GROSS_PROBLEM</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">structural</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">problem</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::mismatched_brackets</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">))) {</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_UnpairedBrackets</span><span class="plain">),</span>
<span class="string">"this is a phrase which I don't recognise"</span><span class="plain">,</span>
<span class="string">"perhaps because it uses brackets '(' and ')' or braces '{' and '}' "</span>
<span class="string">"in a way that doesn't make sense to me. Each open '(' or '{' has "</span>
<span class="string">"to have a matching ')' or '}'."</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_UnknownPhrase</span><span class="plain">),</span>
<span class="string">"this is a phrase which I don't recognise"</span><span class="plain">,</span>
<span class="string">"possibly because it is one you meant to define but never got round "</span>
<span class="string">"to, or because the wording is wrong (see the Phrasebook section of "</span>
<span class="string">"the Index to check). Alternatively, it may be that the text "</span>
<span class="string">"immediately previous to this was a definition whose ending, normally "</span>
<span class="string">"a full stop, is missing?"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11_9_1">&#167;11.9.1</a>.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>"Diagnosis" nonterminals are used to parse syntax which is already known
to be invalid: they simply choose between problem messages. This one picks
up on misuse of structural phrases.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">structural</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">problem</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt; ::=</span>
<span class="reserved">continue</span><span class="plain"> ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_WrongContinue problem</span> <span class="cwebmacronumber">12.1</span>&gt;
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP12_1"></a><b>&#167;12.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_WrongContinue problem</span> <span class="cwebmacronumber">12.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_WrongContinue</span><span class="plain">),</span>
<span class="string">"this is a phrase which I don't recognise"</span><span class="plain">,</span>
<span class="string">"and which isn't defined. Perhaps you wanted the phrase which "</span>
<span class="string">"would skip to the next repetition of a loop, since that's "</span>
<span class="string">"written 'continue' in some programming languages (such as C "</span>
<span class="string">"and Inform 6)? If so, what you want is 'next'."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. Arithmetic operands. </b>The following works out the kind of an operand for an arithmetic operation,
which because of polymorphism is not as straightforward as it looks.
</p>
<pre class="display">
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">Dash::fix_arithmetic_operand</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">operand</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">operand</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, </span><span class="constant">UNKNOWN_NT</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">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">operand</span><span class="plain">) != </span><span class="constant">RVALUE_CONTEXT_NT</span><span class="plain">)</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"arithmetic operand not an rvalue"</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">expected</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">check</span><span class="plain"> = </span><span class="identifier">operand</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">check</span><span class="plain">, </span><span class="identifier">AMBIGUITY_NT</span><span class="plain">)) </span><span class="identifier">check</span><span class="plain"> = </span><span class="identifier">check</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Rvalues::is_CONSTANT_construction</span><span class="plain">(</span><span class="identifier">check</span><span class="plain">, </span><span class="identifier">CON_property</span><span class="plain">)) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_property</span><span class="plain">(</span><span class="identifier">check</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::is_either_or</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
<span class="identifier">expected</span><span class="plain"> = </span><span class="functiontext">Properties::Valued::kind</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">);</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">ParseTree::get_kind_required_by_context</span><span class="plain">(</span><span class="identifier">operand</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_kind_required_by_context</span><span class="plain">(</span><span class="identifier">operand</span><span class="plain">, </span><span class="identifier">expected</span><span class="plain">);</span>
<span class="constant">BEGIN_DASH_MODE</span><span class="plain">;</span>
<span class="identifier">DASH_MODE_EXIT</span><span class="plain">(</span><span class="constant">ISSUE_PROBLEMS_DMODE</span><span class="plain">);</span>
<span class="identifier">DASH_MODE_CREATE</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="identifier">rv</span><span class="plain"> = </span><span class="functiontext">Dash::typecheck_recursive</span><span class="plain">(</span><span class="identifier">operand</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="constant">END_DASH_MODE</span><span class="plain">;</span>
<span class="identifier">ParseTree::set_kind_required_by_context</span><span class="plain">(</span><span class="identifier">operand</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">rv</span><span class="plain"> == </span><span class="identifier">NEVER_MATCH</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="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">operand</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::fix_arithmetic_operand is used in <a href="#SP11_9_1_1_2_2_1">&#167;11.9.1.1.2.2.1</a>.</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. Local variable markers. </b>Branches (4A) and (4I) both make use of the following code, which is
applied to any invocation surviving Dash.
</p>
<p class="inwebparagraph">Here's the usual way a local variable is made. One invocation we matched is
for the phrase whose prototype reads:
</p>
<blockquote>
<p>To let (T - nonexisting variable) be (V - value): ...</p>
</blockquote>
<p class="inwebparagraph">To be definite, let's suppose we are working on:
</p>
<blockquote>
<p>let the magic word be "Shazam [turn count] times!";</p>
</blockquote>
<p class="inwebparagraph">The checking code above accepted "magic word" as a new name, and marked
token 0 in the invocation as one where a new variable will need to be
created &mdash; which is done if and when the invocation is ever compiled.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::set_up_any_local_required</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain">) {</span>
<span class="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">N</span><span class="plain"> = </span><span class="functiontext">Invocations::get_no_tokens</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">N</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token_variable_kind</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i</span><span class="plain"> == 0) &amp;&amp; (</span><span class="identifier">N</span><span class="plain"> &gt;= 2) &amp;&amp; (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Phrases::TypeData::is_a_let_assignment</span><span class="plain">(</span><span class="identifier">ParseTree::get_phrase_invoked</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">))))</span>
&lt;<span class="cwebmacro">Infer the kind of the new variable</span> <span class="cwebmacronumber">14.1</span>&gt;<span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">changed</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">K</span><span class="plain"> = </span><span class="identifier">Kinds::substitute</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, &amp;</span><span class="identifier">changed</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">changed</span><span class="plain">) </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(4A.c.1) Local var amended to $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="functiontext">Invocations::set_token_variable_kind</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::set_up_any_local_required is used in <a href="#SP11_9_2_3_2">&#167;11.9.2.3.2</a>, <a href="#SP11_9_1_1">&#167;11.9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP14_1"></a><b>&#167;14.1. </b>The following code is used to work out a good kind for the new variable,
instead of "value", based on looking at token 1 &mdash; the value being assigned.
In the example above, we look at this initial value,
</p>
<blockquote>
<p>"Shazam [turn count] times!"</p>
</blockquote>
<p class="inwebparagraph">and decide that K should be "text".
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Infer the kind of the new variable</span> <span class="cwebmacronumber">14.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">val</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token_as_parsed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">val</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">initial_value</span><span class="plain"> = </span><span class="functiontext">Invocations::get_token_as_parsed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, 1);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">iv_spec</span><span class="plain"> = </span><span class="identifier">ParseTree::get_phrase_invoked</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">)-</span><span class="element">&gt;type_data.token_sequence</span><span class="plain">[1]</span><span class="element">.to_match</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">initial_value</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Where no kind was explicitly stated, infer this from the supplied initial value</span> <span class="cwebmacronumber">14.1.1</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP14">&#167;14</a>.</p>
<p class="inwebparagraph"><a id="SP14_1_1"></a><b>&#167;14.1.1. </b>Unusually, it's legal for the initial value to be a generic constant &mdash;
</p>
<blockquote>
<p>let the magic digraph be a text;</p>
</blockquote>
<p class="inwebparagraph">This doesn't give us an initial value as such, but it explicitly tells us the
kind, which is good enough.
</p>
<p class="inwebparagraph">Otherwise, we either know the kind already from polymorphism calculations, or
we can work it out by seeing what the initial value evaluates to. As usual,
we "round up to objects"; if the let-value is a kind of object, we make
the variable have kind "object", rather than some subkind.
</p>
<p class="inwebparagraph">We make one exception to allow lines like &mdash;
</p>
<blockquote>
<p>let X be a one-to-one relation of numbers to men;</p>
</blockquote>
<p class="inwebparagraph">where the adjective "one-to-one" forces the right hand side to be description
of a relation.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Where no kind was explicitly stated, infer this from the supplied initial value</span> <span class="cwebmacronumber">14.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">seems_to_be</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Specifications::is_kind_like</span><span class="plain">(</span><span class="identifier">iv_spec</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">initial_value</span><span class="plain">, </span><span class="constant">CONSTANT_NT</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">ParseTree::get_kind_of_value</span><span class="plain">(</span><span class="identifier">initial_value</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) == </span><span class="identifier">CON_description</span><span class="plain">) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">DK</span><span class="plain"> = </span><span class="identifier">Kinds::unary_construction_material</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">DK</span><span class="plain">) == </span><span class="identifier">CON_relation</span><span class="plain">) </span><span class="identifier">seems_to_be</span><span class="plain"> = </span><span class="identifier">DK</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">seems_to_be</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">seems_to_be</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">initial_value</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">LOCAL_VARIABLES</span><span class="plain">, </span><span class="string">"New variable %W from $P ($P) seems to be: $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">W</span><span class="plain">, </span><span class="identifier">initial_value</span><span class="plain">, </span><span class="identifier">iv_spec</span><span class="plain">, </span><span class="identifier">seems_to_be</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">seems_to_be</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span>&lt;<span class="cwebmacro">Fail: the initial value of the local is unknown</span> <span class="cwebmacronumber">14.1.1.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">seems_to_be</span><span class="plain">) == </span><span class="identifier">CON_list_of</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">Kinds::unary_construction_material</span><span class="plain">(</span><span class="identifier">seems_to_be</span><span class="plain">), </span><span class="identifier">K_value</span><span class="plain">)))</span>
&lt;<span class="cwebmacro">Fail: the initial value of the local is the empty list</span> <span class="cwebmacronumber">14.1.1.2</span>&gt;<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">seems_to_be</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Fail: the initial value can't be stored</span> <span class="cwebmacronumber">14.1.1.3</span>&gt;<span class="character">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(4A.c.1) Local variable seems to have kind: $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">seems_to_be</span><span class="plain">);</span>
<span class="identifier">K</span><span class="plain"> = </span><span class="identifier">seems_to_be</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::lt</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">))</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">Kinds::Compare::super</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">), </span><span class="identifier">K_object</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
<span class="identifier">K</span><span class="plain"> = </span><span class="identifier">Kinds::Compare::super</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(4A.c.1) Local variable inferred to have kind: $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP14_1">&#167;14.1</a>.</p>
<p class="inwebparagraph"><a id="SP14_1_1_1"></a><b>&#167;14.1.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Fail: the initial value of the local is unknown</span> <span class="cwebmacronumber">14.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">initial_value</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">BelievedImpossible</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The phrase %1 tries to use 'let' to give a temporary name to a value, "</span>
<span class="string">"but the value ('%2') is one that I can't understand."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP14_1_1">&#167;14.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP14_1_1_2"></a><b>&#167;14.1.1.2. </b>Bet you didn't think of this one. Actually, the kind of the list can also
collapse to just "value" if the entries are incompatible, so we call the
relevant code to issue a better problem message if it can.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Fail: the initial value of the local is the empty list</span> <span class="cwebmacronumber">14.1.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pc</span><span class="plain"> = </span><span class="identifier">problem_count</span><span class="plain">;</span>
<span class="functiontext">Lists::check_one</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">initial_value</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pc</span><span class="plain"> == </span><span class="identifier">problem_count</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="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_CantLetEmptyList</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The phrase %1 tries to use 'let' to give a temporary name to the "</span>
<span class="string">"empty list '{ }', but because it's empty, I can't tell what kind of "</span>
<span class="string">"value the list should have. Try 'let X be a list of numbers' (or "</span>
<span class="string">"whatever) instead."</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">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP14_1_1">&#167;14.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP14_1_1_3"></a><b>&#167;14.1.1.3. </b>And some kinds are just forbidden in storage:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Fail: the initial value can't be stored</span> <span class="cwebmacronumber">14.1.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">),</span>
<span class="string">"this isn't a definite kind"</span><span class="plain">,</span>
<span class="string">"and is instead a general description which might apply to many "</span>
<span class="string">"different kinds, so I can't see how to create this named value. "</span>
<span class="string">"(For example, 'let R be a relation' is vague because it doesn't "</span>
<span class="string">"make clear what R will relate - 'let R be a relation of numbers' "</span>
<span class="string">"would be fine.)"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP14_1_1">&#167;14.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. Problems, problems, problems. </b>We are now in a situation where Dash has certainly failed, and on every
possible alternative reading, so it would be legitimate to return <code class="display"><span class="extract">NEVER_MATCH</span></code>
here, which would likely result in some anodyne problem message from higher
up in Dash.
</p>
<p class="inwebparagraph">But we want to produce more helpful problem messages than that. It's not
entirely clear how best to do this. Often, when a node fails, it fails for
seven different reasons &mdash; each different possibility fails for a different
cause. We want, somehow, to guess which was the most likely to have been
intended and to report the problem with that one.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::failed_one</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">context</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_needed</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">list</span><span class="plain">[1];</span>
<span class="identifier">list</span><span class="plain">[0] = </span><span class="identifier">inv</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Dash::failed</span><span class="plain">(</span><span class="identifier">list</span><span class="plain">, 1, </span><span class="identifier">context</span><span class="plain">, </span><span class="identifier">kind_needed</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">PM_BadIntermediateKind_wording</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING_INIT</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::failed</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> **</span><span class="identifier">list_of_possible_readings</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_of_possible_readings</span><span class="plain">,</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">context</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_needed</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::problems_have_been_issued</span><span class="plain">()) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">first_inv_in_group</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">first_failing_interestingly</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">first_not_failing_grossly</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">SW</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">list_includes_lets</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">nongross_count</span><span class="plain"> = 0;</span>
&lt;<span class="cwebmacro">Scan through the invocations in the problematic group, gathering information</span> <span class="cwebmacronumber">15.1</span>&gt;<span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">most_likely_to_have_been_intended</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Decide which invocation is the one most likely to have been intended</span> <span class="cwebmacronumber">15.2</span>&gt;<span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pc_before</span><span class="plain"> = </span><span class="identifier">problem_count</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">first_failing_interestingly</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Re-type-check the first interesting invocation, allowing interesting problems this time</span> <span class="cwebmacronumber">15.3</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">most_likely_to_have_been_intended</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Re-type-check the tokens of the most likely invocation with silence off</span> <span class="cwebmacronumber">15.4</span>&gt;
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> == </span><span class="identifier">pc_before</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">SW</span><span class="plain">)) &lt;</span><span class="identifier">failed</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">-</span><span class="identifier">substitution</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt;(</span><span class="identifier">SW</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Issue a problem for a regular phrase with multiple failed possibilities</span> <span class="cwebmacronumber">15.5</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::failed_one is used in <a href="#SP11_9_1_1_11">&#167;11.9.1.1.11</a>.</p>
<p class="endnote">The function Dash::failed is used in <a href="#SP11_9_2_4">&#167;11.9.2.4</a>.</p>
<p class="inwebparagraph"><a id="SP15_1"></a><b>&#167;15.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Scan through the invocations in the problematic group, gathering information</span> <span class="cwebmacronumber">15.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">ref</span><span class="plain">=0; </span><span class="identifier">ref</span><span class="plain">&lt;</span><span class="identifier">no_of_possible_readings</span><span class="plain">; </span><span class="identifier">ref</span><span class="plain">++) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain"> = </span><span class="identifier">list_of_possible_readings</span><span class="plain">[</span><span class="identifier">ref</span><span class="plain">];</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">INTERESTINGLY_FAILED_DASHFLAG</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">first_failing_interestingly</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="identifier">first_failing_interestingly</span><span class="plain"> = </span><span class="identifier">inv</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">first_inv_in_group</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">first_inv_in_group</span><span class="plain"> = </span><span class="identifier">inv</span><span class="plain">;</span>
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain"> = </span><span class="identifier">ParseTree::get_phrase_invoked</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ph</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Phrases::TypeData::is_a_let_assignment</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">)) </span><span class="identifier">list_includes_lets</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">Dash::test_flag</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">GROSSLY_FAILED_DASHFLAG</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">first_not_failing_grossly</span><span class="plain"> = </span><span class="identifier">inv</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Phrases::TypeData::is_a_say_X_phrase</span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">&gt;type_data</span><span class="plain">))) </span><span class="identifier">SW</span><span class="plain"> = </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">);</span>
<span class="identifier">nongross_count</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_2"></a><b>&#167;15.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Decide which invocation is the one most likely to have been intended</span> <span class="cwebmacronumber">15.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">first_failing_interestingly</span><span class="plain">)</span>
<span class="identifier">most_likely_to_have_been_intended</span><span class="plain"> = </span><span class="identifier">first_failing_interestingly</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">nongross_count</span><span class="plain"> &gt; 1) &amp;&amp; (</span><span class="identifier">list_includes_lets</span><span class="plain">))</span>
<span class="identifier">most_likely_to_have_been_intended</span><span class="plain"> = </span><span class="identifier">first_not_failing_grossly</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nongross_count</span><span class="plain"> == 1)</span>
<span class="identifier">most_likely_to_have_been_intended</span><span class="plain"> = </span><span class="identifier">first_not_failing_grossly</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">nongross_count</span><span class="plain"> == 0) &amp;&amp; (</span><span class="identifier">first_inv_in_group</span><span class="plain">))</span>
<span class="identifier">most_likely_to_have_been_intended</span><span class="plain"> = </span><span class="identifier">first_inv_in_group</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_3"></a><b>&#167;15.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Re-type-check the first interesting invocation, allowing interesting problems this time</span> <span class="cwebmacronumber">15.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">BEGIN_DASH_MODE</span><span class="plain">;</span>
<span class="identifier">DASH_MODE_ENTER</span><span class="plain">(</span><span class="constant">ISSUE_INTERESTING_PROBLEMS_DMODE</span><span class="plain">);</span>
<span class="identifier">DASH_MODE_CREATE</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="functiontext">Dash::typecheck_recursive</span><span class="plain">(</span><span class="identifier">first_failing_interestingly</span><span class="plain">, </span><span class="identifier">context</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="constant">END_DASH_MODE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_4"></a><b>&#167;15.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Re-type-check the tokens of the most likely invocation with silence off</span> <span class="cwebmacronumber">15.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ec</span><span class="plain"> = </span><span class="identifier">problem_count</span><span class="plain">;</span>
<span class="constant">BEGIN_DASH_MODE</span><span class="plain">;</span>
<span class="identifier">DASH_MODE_ENTER</span><span class="plain">(</span><span class="constant">ISSUE_PROBLEMS_DMODE</span><span class="plain">);</span>
<span class="identifier">DASH_MODE_CREATE</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="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="functiontext">Invocations::get_no_tokens</span><span class="plain">(</span><span class="identifier">most_likely_to_have_been_intended</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="functiontext">Dash::typecheck_recursive</span><span class="plain">(</span><span class="functiontext">Invocations::get_token</span><span class="plain">(</span><span class="identifier">most_likely_to_have_been_intended</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">), </span><span class="identifier">context</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="identifier">problem_count</span><span class="plain"> &gt; </span><span class="identifier">ec</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">problem_count</span><span class="plain"> == </span><span class="identifier">ec</span><span class="plain">) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Try again in local problems mode\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="constant">BEGIN_DASH_MODE</span><span class="plain">;</span>
<span class="identifier">DASH_MODE_ENTER</span><span class="plain">(</span><span class="constant">ISSUE_LOCAL_PROBLEMS_DMODE</span><span class="plain">);</span>
<span class="identifier">DASH_MODE_CREATE</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="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="functiontext">Invocations::get_no_tokens</span><span class="plain">(</span><span class="identifier">most_likely_to_have_been_intended</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="functiontext">Dash::typecheck_recursive</span><span class="plain">(</span><span class="functiontext">Invocations::get_token</span><span class="plain">(</span><span class="identifier">most_likely_to_have_been_intended</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">), </span><span class="identifier">context</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="identifier">problem_count</span><span class="plain"> &gt; </span><span class="identifier">ec</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="constant">END_DASH_MODE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="constant">END_DASH_MODE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> == </span><span class="identifier">ec</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">ParseTree::get_kind_resulting</span><span class="plain">(</span><span class="identifier">most_likely_to_have_been_intended</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">kind_needed</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K</span><span class="plain">) &amp;&amp; (</span><span class="identifier">W</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">) == </span><span class="identifier">NEVER_MATCH</span><span class="plain">)) {</span>
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">PW</span><span class="plain"> = </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">list_of_possible_readings</span><span class="plain">[0]);</span>
<span class="reserved">if</span><span class="plain"> (!(</span><span class="identifier">Wordings::eq</span><span class="plain">(</span><span class="identifier">PM_BadIntermediateKind_wording</span><span class="plain">, </span><span class="identifier">PW</span><span class="plain">))) {</span>
<span class="identifier">PM_BadIntermediateKind_wording</span><span class="plain"> = </span><span class="identifier">PW</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">PW</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">W</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_BadIntermediateKind</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In %1, the phrase '%2' doesn't seem to fit: I was hoping it would "</span>
<span class="string">"be %4, but in fact it's %3."</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">NEVER_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> == </span><span class="identifier">ec</span><span class="plain">) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Try again in gross problems mode\</span><span class="plain">n</span><span class="string">$T\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">most_likely_to_have_been_intended</span><span class="plain">);</span>
<span class="constant">BEGIN_DASH_MODE</span><span class="plain">;</span>
<span class="identifier">DASH_MODE_ENTER</span><span class="plain">(</span><span class="constant">ISSUE_GROSS_PROBLEMS_DMODE</span><span class="plain">);</span>
<span class="identifier">DASH_MODE_CREATE</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="functiontext">Dash::typecheck_recursive</span><span class="plain">(</span><span class="identifier">most_likely_to_have_been_intended</span><span class="plain">, </span><span class="identifier">context</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="constant">END_DASH_MODE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> == 0)</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">),</span>
<span class="string">"the ingredients in this phrase do not fit it"</span><span class="plain">,</span>
<span class="string">"and I am confused enough by this that I can't give a very helpful "</span>
<span class="string">"problem message. Sorry about that."</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_5"></a><b>&#167;15.5. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem for a regular phrase with multiple failed possibilities</span> <span class="cwebmacronumber">15.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<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_AllInvsFailed</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_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, which I tried to match against several possible phrase "</span>
<span class="string">"definitions. None of them worked."</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="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. </b>The following chooses a problem message for a text substitution which is
unrecognised.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">failed</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">-</span><span class="identifier">substitution</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt; ::=</span>
<span class="identifier">a</span><span class="plain"> </span><span class="identifier">list</span><span class="plain"> </span><span class="identifier">of</span><span class="plain"> ... | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_SayAList problem</span> <span class="cwebmacronumber">16.1</span>&gt;
<span class="plain">... ==&gt; </span>&lt;<span class="cwebmacro">Issue last-resort failed ts problem</span> <span class="cwebmacronumber">16.2</span>&gt;
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP16_1"></a><b>&#167;16.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_SayAList problem</span> <span class="cwebmacronumber">16.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::Issue::sentence_in_detail_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_SayAList</span><span class="plain">), </span><span class="identifier">W</span><span class="plain">,</span>
<span class="string">"this asked to say 'a list of...'"</span><span class="plain">,</span>
<span class="string">"which I read as being a general description applying to some "</span>
<span class="string">"lists and not others, so it's not something which can be said. "</span>
<span class="string">"(Maybe you meant 'the list of...' instead? That normally makes "</span>
<span class="string">"a definite list of whatever matches the '...' part.)"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP16">&#167;16</a>.</p>
<p class="inwebparagraph"><a id="SP16_2"></a><b>&#167;16.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue last-resort failed ts problem</span> <span class="cwebmacronumber">16.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::Issue::sentence_in_detail_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">), </span><span class="identifier">W</span><span class="plain">,</span>
<span class="string">"this asked to say something which I do not recognise"</span><span class="plain">,</span>
<span class="string">"either as a value or as one of the possible text substitutions."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP16">&#167;16</a>.</p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. </b>In the final checklist of doomed possibility, the code to quote an
invocation in a problem message will call the following routine for each
parsed token. This remembers the token so that it can be explained in notes
at the end of the big list; but each word range is remembered only once,
for brevity. We don't gloss the meanings of literal constants like <code class="display"><span class="extract">26</span></code>
or <code class="display"><span class="extract">"frog"</span></code> since these are glaringly obvious.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Dash::note_inv_token_text</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">new_name</span><span class="plain">) {</span>
<span class="reserved">inv_token_problem_token</span><span class="plain"> *</span><span class="identifier">itpt</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">itpt</span><span class="plain">, </span><span class="reserved">inv_token_problem_token</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::eq</span><span class="plain">(</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;problematic_text</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</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">new_name</span><span class="plain">) </span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;new_name</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">itpt</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">inv_token_problem_token</span><span class="plain">);</span>
<span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;problematic_text</span><span class="plain"> = </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;new_name</span><span class="plain"> = </span><span class="identifier">new_name</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">AMBIGUITY_NT</span><span class="plain">)) </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;as_parsed</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;already_described</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">Rvalues::is_CONSTANT_of_kind</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">K_number</span><span class="plain">)) ||</span>
<span class="plain">(</span><span class="functiontext">Rvalues::is_CONSTANT_of_kind</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">K_text</span><span class="plain">))) </span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">&gt;already_described</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::note_inv_token_text is used in 22/dptd (<a href="22-dptd.html#SP3_1_2">&#167;3.1.2</a>).</p>
<p class="inwebparagraph"><a id="SP18"></a><b>&#167;18. </b>This last little grammar diagnoses problems with a condition, and helps to
construct a problem message which will (usually) show which part of a compound
condition caused the trouble:
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">problem</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">problem</span><span class="plain">-</span><span class="identifier">part</span><span class="plain">&gt; &lt;</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">problem</span><span class="plain">-</span><span class="identifier">part</span><span class="plain">-</span><span class="identifier">tail</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">R</span><span class="plain">[1] | </span><span class="identifier">R</span><span class="plain">[2]</span>
<span class="plain">&lt;</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">problem</span><span class="plain">-</span><span class="identifier">part</span><span class="plain">&gt; ==&gt; </span><span class="identifier">R</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">problem</span><span class="plain">-</span><span class="identifier">part</span><span class="plain">-</span><span class="identifier">tail</span><span class="plain">&gt; ::=</span>
<span class="plain">, </span><span class="identifier">and</span><span class="plain">/</span><span class="identifier">or</span><span class="plain"> &lt;</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">problem</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">R</span><span class="plain">[1]</span>
<span class="plain">,/</span><span class="identifier">and</span><span class="plain">/</span><span class="identifier">or</span><span class="plain"> &lt;</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">problem</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt; ==&gt; </span><span class="identifier">R</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">problem</span><span class="plain">-</span><span class="identifier">part</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">&gt; | ==&gt; 0; </span>&lt;<span class="cwebmacro">Quote this-condition-okay segment</span> <span class="cwebmacronumber">18.1</span>&gt;<span class="plain">;</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">&gt; | ==&gt; </span><span class="constant">INVALID_CP_BIT</span><span class="plain">; </span>&lt;<span class="cwebmacro">Quote this-condition-value segment</span> <span class="cwebmacronumber">18.2</span>&gt;<span class="plain">;</span>
<span class="plain">... </span><span class="identifier">begins</span><span class="plain">/</span><span class="identifier">ends</span><span class="plain"> | ==&gt; </span><span class="constant">WHENWHILE_CP_BIT</span><span class="plain">+</span><span class="constant">INVALID_CP_BIT</span><span class="plain">; </span>&lt;<span class="cwebmacro">Quote scene-begins-or-ends segment</span> <span class="cwebmacronumber">18.3</span>&gt;<span class="plain">;</span>
<span class="identifier">when</span><span class="plain">/</span><span class="reserved">while</span><span class="plain"> *** | ==&gt; </span><span class="constant">WHENWHILE_CP_BIT</span><span class="plain">+</span><span class="constant">INVALID_CP_BIT</span><span class="plain">; </span>&lt;<span class="cwebmacro">Quote this-condition-bad segment</span> <span class="cwebmacronumber">18.4</span>&gt;<span class="plain">;</span>
<span class="plain">... ==&gt; </span><span class="constant">INVALID_CP_BIT</span><span class="plain">; </span>&lt;<span class="cwebmacro">Quote this-condition-bad segment</span> <span class="cwebmacronumber">18.4</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP18_1"></a><b>&#167;18.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Quote this-condition-okay segment</span> <span class="cwebmacronumber">18.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">preform_lookahead_mode</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(4, </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">"'%4' was okay; "</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP18">&#167;18</a>.</p>
<p class="inwebparagraph"><a id="SP18_2"></a><b>&#167;18.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Quote this-condition-value segment</span> <span class="cwebmacronumber">18.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">preform_lookahead_mode</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(4, </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">"'%4' only made sense as a value, which can't be used as a condition; "</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP18">&#167;18</a>.</p>
<p class="inwebparagraph"><a id="SP18_3"></a><b>&#167;18.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Quote scene-begins-or-ends segment</span> <span class="cwebmacronumber">18.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">preform_lookahead_mode</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(4, </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">"'%4' did not make sense as a condition, but looked as if it might "</span>
<span class="string">"be a way to specify a beginning or end for a scene - but such things "</span>
<span class="string">"can't be divided by 'or'; "</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP18">&#167;18</a>.</p>
<p class="inwebparagraph"><a id="SP18_4"></a><b>&#167;18.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Quote this-condition-bad segment</span> <span class="cwebmacronumber">18.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">preform_lookahead_mode</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(4, </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">"'%4' did not make sense; "</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP18">&#167;18</a> (twice).</p>
<p class="inwebparagraph"><a id="SP19"></a><b>&#167;19. (5) Single nodes. </b>Here we typecheck a single non-invocation node on its own terms, ignoring
any children it may have.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::typecheck_single_node</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="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_expected</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">condition_context</span><span class="plain">) {</span>
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(5)"</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Kind expected: $u, condition expected: %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">kind_expected</span><span class="plain">, </span><span class="identifier">condition_context</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">outcome</span><span class="plain"> = </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">; </span> <span class="comment">drops to <code class="display"><span class="extract">SOMETIMES_MATCH</span></code> if a need for run-time checking is realised</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Rvalues::is_nothing_object_constant</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">kind_expected</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::lt</span><span class="plain">(</span><span class="identifier">kind_expected</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">)))</span>
&lt;<span class="cwebmacro">Disallow "nothing" as a match for a description requiring a kind of object</span> <span class="cwebmacronumber">19.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Step (5.a) Deal with the UNKNOWN_NT</span> <span class="cwebmacronumber">19.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Step (5.b) Deal with bare property names</span> <span class="cwebmacronumber">19.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Step (5.c) Deal with any attached proposition</span> <span class="cwebmacronumber">19.4</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Step (5.d) Apply miscellaneous other coercions</span> <span class="cwebmacronumber">19.5</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Step (5.e) The Main Rule of Type-Checking</span> <span class="cwebmacronumber">19.6</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">outcome</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::typecheck_single_node is used in <a href="#SP11_9_1_2">&#167;11.9.1.2</a>.</p>
<p class="inwebparagraph"><a id="SP19_1"></a><b>&#167;19.1. </b>"You can't have/ Something for nothing," as Canadian power-trio Rush tell
us with the air of having just made a great discovery; well, you can't have
"nothing" for something, either &mdash;
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Disallow "nothing" as a match for a description requiring a kind of object</span> <span class="cwebmacronumber">19.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="identifier">kind_expected</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_NothingForSomething</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but '%2' is literally no thing, and it consequently does "</span>
<span class="string">"not count as %3."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19">&#167;19</a>.</p>
<p class="inwebparagraph"><a id="SP19_2"></a><b>&#167;19.2. Rule (5.a). </b>In all cases, unknown text in <code class="display"><span class="extract">found</span></code> is incorrect. We can produce
any of more than twenty different problem messages here, in an attempt to be
helpful about what exactly is wrong.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">SAY_UTSHAPE</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">LIST_UTSHAPE</span><span class="plain"> 2</span>
<span class="definitionkeyword">define</span> <span class="constant">NO_UTSHAPE</span><span class="plain"> 3</span>
</pre>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (5.a) Deal with the UNKNOWN_NT</span> <span class="cwebmacronumber">19.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(5.a)"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">UNKNOWN_NT</span><span class="plain">)) {</span>
<span class="constant">THIS_IS_A_GROSS_PROBLEM</span><span class="plain">;</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"(5.a) problem message:\</span><span class="plain">n</span><span class="string">found: $Texpected: $u"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">kind_expected</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">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">kind_expected</span><span class="plain">, </span><span class="identifier">K_stored_action</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Unknown found text occurs as an action to try</span> <span class="cwebmacronumber">19.2.1</span>&gt;<span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">Problems::quote_source_eliding_begin</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</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">condition_context</span><span class="plain">)</span>
<span class="identifier">Problems::quote_text</span><span class="plain">(3, </span><span class="string">"a condition"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kind_expected</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="identifier">K_value</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="identifier">kind_expected</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">shape</span><span class="plain"> = </span><span class="constant">NO_UTSHAPE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_sentence</span><span class="plain">) {</span>
<span class="plain">&lt;</span><span class="identifier">unknown</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">-</span><span class="identifier">shape</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">));</span>
<span class="identifier">shape</span><span class="plain"> = &lt;&lt;</span><span class="identifier">r</span><span class="plain">&gt;&gt;;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">shape</span><span class="plain"> == </span><span class="constant">NO_UTSHAPE</span><span class="plain">) {</span>
<span class="plain">&lt;</span><span class="identifier">unknown</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">-</span><span class="identifier">shape</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="identifier">shape</span><span class="plain"> = &lt;&lt;</span><span class="identifier">r</span><span class="plain">&gt;&gt;;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">preceding</span><span class="plain"> = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)) - 1;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">preceding</span><span class="plain"> &gt;= 0) &amp;&amp; (</span><span class="identifier">current_sentence</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(((</span><span class="identifier">compiling_text_routines_mode</span><span class="plain">) || (</span><span class="identifier">shape</span><span class="plain"> == </span><span class="constant">SAY_UTSHAPE</span><span class="plain">))) &amp;&amp;</span>
<span class="plain">((</span><span class="identifier">preceding</span><span class="plain"> == </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">)))</span>
<span class="plain">|| (</span><span class="identifier">Lexer::word</span><span class="plain">(</span><span class="identifier">preceding</span><span class="plain">) == </span><span class="identifier">COMMA_V</span><span class="plain">)))</span>
&lt;<span class="cwebmacro">Unknown found text occurs as a text substitution</span> <span class="cwebmacronumber">19.2.2</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">condition_context</span><span class="plain">) &amp;&amp; (</span><span class="identifier">shape</span><span class="plain"> == </span><span class="constant">LIST_UTSHAPE</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Issue a problem message for a compound condition which has gone bad</span> <span class="cwebmacronumber">19.2.3</span>&gt;
<span class="reserved">else</span>
&lt;<span class="cwebmacro">Issue a problem message for miscellaneous suspicious wordings</span> <span class="cwebmacronumber">19.2.4</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19">&#167;19</a>.</p>
<p class="inwebparagraph"><a id="SP19_2_1"></a><b>&#167;19.2.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Unknown found text occurs as an action to try</span> <span class="cwebmacronumber">19.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">K2</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="functiontext">Dash::clear_validation_case</span><span class="plain">();</span>
<span class="plain">&lt;</span><span class="identifier">action</span><span class="plain">-</span><span class="identifier">pattern</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</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="functiontext">Dash::get_validation_case</span><span class="plain">(&amp;</span><span class="identifier">spec</span><span class="plain">, &amp;</span><span class="identifier">K</span><span class="plain">, &amp;</span><span class="identifier">K2</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_UnknownTryAction1</span><span class="plain">));</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(3, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">));</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(5, </span><span class="identifier">K2</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but '%2' is not an action I can try. This looks as "</span>
<span class="string">"if it might be because it contains something of the wrong kind. "</span>
<span class="string">"My best try involved seeing if '%3' could be %4, which might have "</span>
<span class="string">"made sense, but it turned out to be %5."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_UnknownTryAction2</span><span class="plain">),</span>
<span class="string">"this is not an action I recognise"</span><span class="plain">,</span>
<span class="string">"or else is malformed in a way I can't see how to sort out."</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19_2">&#167;19.2</a>.</p>
<p class="inwebparagraph"><a id="SP20"></a><b>&#167;20. </b>The &lt;unknown-text-shape&gt; is used purely in diagnosing problems; it helps
to decide, for instance, whether the errant phrase was intended to be a text
substitution or not.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">unknown</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">-</span><span class="identifier">shape</span><span class="plain">&gt; ::=</span>
<span class="identifier">say</span><span class="plain"> ... | ==&gt; </span><span class="constant">SAY_UTSHAPE</span>
<span class="plain">... </span><span class="identifier">and</span><span class="plain">/</span><span class="identifier">or</span><span class="plain"> ... | ==&gt; </span><span class="constant">LIST_UTSHAPE</span>
<span class="plain">... ==&gt; </span><span class="constant">NO_UTSHAPE</span>
<span class="plain">&lt;</span><span class="identifier">unknown</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">-</span><span class="identifier">substitution</span><span class="plain">-</span><span class="identifier">problem</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt; ::=</span>
<span class="plain">, ... | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_SayComma problem</span> <span class="cwebmacronumber">20.1</span>&gt;
<span class="identifier">unicode</span><span class="plain"> ... | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_SayUnicode problem</span> <span class="cwebmacronumber">20.2</span>&gt;
<span class="plain">...</span><span class="element"> condition</span><span class="plain"> | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_SayUnknownCondition problem</span> <span class="cwebmacronumber">20.4</span>&gt;
<span class="identifier">otherwise</span><span class="plain">/</span><span class="reserved">else</span><span class="plain"> *** | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_SayElseMisplaced problem</span> <span class="cwebmacronumber">20.3</span>&gt;
<span class="plain">... ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_SayUnknown problem</span> <span class="cwebmacronumber">20.5</span>&gt;
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP20_1"></a><b>&#167;20.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_SayComma problem</span> <span class="cwebmacronumber">20.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<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_SayComma</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the line %1, I was expecting that '%2' would be something to "</span>
<span class="string">"'say', but unexpectedly it began with a comma. The usual form is "</span>
<span class="string">"just 'say \</span><span class="plain">"</span><span class="string">text\</span><span class="plain">"</span><span class="string">', perhaps with some substitutions in square "</span>
<span class="string">"brackets within the quoted text, but no commas."</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="#SP20">&#167;20</a>.</p>
<p class="inwebparagraph"><a id="SP20_2"></a><b>&#167;20.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_SayUnicode problem</span> <span class="cwebmacronumber">20.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<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_SayUnicode</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the line %1, I was expecting that '%2' would be something to "</span>
<span class="string">"'say', but it didn't look like any form of 'say' that I know. "</span>
<span class="string">"So I tried to read '%2' as a Unicode character, which seemed "</span>
<span class="string">"likely because of the word 'unicode', but that didn't work either. "</span>
<span class="string">"%PUnicode characters can be written either using their decimal "</span>
<span class="string">"numbers - for instance, 'Unicode 2041' - or with their standard "</span>
<span class="string">"names - 'Unicode Latin small ligature oe'. For efficiency reasons "</span>
<span class="string">"these names are only available if you ask for them; to make them "</span>
<span class="string">"available, you need to 'Include Unicode Character Names by Graham "</span>
<span class="string">"Nelson' or, if you really need more, 'Include Unicode Full "</span>
<span class="string">"Character Names by Graham Nelson'."</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="#SP20">&#167;20</a>.</p>
<p class="inwebparagraph"><a id="SP20_3"></a><b>&#167;20.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_SayElseMisplaced problem</span> <span class="cwebmacronumber">20.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<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_SayElseMisplaced</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the line %1, I was expecting that '%2' would be something to "</span>
<span class="string">"'say', but unexpectedly I found an 'otherwise' (or 'else'). That "</span>
<span class="string">"would be fine inside an '[if ...]' part of the text, but doesn't "</span>
<span class="string">"make sense on its own."</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="#SP20">&#167;20</a>.</p>
<p class="inwebparagraph"><a id="SP20_4"></a><b>&#167;20.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_SayUnknownCondition problem</span> <span class="cwebmacronumber">20.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<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_SayUnknownCondition</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the line %1, I was expecting that '%2' would be something to "</span>
<span class="string">"'say', but it didn't look like any form of 'say' that I know. So "</span>
<span class="string">"I tried to read '%2' as a value of some kind (because it's legal "</span>
<span class="string">"to say values), but couldn't make sense of it that way either. "</span>
<span class="string">"%PSometimes this happens because punctuation has gone wrong - "</span>
<span class="string">"for instance, if you've omitted a semicolon or full stop at the "</span>
<span class="string">"end of the 'say' phrase."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"%PNames which end in 'condition' often represent the current "</span>
<span class="string">"state of something which can be in any one of three or more "</span>
<span class="string">"states. This will only be the case if you have explicitly said "</span>
<span class="string">"so, with a line like 'The rocket is either dry, fuelled or launched.' - "</span>
<span class="string">"in which case the value 'rocket condition' will always be one "</span>
<span class="string">"of 'dry', 'fuelled' or 'launched'. Note that all of this only "</span>
<span class="string">"applies to a list of three or more possibilities - a thing can "</span>
<span class="string">"have any number of either/or properties. For instance, a "</span>
<span class="string">"container is open or closed, but it also transparent or opaque. "</span>
<span class="string">"Neither of these counts as its 'condition'."</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="#SP20">&#167;20</a>.</p>
<p class="inwebparagraph"><a id="SP20_5"></a><b>&#167;20.5. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_SayUnknown problem</span> <span class="cwebmacronumber">20.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<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_SayUnknown</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the line %1, I was expecting that '%2' would be something to "</span>
<span class="string">"'say', but it didn't look like any form of 'say' that I know. So "</span>
<span class="string">"I tried to read '%2' as a value of some kind (because it's legal "</span>
<span class="string">"to say values), but couldn't make sense of it that way either. "</span>
<span class="string">"%PSometimes this happens because punctuation has gone wrong - "</span>
<span class="string">"for instance, if you've omitted a semicolon or full stop at the "</span>
<span class="string">"end of the 'say' phrase."</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="#SP20">&#167;20</a>.</p>
<p class="inwebparagraph"><a id="SP19_2_2"></a><b>&#167;19.2.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Unknown found text occurs as a text substitution</span> <span class="cwebmacronumber">19.2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">&lt;</span><span class="identifier">unknown</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">-</span><span class="identifier">substitution</span><span class="plain">-</span><span class="identifier">problem</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19_2">&#167;19.2</a>.</p>
<p class="inwebparagraph"><a id="SP19_2_3"></a><b>&#167;19.2.3. </b>It's a bit unenlightening when an entire condition is rejected as
unknown if, in fact, only one of perhaps many clauses is broken. We
therefore produce quite an elaborate problem message which goes through
the clauses, summing up their status in turn:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">INVALID_CP_BIT</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">WHENWHILE_CP_BIT</span><span class="plain"> 2</span>
</pre>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem message for a compound condition which has gone bad</span> <span class="cwebmacronumber">19.2.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<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_CompoundConditionFailed</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the sentence %1, I was expecting that '%2' would be a condition. "</span>
<span class="string">"It didn't make sense as one long phrase, but because it was divided up by "</span>
<span class="string">"'and'/'or', I tried breaking it down into smaller conditions, but "</span>
<span class="string">"that didn't work either. "</span><span class="plain">);</span>
<span class="plain">&lt;</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">problem</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</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">dubious</span><span class="plain"> = &lt;&lt;</span><span class="identifier">r</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">dubious</span><span class="plain"> &amp; </span><span class="constant">INVALID_CP_BIT</span><span class="plain">)</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"so I ran out of ideas."</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"but that combination of conditions isn't allowed to be joined "</span>
<span class="string">"together with 'and' or 'or', because that would just be too confusing. "</span>
<span class="string">"%PFor example, 'if the player is carrying a container or a "</span>
<span class="string">"supporter' has an obvious meaning in English, but Inform reads "</span>
<span class="string">"it as two different conditions glued together: 'if the player is "</span>
<span class="string">"carrying a container', and also 'a supporter'. The meaning of "</span>
<span class="string">"the first is obvious. The second part is true if the current "</span>
<span class="string">"item under discussion is a supporter - for instance, the noun of "</span>
<span class="string">"the current action, or the item to which a definition applies. "</span>
<span class="string">"Both of these conditions are useful in different circumstances, "</span>
<span class="string">"but combining them in one condition like this makes a very "</span>
<span class="string">"misleading line of text. So Inform disallows it."</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">dubious</span><span class="plain"> &amp; </span><span class="constant">WHENWHILE_CP_BIT</span><span class="plain">)</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"%PI notice there's a 'when' or 'while' being used as the opening "</span>
<span class="string">"word of one of those conditions, though; maybe that's the problem?"</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="#SP19_2">&#167;19.2</a>.</p>
<p class="inwebparagraph"><a id="SP21"></a><b>&#167;21. </b>These are cases where the wording used in the source text suggests some
common misunderstanding.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">unknown</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">-</span><span class="identifier">problem</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt; ::=</span>
<span class="identifier">turns</span><span class="plain"> | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_NumberOfTurns problem</span> <span class="cwebmacronumber">21.1</span>&gt;
<span class="plain">... </span><span class="identifier">is</span><span class="plain">/</span><span class="identifier">are</span><span class="plain"> </span><span class="identifier">out</span><span class="plain"> </span><span class="identifier">of</span><span class="plain"> </span><span class="identifier">play</span><span class="plain"> | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_OutOfPlay problem</span> <span class="cwebmacronumber">21.2</span>&gt;
<span class="identifier">unicode</span><span class="plain"> ... | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_MidTextUnicode problem</span> <span class="cwebmacronumber">21.5</span>&gt;
<span class="plain">...</span><span class="element"> condition</span><span class="plain"> | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_UnknownCondition problem</span> <span class="cwebmacronumber">21.6</span>&gt;
<span class="plain">... ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_Unknown problem</span> <span class="cwebmacronumber">21.8</span>&gt;
<span class="plain">&lt;</span><span class="identifier">unknown</span><span class="plain">-</span><span class="identifier">use</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt; ::=</span>
<span class="plain">... ^</span><span class="identifier">option</span><span class="plain"> | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_OptionlessOption problem</span> <span class="cwebmacronumber">21.3</span>&gt;
<span class="plain">... ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_Unknown problem</span> <span class="cwebmacronumber">21.8</span>&gt;
<span class="plain">&lt;</span><span class="identifier">unknown</span><span class="reserved">-activity</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt; ::=</span>
<span class="plain">... </span><span class="identifier">of</span><span class="plain"> | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_ActivityOf problem</span> <span class="cwebmacronumber">21.4</span>&gt;
<span class="plain">... </span><span class="reserved">for</span><span class="plain"> | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_ActivityWithFor problem</span> <span class="cwebmacronumber">21.7</span>&gt;
<span class="plain">... ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_Unknown problem</span> <span class="cwebmacronumber">21.8</span>&gt;
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP21_1"></a><b>&#167;21.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_NumberOfTurns problem</span> <span class="cwebmacronumber">21.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<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_NumberOfTurns</span><span class="plain">));</span>
&lt;<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"%PPerhaps by 'turns' you meant the number of turns of play to date? "</span>
<span class="string">"If so, try 'turn count' instead."</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="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP21_2"></a><b>&#167;21.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_OutOfPlay problem</span> <span class="cwebmacronumber">21.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<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_OutOfPlay</span><span class="plain">));</span>
&lt;<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"%PPeople sometimes say that things or people removed from all "</span>
<span class="string">"rooms are 'out of play', but Inform uses the adjective "</span>
<span class="string">"'off-stage' - for instance, 'if the ball is off-stage'. "</span>
<span class="string">"If you would like 'out of play' to work, you could always "</span>
<span class="string">"write 'Definition: A thing is out of play if it is off-stage.' "</span>
<span class="string">"Then the two would be equivalent."</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="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP21_3"></a><b>&#167;21.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_OptionlessOption problem</span> <span class="cwebmacronumber">21.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<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_OptionlessOption</span><span class="plain">));</span>
&lt;<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"%PThe names of use options, on the rare occasions when they "</span>
<span class="string">"appear as values, always end with the word 'option' - for "</span>
<span class="string">"instance, we have to write 'American dialect option' not "</span>
<span class="string">"'American dialect'. As your text here doesn't end with the "</span>
<span class="string">"word 'option', perhaps you've forgotten this arcane rule?"</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="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP21_4"></a><b>&#167;21.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_ActivityOf problem</span> <span class="cwebmacronumber">21.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<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_ActivityOf</span><span class="plain">));</span>
&lt;<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"%PActivity names rarely end with 'of': for instance, when we talk "</span>
<span class="string">"about 'printing the name of something', properly speaking "</span>
<span class="string">"the activity is called 'printing the name'. Maybe that's it?"</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="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP21_5"></a><b>&#167;21.5. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_MidTextUnicode problem</span> <span class="cwebmacronumber">21.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<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_MidTextUnicode</span><span class="plain">));</span>
&lt;<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"%PMaybe you intended this to produce a Unicode character? "</span>
<span class="string">"Unicode characters can be written either using their decimal "</span>
<span class="string">"numbers - for instance, 'Unicode 2041' - or with their standard "</span>
<span class="string">"names - 'Unicode Latin small ligature oe'. For efficiency reasons "</span>
<span class="string">"these names are only available if you ask for them; to make them "</span>
<span class="string">"available, you need to 'Include Unicode Character Names by Graham "</span>
<span class="string">"Nelson' or, if you really need more, 'Include Unicode Full "</span>
<span class="string">"Character Names by Graham Nelson'."</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="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP21_6"></a><b>&#167;21.6. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_UnknownCondition problem</span> <span class="cwebmacronumber">21.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<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_UnknownCondition</span><span class="plain">));</span>
&lt;<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"%PNames which end in 'condition' often represent the current "</span>
<span class="string">"state of something which can be in any one of three or more "</span>
<span class="string">"states. Names like this only work if you've declared them, with "</span>
<span class="string">"a line like 'The rocket is either dry, fuelled or launched.' - "</span>
<span class="string">"in which case the value 'rocket condition' will always be one "</span>
<span class="string">"of 'dry', 'fuelled' or 'launched'. Maybe you forgot to declare "</span>
<span class="string">"something like this, or mis-spelled the name of the owner?"</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="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP21_7"></a><b>&#167;21.7. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_ActivityWithFor problem</span> <span class="cwebmacronumber">21.7</span>&gt; =
</code></p>
<pre class="displaydefn">
<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_ActivityWithFor</span><span class="plain">));</span>
&lt;<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"%PWere you by any chance meaning to refer to an activity by name, "</span>
<span class="string">"and used the word 'for' at the end of that name? If so, try removing "</span>
<span class="string">"just the word 'for'."</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="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP21_8"></a><b>&#167;21.8. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_Unknown problem</span> <span class="cwebmacronumber">21.8</span>&gt; =
</code></p>
<pre class="displaydefn">
<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_Unknown</span><span class="plain">));</span>
&lt;<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>&gt;<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="#SP21">&#167;21</a> (three times).</p>
<p class="inwebparagraph"><a id="SP21_1_1"></a><b>&#167;21.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the sentence %1, I was expecting to read %3, but instead found some "</span>
<span class="string">"text that I couldn't understand - '%2'. "</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP21_1">&#167;21.1</a>, <a href="#SP21_2">&#167;21.2</a>, <a href="#SP21_3">&#167;21.3</a>, <a href="#SP21_4">&#167;21.4</a>, <a href="#SP21_5">&#167;21.5</a>, <a href="#SP21_6">&#167;21.6</a>, <a href="#SP21_7">&#167;21.7</a>, <a href="#SP21_8">&#167;21.8</a>.</p>
<p class="inwebparagraph"><a id="SP19_2_4"></a><b>&#167;19.2.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem message for miscellaneous suspicious wordings</span> <span class="cwebmacronumber">19.2.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">kind_expected</span><span class="plain">, </span><span class="identifier">K_use_option</span><span class="plain">)) {</span>
<span class="plain">&lt;</span><span class="identifier">unknown</span><span class="plain">-</span><span class="identifier">use</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">kind_expected</span><span class="plain">) == </span><span class="identifier">CON_activity</span><span class="plain">) {</span>
<span class="plain">&lt;</span><span class="identifier">unknown</span><span class="reserved">-activity</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="plain">&lt;</span><span class="identifier">unknown</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">-</span><span class="identifier">problem</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</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">This code is used in <a href="#SP19_2">&#167;19.2</a>.</p>
<p class="inwebparagraph"><a id="SP19_3"></a><b>&#167;19.3. Rule (5.b). </b>This is all concerned with a shorthand far more convenient to an Inform author
than it is to us &mdash; where a property's name is used without any indication of
its owner.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (5.b) Deal with bare property names</span> <span class="cwebmacronumber">19.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(5.b)"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">kind_expected</span><span class="plain">) != </span><span class="identifier">CON_property</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">check</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::is</span><span class="plain">(</span><span class="identifier">check</span><span class="plain">, </span><span class="identifier">AMBIGUITY_NT</span><span class="plain">)) </span><span class="identifier">check</span><span class="plain"> = </span><span class="identifier">check</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Rvalues::is_CONSTANT_construction</span><span class="plain">(</span><span class="identifier">check</span><span class="plain">, </span><span class="identifier">CON_property</span><span class="plain">)) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_property</span><span class="plain">(</span><span class="identifier">check</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Step (5.b.2) If a bare property name is used where we expect a value, coerce it if the kinds allow</span> <span class="cwebmacronumber">19.3.1</span>&gt;<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="#SP19">&#167;19</a>.</p>
<p class="inwebparagraph"><a id="SP19_3_1"></a><b>&#167;19.3.1. </b>But more often we want a value which just happens in this case to come
from a property. For instance, in a text routine printing a description
like "The cedarwood box could hold [carrying capacity in words]
item[s].", we want "carrying capacity" to be a number value, and we
treat it as if it read "carrying capacity of the cedarwood box".
</p>
<p class="inwebparagraph">We don't coerce if the property holds a relation, because letting a variable
be a description of a relation tries to create a local relation on the
stack frame, and this is unlikely to be what anyone wanted.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (5.b.2) If a bare property name is used where we expect a value, coerce it if the kinds allow</span> <span class="cwebmacronumber">19.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(5.b.2)"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kind_expected</span><span class="plain">) {</span>
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(5.b.2a)"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::is_value_property</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">)) {</span>
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(5.b.2b)"</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_if_coerced</span><span class="plain"> = </span><span class="functiontext">Properties::Valued::kind</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">verdict</span><span class="plain"> = </span><span class="identifier">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">kind_if_coerced</span><span class="plain">, </span><span class="identifier">kind_expected</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">verdict</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) {</span>
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(5.b.2c)"</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Coerce into a property of the "self" object</span> <span class="cwebmacronumber">19.3.1.1</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">verdict</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">kind_expected</span><span class="plain">) == </span><span class="identifier">CON_description</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">kind_if_coerced</span><span class="plain">) != </span><span class="identifier">CON_relation</span><span class="plain">)) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(5.b.2) coercing to description\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">become</span><span class="plain"> = </span><span class="functiontext">Specifications::from_kind</span><span class="plain">(</span><span class="identifier">kind_if_coerced</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">become</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="identifier">ParseTree::copy_in_place</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="functiontext">Descriptions::to_rvalue</span><span class="plain">(</span><span class="identifier">become</span><span class="plain">));</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(5.b.2) declining to cast into property value form\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">verdict</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19_3">&#167;19.3</a>.</p>
<p class="inwebparagraph"><a id="SP19_3_1_1"></a><b>&#167;19.3.1.1. </b>The tricky part is working out what the implicitly meant object is, a
classic donkey anaphora-style problem in linguistics. We don't even begin
to solve that here: indeed the decision is taken rather indirectly, because
we simply compile code which uses Inform 6's <code class="display"><span class="extract">self</span></code> variable to refer to
the owner. The I6 library and our own run-time code conspire to ensure that
<code class="display"><span class="extract">self</span></code> is always equal to something sensible.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Coerce into a property of the "self" object</span> <span class="cwebmacronumber">19.3.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">was</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="identifier">next_alternative</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">pr</span><span class="plain"> = </span><span class="identifier">ParseTree::duplicate</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="identifier">pr</span><span class="plain">-&gt;</span><span class="identifier">next_alternative</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">become</span><span class="plain"> = </span><span class="functiontext">Lvalues::new_PROPERTY_VALUE</span><span class="plain">(</span><span class="identifier">pr</span><span class="plain">, </span><span class="functiontext">Rvalues::new_self_object_constant</span><span class="plain">());</span>
<span class="identifier">ParseTree::copy</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">become</span><span class="plain">);</span>
<span class="identifier">p</span><span class="plain">-&gt;</span><span class="identifier">next_alternative</span><span class="plain"> = </span><span class="identifier">was</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(5.b) coercing PROPERTY to PROPERTY VALUE: $P\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19_3_1">&#167;19.3.1</a>.</p>
<p class="inwebparagraph"><a id="SP19_4"></a><b>&#167;19.4. Rule (5.c). </b>An unchecked SP can contain a proposition which, though valid as a
predicate calculus sentence, makes no sense for type reasons: for instance,
"the Orange Room is 10" compiles to a valid sentence but one in which the
binary predicate for equality is applied to incomparable SPs. To type-check,
we must prove that any proposition needed is valid on these grounds, and we
delegate that to "Type Check Propositions.w".
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (5.c) Deal with any attached proposition</span> <span class="cwebmacronumber">19.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(5.c)"</span><span class="plain">);</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">desired_to</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">TEST_PROPOSITION_NT</span><span class="plain">)) </span><span class="identifier">desired_to</span><span class="plain"> = </span><span class="string">"be a condition"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Descriptions::is_complex</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)) </span><span class="identifier">desired_to</span><span class="plain"> = </span><span class="string">"be a description"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">desired_to</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Calculus::Propositions::Checker::type_check</span><span class="plain">(</span><span class="functiontext">Specifications::to_proposition</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">),</span>
<span class="functiontext">Calculus::Propositions::Checker::tc_no_problem_reporting</span><span class="plain">())</span>
<span class="plain">== </span><span class="identifier">NEVER_MATCH</span><span class="plain">) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(5.c) on $P failed proposition type-checking: $D\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">p</span><span class="plain">, </span><span class="functiontext">Specifications::to_proposition</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="constant">THIS_IS_A_GROSS_PROBLEM</span><span class="plain">;</span>
<span class="functiontext">Calculus::Propositions::Checker::type_check</span><span class="plain">(</span><span class="functiontext">Specifications::to_proposition</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">),</span>
<span class="functiontext">Calculus::Propositions::Checker::tc_problem_reporting</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">), </span><span class="identifier">desired_to</span><span class="plain">));</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> { </span><span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(5.c) Okay!"</span><span class="plain">); }</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19">&#167;19</a>.</p>
<p class="inwebparagraph"><a id="SP19_5"></a><b>&#167;19.5. Rule (5.d). </b>Something of a grab-bag, this one. What these three situations have in common
is that all use the typechecker to clarify ambiguities in syntax.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (5.d) Apply miscellaneous other coercions</span> <span class="cwebmacronumber">19.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
&lt;<span class="cwebmacro">Step (5.d.1) Coerce TEST ACTION to constant action</span> <span class="cwebmacronumber">19.5.1</span>&gt;<span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
&lt;<span class="cwebmacro">Step (5.d.2) Coerce constant TEXT and TEXT ROUTINE to UNDERSTANDING</span> <span class="cwebmacronumber">19.5.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Step (5.d.3) Coerce a description to a value, if we expect a noun-like description</span> <span class="cwebmacronumber">19.5.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Step (5.d.4) Reject plausible but wrong uses due to use of inline-only types in phrases</span> <span class="cwebmacronumber">19.5.4</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19">&#167;19</a>.</p>
<p class="inwebparagraph"><a id="SP19_5_1"></a><b>&#167;19.5.1. </b>An action pattern can be an action if specific enough, and this is
crucial: it enables phrases such as "try taking the box" to work. When
such phrases are type-checked, they expect the argument to be a constant
action value, which is a specific action.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (5.d.1) Coerce TEST ACTION to constant action</span> <span class="cwebmacronumber">19.5.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(5.d.1)"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Conditions::is_TEST_ACTION</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)) &amp;&amp; (</span><span class="identifier">kind_expected</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">K_stored_action</span><span class="plain">, </span><span class="identifier">kind_expected</span><span class="plain">))) {</span>
<span class="identifier">action_pattern</span><span class="plain"> *</span><span class="identifier">ap</span><span class="plain"> = </span><span class="identifier">ParseTree::get_constant_action_pattern</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PL::Actions::Patterns::is_unspecific</span><span class="plain">(</span><span class="identifier">ap</span><span class="plain">)) {</span>
<span class="constant">THIS_IS_A_GROSSER_THAN_GROSS_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</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_ActionNotSpecific</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but '%2' is too vague to describe a specific action. "</span>
<span class="string">"%PIt has to be an exact instruction about what is being done, and "</span>
<span class="string">"to what. For instance, 'taking the box' is fine, but 'dropping or "</span>
<span class="string">"taking something openable' is not."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PL::Actions::Patterns::is_overspecific</span><span class="plain">(</span><span class="identifier">ap</span><span class="plain">)) {</span>
<span class="constant">THIS_IS_A_GROSSER_THAN_GROSS_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</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_ActionTooSpecific</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but '%2' imposes too many restrictions on the "</span>
<span class="string">"action to be carried out, by saying something about the "</span>
<span class="string">"circumstances which you can't guarantee will be true. "</span>
<span class="string">"%PSometimes this problem appears because I've misread text like "</span>
<span class="string">"'in ...' as a clause saying that the action takes place in a "</span>
<span class="string">"particular room, when in fact it was part of the name of one of "</span>
<span class="string">"the items involved. If that's the problem, try using 'let' to "</span>
<span class="string">"create a simpler name for it, and then rewrite the 'try' to use "</span>
<span class="string">"that simpler name - the ambiguity should then vanish."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">ParseTree::copy_in_place</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">);</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Coerced to sa: $P\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">condition_context</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">CONSTANT_NT</span><span class="plain">))) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">E</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</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">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">K_stored_action</span><span class="plain">)) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">val</span><span class="plain"> = </span><span class="identifier">ParseTree::duplicate</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="identifier">ParseTree::copy_in_place</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">TEST_VALUE_NT</span><span class="plain">));</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">val</span><span class="plain">));</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">val</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Coerced back again to sa: $P\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">ALWAYS_MATCH</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="#SP19_5">&#167;19.5</a>.</p>
<p class="inwebparagraph"><a id="SP19_5_2"></a><b>&#167;19.5.2. </b>The following applies only to literal text in double-quotes, which might
or might not include text substitutions in square brackets: if we check it
against "understanding", then we are trying to interpret it as a grammar
to parse rather than text to print. We need to coerce since these have very
different representations at run-time.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (5.d.2) Coerce constant TEXT and TEXT ROUTINE to UNDERSTANDING</span> <span class="cwebmacronumber">19.5.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(5.d.2)"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Rvalues::is_CONSTANT_of_kind</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">K_text</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">K_understanding</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">kind_expected</span><span class="plain">, </span><span class="identifier">K_understanding</span><span class="plain">))) {</span>
<span class="identifier">ParseTree::set_kind_of_value</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">K_understanding</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19_5">&#167;19.5</a>.</p>
<p class="inwebparagraph"><a id="SP19_5_3"></a><b>&#167;19.5.3. </b>Another ambiguity is that the text "women who are in lighted rooms" in:
</p>
<blockquote>
<p>let N be the number of women who are in lighted rooms;</p>
</blockquote>
<p class="inwebparagraph">...is parsed as a description, a condition. But in
fact it's a noun here &mdash; it has to be a value, in fact, which can go into
the "number of..." phrase as an argument. We make this happen by coercing
it to a constant value, using the "description of..." constructor.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (5.d.3) Coerce a description to a value, if we expect a noun-like description</span> <span class="cwebmacronumber">19.5.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(5.d.3)"</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">domain</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">kind_expected</span><span class="plain">) == </span><span class="identifier">CON_description</span><span class="plain">) {</span>
<span class="identifier">domain</span><span class="plain"> = </span><span class="identifier">Kinds::unary_construction_material</span><span class="plain">(</span><span class="identifier">kind_expected</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">domain</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Specifications::is_description</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">))) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(5.d.3) requiring description of $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">domain</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">K_object</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(5.d.3) finding description of $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">made_match</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="identifier">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">domain</span><span class="plain">) == </span><span class="identifier">NEVER_MATCH</span><span class="plain">) </span><span class="identifier">made_match</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Throw out the wrong sort of description with a seldom-seen problem message</span> <span class="cwebmacronumber">19.5.3.2</span>&gt;<span class="plain">;</span>
<span class="identifier">quantifier</span><span class="plain"> *</span><span class="identifier">q</span><span class="plain"> = </span><span class="functiontext">Descriptions::get_quantifier</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">q</span><span class="plain">) &amp;&amp; (</span><span class="identifier">q</span><span class="plain"> != </span><span class="identifier">not_exists_quantifier</span><span class="plain">) &amp;&amp; (</span><span class="identifier">q</span><span class="plain"> != </span><span class="identifier">for_all_quantifier</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Issue a problem message for a quantified proposition in the description</span> <span class="cwebmacronumber">19.5.3.1</span>&gt;<span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">as_con</span><span class="plain"> = </span><span class="functiontext">Descriptions::to_rvalue</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">as_con</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Issue a problem message for a malformed proposition in the description</span> <span class="cwebmacronumber">19.5.3.3</span>&gt;<span class="plain">;</span>
<span class="identifier">ParseTree::copy_in_place</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">as_con</span><span class="plain">);</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</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">ALWAYS_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19_5">&#167;19.5</a>.</p>
<p class="inwebparagraph"><a id="SP19_5_3_1"></a><b>&#167;19.5.3.1. </b>This is for undescriptive descriptions, really.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem message for a quantified proposition in the description</span> <span class="cwebmacronumber">19.5.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_AN_INTERESTING_PROBLEM</span><span class="plain"> {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</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_BadQuantifierInDescription</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In %1 you wrote the description '%2' in the context of a value, "</span>
<span class="string">"but descriptions used that way are not allowed to talk about "</span>
<span class="string">"quantities. For example, it's okay to write 'an even number' "</span>
<span class="string">"as a description value, but not 'three numbers' or 'most numbers'."</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">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19_5_3">&#167;19.5.3</a>.</p>
<p class="inwebparagraph"><a id="SP19_5_3_2"></a><b>&#167;19.5.3.2. </b>The following message is seldom seen since most phrases using descriptions
are set up with two parallel versions. As every description matches exactly one
of these, there won't be a problem. But just in case the user has intentionally
defined a phrase for only one case:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Throw out the wrong sort of description with a seldom-seen problem message</span> <span class="cwebmacronumber">19.5.3.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">made_match</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">domain</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">BelievedImpossible</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the line %1, the text '%2' seems to be a description of %3, but "</span>
<span class="string">"a description of %4 was required."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19_5_3">&#167;19.5.3</a>.</p>
<p class="inwebparagraph"><a id="SP19_5_3_3"></a><b>&#167;19.5.3.3. </b>I can't see an easy proof that this can never occur, but nor can I make it
happen. The problem message is just in case someone finds a way. It appears
if the description has a proposition with other than one free variable, once
any universal quantifier ("all", etc.) is removed.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem message for a malformed proposition in the description</span> <span class="cwebmacronumber">19.5.3.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</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">BelievedImpossible</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the line %1, the text '%2' is given where a description of a collection "</span>
<span class="string">"of things or values was required. For instance, 'rooms which contain "</span>
<span class="string">"something', or 'closed containers' - note that there is no need to say "</span>
<span class="string">"'all' or 'every' in this context, as that is understood already."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19_5_3">&#167;19.5.3</a>.</p>
<p class="inwebparagraph"><a id="SP19_5_4"></a><b>&#167;19.5.4. </b>It might look as if this ought to be checked when phrase definitions are
made; the trouble is, "action", "condition" and so on are valid
in phrase definitions, but only in inline-defined ones. We don't want to get
into all that here, because the message is aimed more at Inform novices who
have made an understandable confusion.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (5.d.4) Reject plausible but wrong uses due to use of inline-only types in phrases</span> <span class="cwebmacronumber">19.5.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTreeUsage::is_lvalue</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</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">BelievedImpossible</span><span class="plain">)); </span> <span class="comment">screened out at definition time</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the line %1, '%2' ought to be a value, but isn't - there must be "</span>
<span class="string">"something fishy about the way it was created. %P"</span>
<span class="string">"Usually this happens because it is one of the named items in "</span>
<span class="string">"a phrase definition, but stood for a chunk of text which can't "</span>
<span class="string">"be a value - for instance, 'To marvel at (feat - an action)' "</span>
<span class="string">"doesn't make 'feat' a value. (Calling it a 'stored action' "</span>
<span class="string">"would have been fine; and similarly, if you want something "</span>
<span class="string">"which is either true or false, use 'truth state' not 'condition'.)"</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</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="#SP19_5">&#167;19.5</a>.</p>
<p class="inwebparagraph"><a id="SP19_6"></a><b>&#167;19.6. Rule (5.e). </b>The "main rule" is, as we shall see, that <code class="display"><span class="extract">p</span></code> should have the same
species as <code class="display"><span class="extract">expected</span></code>, or if <code class="display"><span class="extract">expected</span></code> give no species then at least it
should have the same family. The two exceptional cases are when <code class="display"><span class="extract">expected</span></code>
is a description such as "an even number", or the name of a kind of value
such as "a scene", in which case we allow <code class="display"><span class="extract">p</span></code> if it's a value which
meets these requirements.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (5.e) The Main Rule of Type-Checking</span> <span class="cwebmacronumber">19.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">exceptional_case</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Step (5.e.2) Exception: when expecting a generic or actual CONSTANT</span> <span class="cwebmacronumber">19.6.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">exceptional_case</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span>&lt;<span class="cwebmacro">Step (5.e.3) Main rule</span> <span class="cwebmacronumber">19.6.2</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19">&#167;19</a>.</p>
<p class="inwebparagraph"><a id="SP19_6_1"></a><b>&#167;19.6.1. </b>Now for the related, but slightly simpler, case of matching the name of a
kind. Suppose we are parsing "award 5 points" against
</p>
<blockquote>
<p>To award (N - a number) points: ...</p>
</blockquote>
<p class="inwebparagraph">Here <code class="display"><span class="extract">p</span></code> will be the actual constant value 5, and <code class="display"><span class="extract">expected</span></code> the
generic constant value with kind "number".
</p>
<p class="inwebparagraph">A phrase which returns a value must have its own return value's kind
checked. Unfortunately we can't do that yet: we want to wait until
recursive type-checking has removed incorrect invocations before drawing a
conclusion about the return kind of the phrase.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (5.e.2) Exception: when expecting a generic or actual CONSTANT</span> <span class="cwebmacronumber">19.6.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(5.e.2)"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">kind_expected</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">ParseTreeUsage::is_value</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::is</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">PHRASE_TO_DECIDE_VALUE_NT</span><span class="plain">)) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"(5.e.2) exempting phrase from return value checking for now\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::compatible</span><span class="plain">(</span>
<span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">),</span>
<span class="identifier">kind_expected</span><span class="plain">)) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">:</span>
&lt;<span class="cwebmacro">Fail with a mismatched value problem message</span> <span class="cwebmacronumber">19.6.1.1</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">:</span>
<span class="identifier">outcome</span><span class="plain"> = </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"dropping to sometimes level\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">outcome</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">: </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">exceptional_case</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19_6">&#167;19.6</a>.</p>
<p class="inwebparagraph"><a id="SP19_6_1_1"></a><b>&#167;19.6.1.1. </b>This is the error message a typical C compiler's type-checker would issue;
it says the value has the wrong kind.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Fail with a mismatched value problem message</span> <span class="cwebmacronumber">19.6.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Offending subtree: $T\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="identifier">kind_expected</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">LOCAL_VARIABLE_NT</span><span class="plain">)) {</span>
<span class="reserved">local_variable</span><span class="plain"> *</span><span class="identifier">lvar</span><span class="plain"> = </span><span class="identifier">ParseTree::get_constant_local_variable</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="functiontext">LocalVariables::kind</span><span class="plain">(</span><span class="identifier">lvar</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_LocalMismatch</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but '%2' is a temporary name for %4 (created by 'let' "</span>
<span class="string">"or 'repeat'), whereas I was expecting to find %3 there."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">kind_expected</span><span class="plain">, </span><span class="identifier">K_sayable_value</span><span class="plain">)) {</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">p</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_AllSayInvsFailed</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">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)))</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but that only works for sayable values, that is, "</span>
<span class="string">"values which I can display in text form. '%2' isn't one of those "</span>
<span class="string">"values: it's %4, a kind which isn't sayable."</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but that only works for sayable values, that is, "</span>
<span class="string">"values which I can display in text form. This isn't one of those "</span>
<span class="string">"values: it's %4, a kind which isn't sayable."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Found: $u; Expected: $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">),</span>
<span class="identifier">kind_expected</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">p</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_TypeMismatch</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">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)))</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but that has the wrong kind of value: %4 rather than %3."</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but '%2' has the wrong kind of value: %4 rather than %3."</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">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19_6_1">&#167;19.6.1</a>.</p>
<p class="inwebparagraph"><a id="SP19_6_2"></a><b>&#167;19.6.2. </b>We now apply the main rule, supposing that neither of the exceptional cases
has intervened to stop us getting here. The found and expected specifications
must have the same family and, unless the expected species is <code class="display"><span class="extract">UNKNOWN_NT</span></code>, the
same species as well.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Step (5.e.3) Main rule</span> <span class="cwebmacronumber">19.6.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG_DASH</span><span class="plain">(</span><span class="string">"(5.e.3)"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">kind_expected</span><span class="plain">) || (</span><span class="identifier">condition_context</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">condition_found</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">ParseTreeUsage::is_condition</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)) </span><span class="identifier">condition_found</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="identifier">condition_found</span><span class="plain"> != </span><span class="identifier">condition_context</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Specifications::is_description</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)) &amp;&amp; (</span><span class="identifier">kind_expected</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Fail with a warning about literal descriptions</span> <span class="cwebmacronumber">19.6.2.1</span>&gt;
<span class="reserved">else</span>
&lt;<span class="cwebmacro">Fail with a catch-all typechecking problem message</span> <span class="cwebmacronumber">19.6.2.2</span>&gt;<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="#SP19_6">&#167;19.6</a>.</p>
<p class="inwebparagraph"><a id="SP19_6_2_1"></a><b>&#167;19.6.2.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Fail with a warning about literal descriptions</span> <span class="cwebmacronumber">19.6.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Descriptions::is_complex</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)) {</span>
<span class="constant">THIS_IS_AN_INTERESTING_PROBLEM</span><span class="plain"> {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="identifier">kind_expected</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind_of</span><span class="plain">(4, </span><span class="identifier">p</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_GenericDescription</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but '%2' is used in a context where I'd expect to see "</span>
<span class="string">"a (single) specific example of %3. Although what you wrote did "</span>
<span class="string">"make sense as a description, it could refer to many different "</span>
<span class="string">"values or to none, so it wasn't specific enough."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="constant">THIS_IS_AN_INTERESTING_PROBLEM</span><span class="plain"> {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="identifier">kind_expected</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind_of</span><span class="plain">(4, </span><span class="identifier">p</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_LiteralDescriptionAsValue</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but '%2' is used in a context where I'd expect to see "</span>
<span class="string">"a (single) specific example of %3, not a description."</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Specifications::is_kind_like</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">), </span><span class="identifier">K_time</span><span class="plain">)))</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">" %P(If you meant the current time, this is called 'time "</span>
<span class="string">"of day' in Inform to avoid confusing it with the various "</span>
<span class="string">"other meanings that the word 'time' can have.)"</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19_6_2">&#167;19.6.2</a>.</p>
<p class="inwebparagraph"><a id="SP19_6_2_2"></a><b>&#167;19.6.2.2. </b>This is the general-purpose Problem message to which the type-checker
resorts when it has nothing more specific to say.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Fail with a catch-all typechecking problem message</span> <span class="cwebmacronumber">19.6.2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">THIS_IS_AN_ORDINARY_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="identifier">kind_expected</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind_of</span><span class="plain">(4, </span><span class="identifier">p</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">BelievedImpossible</span><span class="plain">)); </span> <span class="comment">at any rate I haven't seen it lately</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but '%2' seems to be %4, whereas I was expecting to "</span>
<span class="string">"find %3 there."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19_6_2">&#167;19.6.2</a>.</p>
<p class="inwebparagraph"><a id="SP22"></a><b>&#167;22. Ambiguity testing flags. </b>To avoid filling the parse tree with unnecessary annotations, we apply these
only when resolving ambiguities, in (4A) above.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">PASSED_DASHFLAG</span><span class="plain"> 0</span><span class="identifier">x00000001</span><span class="plain"> </span> <span class="comment">once type-checked: did this pass type checking?</span>
<span class="definitionkeyword">define</span> <span class="constant">UNPROVEN_DASHFLAG</span><span class="plain"> 0</span><span class="identifier">x00000002</span><span class="plain"> </span> <span class="comment">once type-checked: will this need run-time checking?</span>
<span class="definitionkeyword">define</span> <span class="constant">GROSSLY_FAILED_DASHFLAG</span><span class="plain"> 0</span><span class="identifier">x00000004</span><span class="plain"> </span> <span class="comment">once type-checked: oh, this one failed big time</span>
<span class="definitionkeyword">define</span> <span class="constant">TESTED_DASHFLAG</span><span class="plain"> 0</span><span class="identifier">x00000008</span><span class="plain"> </span> <span class="comment">has been type-checked</span>
<span class="definitionkeyword">define</span> <span class="constant">INTERESTINGLY_FAILED_DASHFLAG</span><span class="plain"> 0</span><span class="identifier">x00000010</span><span class="plain"> </span> <span class="comment">an interesting problem message could be produced about the way this failed</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::reading_passed</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="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">PASSED_DASHFLAG</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">TESTED_DASHFLAG</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NOT_APPLICABLE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="functiontext">Dash::verdict_to_text</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">p</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="string">"(no node)"</span><span class="plain">;</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">verdict</span><span class="plain"> = </span><span class="string">"untested"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">TESTED_DASHFLAG</span><span class="plain">)) </span><span class="identifier">verdict</span><span class="plain"> = </span><span class="string">"failed"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">INTERESTINGLY_FAILED_DASHFLAG</span><span class="plain">)) </span><span class="identifier">verdict</span><span class="plain"> = </span><span class="string">"interesting"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">GROSSLY_FAILED_DASHFLAG</span><span class="plain">)) </span><span class="identifier">verdict</span><span class="plain"> = </span><span class="string">"gross"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">PASSED_DASHFLAG</span><span class="plain">)) </span><span class="identifier">verdict</span><span class="plain"> = </span><span class="string">"proven"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">UNPROVEN_DASHFLAG</span><span class="plain">)) </span><span class="identifier">verdict</span><span class="plain"> = </span><span class="string">"unproven"</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">verdict</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="functiontext">Dash::quick_verdict_to_text</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">p</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="string">"?"</span><span class="plain">;</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">verdict</span><span class="plain"> = </span><span class="string">"-"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">TESTED_DASHFLAG</span><span class="plain">)) </span><span class="identifier">verdict</span><span class="plain"> = </span><span class="string">"f"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">INTERESTINGLY_FAILED_DASHFLAG</span><span class="plain">)) </span><span class="identifier">verdict</span><span class="plain"> = </span><span class="string">"i"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">GROSSLY_FAILED_DASHFLAG</span><span class="plain">)) </span><span class="identifier">verdict</span><span class="plain"> = </span><span class="string">"g"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">PASSED_DASHFLAG</span><span class="plain">)) </span><span class="identifier">verdict</span><span class="plain"> = </span><span class="string">"p"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::test_flag</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">UNPROVEN_DASHFLAG</span><span class="plain">)) </span><span class="identifier">verdict</span><span class="plain"> = </span><span class="string">"u"</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">verdict</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::reading_passed is used in <a href="#SP10_1_1_3_1_2">&#167;10.1.1.3.1.2</a>, 22/dptd (<a href="22-dptd.html#SP4">&#167;4</a>).</p>
<p class="endnote">The function Dash::verdict_to_text is used in <a href="#SP11_9_2_2">&#167;11.9.2.2</a>, 25/in (<a href="25-in.html#SP10">&#167;10</a>).</p>
<p class="endnote">The function Dash::quick_verdict_to_text is used in <a href="#SP11_9_2_2">&#167;11.9.2.2</a>.</p>
<p class="inwebparagraph"><a id="SP23"></a><b>&#167;23. </b>The bitmap holding the results of typechecking:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Dash::set_flag</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">flag</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</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">"tried to set flag for null p"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">bm</span><span class="plain"> = </span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">epistemological_status_ANNOT</span><span class="plain">);</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">epistemological_status_ANNOT</span><span class="plain">, </span><span class="identifier">bm</span><span class="plain"> | </span><span class="identifier">flag</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Dash::clear_flags</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">p</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">"tried to clear flags for null p"</span><span class="plain">);</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">epistemological_status_ANNOT</span><span class="plain">, 0);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Dash::clear_flag</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">flag</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</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">"tried to clear flag for null p"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">bm</span><span class="plain"> = </span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">epistemological_status_ANNOT</span><span class="plain">);</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">epistemological_status_ANNOT</span><span class="plain">, </span><span class="identifier">bm</span><span class="plain"> &amp; (~</span><span class="identifier">flag</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::test_flag</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">flag</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">bm</span><span class="plain"> = (</span><span class="identifier">p</span><span class="plain">)?(</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">epistemological_status_ANNOT</span><span class="plain">)):0;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">bm</span><span class="plain"> &amp; </span><span class="identifier">flag</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::set_flag is used in <a href="#SP11_9_2_2_1">&#167;11.9.2.2.1</a>, <a href="#SP11_9_1_1">&#167;11.9.1.1</a>, <a href="#SP11_9_1_1_11">&#167;11.9.1.1.11</a>, <a href="#SP11_9_1_1_12">&#167;11.9.1.1.12</a>.</p>
<p class="endnote">The function Dash::clear_flags is used in <a href="#SP11_9_2_1_1">&#167;11.9.2.1.1</a>.</p>
<p class="endnote">The function Dash::clear_flag appears nowhere else.</p>
<p class="endnote">The function Dash::test_flag is used in <a href="#SP11_9_2_2">&#167;11.9.2.2</a>, <a href="#SP11_9_2_3_1">&#167;11.9.2.3.1</a>, <a href="#SP11_9_1_1_5_2">&#167;11.9.1.1.5.2</a>, <a href="#SP15_1">&#167;15.1</a>, <a href="#SP22">&#167;22</a>.</p>
<p class="inwebparagraph"><a id="SP24"></a><b>&#167;24. </b>A convenience sometimes needed for checking conditional clauses, like the
"when..." attached to action patterns:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::validate_conditional_clause</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain">) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">ACTION_PATTERN_PARSING</span><span class="plain">, </span><span class="string">"Validating conditional clause: $P\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">spec</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</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="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="constant">UNKNOWN_NT</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::check_condition</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">) == </span><span class="identifier">NEVER_MATCH</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::validate_conditional_clause is used in 6/rlt (<a href="6-rlt.html#SP30">&#167;30</a>), 21/ac (<a href="21-ac.html#SP10_7">&#167;10.7</a>), 23/abc (<a href="23-abc.html#SP1">&#167;1</a>).</p>
<p class="inwebparagraph"><a id="SP25"></a><b>&#167;25. </b>The exceptional treatment of the "property" kind below is to allow
"examining scenery" to be an action pattern, where an either/or property
has a name which is really a noun rather than an adjective, luring people
into treating it as such.
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">last_spec_failing_to_validate</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">last_kind_failing_to_validate</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">last_kind_found_failing_to_validate</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Dash::clear_validation_case</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">last_spec_failing_to_validate</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">last_kind_failing_to_validate</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">last_kind_found_failing_to_validate</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::get_validation_case</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> **</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> **</span><span class="identifier">set_K</span><span class="plain">,</span>
<span class="identifier">kind</span><span class="plain"> **</span><span class="identifier">set_K2</span><span class="plain">) {</span>
<span class="plain">*</span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">last_spec_failing_to_validate</span><span class="plain">;</span>
<span class="plain">*</span><span class="identifier">set_K</span><span class="plain"> = </span><span class="identifier">last_kind_failing_to_validate</span><span class="plain">;</span>
<span class="plain">*</span><span class="identifier">set_K2</span><span class="plain"> = </span><span class="identifier">last_kind_found_failing_to_validate</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((*</span><span class="identifier">spec</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (*</span><span class="identifier">set_K</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">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ap_validation_suspended</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Dash::suspend_validation</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">state</span><span class="plain">) {</span>
<span class="identifier">ap_validation_suspended</span><span class="plain"> = </span><span class="identifier">state</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::validate_parameter</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">vts</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_found</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">spec</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">ACTION_PATTERN_PARSING</span><span class="plain">, </span><span class="string">"Validating parameter in action pattern: $P ($u)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">spec</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">ParseTree::is</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="constant">UNKNOWN_NT</span><span class="plain">)) </span><span class="reserved">goto</span><span class="plain"> </span><span class="identifier">DontValidate</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Specifications::is_description</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">)) {</span>
<span class="reserved">pcalc_prop</span><span class="plain"> *</span><span class="identifier">prop</span><span class="plain"> = </span><span class="functiontext">Descriptions::to_proposition</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prop</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Calculus::Variables::number_free</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">) != 1)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ap_validation_suspended</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Specifications::is_description</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">)) </span><span class="functiontext">Dash::check_condition</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Dash::check_value</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">); </span> <span class="comment">to force a generic return kind to be evaluated</span>
<span class="identifier">kind_found</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">kind_found</span><span class="plain">) == </span><span class="identifier">CON_property</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">)))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K_understanding</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">kind_found</span><span class="plain">, </span><span class="identifier">K_snippet</span><span class="plain">)) &amp;&amp;</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">K_understanding</span><span class="plain">)))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K_understanding</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_understanding</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="constant">CONSTANT_NT</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">kind_found</span><span class="plain">, </span><span class="identifier">K_text</span><span class="plain">)))</span>
<span class="reserved">goto</span><span class="plain"> </span><span class="identifier">DontValidate</span><span class="plain">;</span>
<span class="identifier">vts</span><span class="plain"> = </span><span class="functiontext">Specifications::from_kind</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::compatible_with_description</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">vts</span><span class="plain">) == </span><span class="identifier">NEVER_MATCH</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K_understanding</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_understanding</span><span class="plain">)) &amp;&amp; (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="constant">CONSTANT_NT</span><span class="plain">))) {</span>
<span class="identifier">vts</span><span class="plain"> = </span><span class="functiontext">Specifications::from_kind</span><span class="plain">(</span><span class="identifier">K_snippet</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Dash::compatible_with_description</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">vts</span><span class="plain">) != </span><span class="identifier">NEVER_MATCH</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">kind_found</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">; </span> <span class="comment">pick up later in type-checking</span>
<span class="reserved">goto</span><span class="plain"> </span><span class="identifier">DontValidate</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">DontValidate</span><span class="plain">:</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">ACTION_PATTERN_PARSING</span><span class="plain">,</span>
<span class="string">"Fails to validate for type-checking reasons: wanted $u, found $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">K</span><span class="plain">, </span><span class="identifier">kind_found</span><span class="plain">);</span>
<span class="identifier">last_spec_failing_to_validate</span><span class="plain"> = </span><span class="identifier">ParseTree::duplicate</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="identifier">last_kind_failing_to_validate</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">;</span>
<span class="identifier">last_kind_found_failing_to_validate</span><span class="plain"> = </span><span class="identifier">kind_found</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::clear_validation_case is used in <a href="#SP19_2_1">&#167;19.2.1</a>.</p>
<p class="endnote">The function Dash::get_validation_case is used in <a href="#SP19_2_1">&#167;19.2.1</a>.</p>
<p class="endnote">The function Dash::suspend_validation is used in 25/pi (<a href="25-pi.html#SP4">&#167;4</a>).</p>
<p class="endnote">The function Dash::validate_parameter is used in 10/teav (<a href="10-teav.html#SP23">&#167;23</a>), 21/ac (<a href="21-ac.html#SP10_5">&#167;10.5</a>).</p>
<p class="inwebparagraph"><a id="SP26"></a><b>&#167;26. </b>This is the state of the <code class="display"><span class="extract">***</span></code> pseudo-phrase used for debugging:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">verbose_checking_state</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Dash::tracing_phrases</span><span class="plain">(</span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">text</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">text</span><span class="plain">) &amp;&amp; (</span><span class="identifier">text</span><span class="plain">[0])) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">LT</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">LT</span><span class="plain">, </span><span class="string">"%w"</span><span class="plain">, </span><span class="identifier">text</span><span class="plain">);</span>
<span class="identifier">Log::set_aspect_from_command_line</span><span class="plain">(</span><span class="identifier">LT</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">LT</span><span class="plain">);</span>
<span class="identifier">verbose_checking_state</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">verbose_checking_state</span><span class="plain"> = (</span><span class="identifier">verbose_checking_state</span><span class="plain">)?</span><span class="identifier">FALSE</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="identifier">verbose_checking_state</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">Log::set_all_aspects</span><span class="plain">(</span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">Log::set_aspect</span><span class="plain">(</span><span class="identifier">MATCHING_DA</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="identifier">Log::set_aspect</span><span class="plain">(</span><span class="identifier">KIND_CHECKING_DA</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="identifier">Log::set_aspect</span><span class="plain">(</span><span class="constant">LOCAL_VARIABLES_DA</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::tracing_phrases is used in <a href="#SP28">&#167;28</a>, 25/cii (<a href="25-cii.html#SP3_7">&#167;3.7</a>).</p>
<p class="inwebparagraph"><a id="SP27"></a><b>&#167;27. Value checking. </b>The following adapts the above test to attempt to match two specifications
together: for example, to match "12" against "even number". This, rather
surprisingly, returns <code class="display"><span class="extract">SOMETIMES_MATCH</span></code>, since we find that the kinds
are guaranteed &mdash; 12 is indeed a number &mdash; but Inform doesn't "know" the
meaning of the word "even", only that it's a test which will be applied
at run time.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Dash::compatible_with_description</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">from_spec</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">to_spec</span><span class="plain">) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CHECKING</span><span class="plain">, </span><span class="string">"[Can we match from: $P to: $P?]\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">from_spec</span><span class="plain">, </span><span class="identifier">to_spec</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">from_spec</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">to_spec</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">result</span><span class="plain"> = </span><span class="identifier">NEVER_MATCH</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">from</span><span class="plain">) &amp;&amp; (</span><span class="identifier">to</span><span class="plain">)) </span><span class="identifier">result</span><span class="plain"> = </span><span class="identifier">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">to</span><span class="plain">) </span><span class="identifier">result</span><span class="plain"> = </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Descriptions::is_qualified</span><span class="plain">(</span><span class="identifier">to_spec</span><span class="plain">)) || (</span><span class="functiontext">Descriptions::to_instance</span><span class="plain">(</span><span class="identifier">to_spec</span><span class="plain">)))</span>
<span class="identifier">result</span><span class="plain"> = </span><span class="functiontext">Dash::worst_case</span><span class="plain">(</span><span class="identifier">result</span><span class="plain">, </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">result</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">: </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CHECKING</span><span class="plain">, </span><span class="string">"[Always]\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">: </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CHECKING</span><span class="plain">, </span><span class="string">"[Sometimes]\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEVER_MATCH</span><span class="plain">: </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CHECKING</span><span class="plain">, </span><span class="string">"[Never]\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">result</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::compatible_with_description is used in <a href="#SP11_5">&#167;11.5</a>, <a href="#SP25">&#167;25</a>, 14/sp (<a href="14-sp.html#SP7_5">&#167;7.5</a>), 14/ds (<a href="14-ds.html#SP12_2">&#167;12.2</a>).</p>
<p class="inwebparagraph"><a id="SP28"></a><b>&#167;28. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Dash::experiment</span><span class="plain">(</span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">full</span><span class="plain">) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Beginning Dashperiment:\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">test_tree</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">last_alt</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">-</span><span class="identifier">uncached</span><span class="plain">&gt;-&gt;</span><span class="identifier">multiplicitous</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">-</span><span class="identifier">uncached</span><span class="plain">&gt;-&gt;</span><span class="identifier">watched</span><span class="plain"> = </span><span class="identifier">TRUE</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">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">T</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">with</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">-</span><span class="identifier">notation</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="identifier">T</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">with</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">-</span><span class="identifier">notation</span><span class="plain">&gt;, 1);</span>
<span class="identifier">W</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">with</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">-</span><span class="identifier">notation</span><span class="plain">&gt;, 2);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">kind</span><span class="plain">&gt;(</span><span class="identifier">T</span><span class="plain">)) </span><span class="identifier">K</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">-</span><span class="identifier">uncached</span><span class="plain">&gt;(</span><span class="identifier">T</span><span class="plain">)) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">last_alt</span><span class="plain">) </span><span class="identifier">last_alt</span><span class="plain">-&gt;</span><span class="identifier">next_alternative</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">test_tree</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="identifier">last_alt</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="identifier">n</span><span class="plain">++;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Failed to parse: %W\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">-</span><span class="identifier">uncached</span><span class="plain">&gt;-&gt;</span><span class="identifier">multiplicitous</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">-</span><span class="identifier">uncached</span><span class="plain">&gt;-&gt;</span><span class="identifier">watched</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">n</span><span class="plain"> &gt; 1) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">holder</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="identifier">AMBIGUITY_NT</span><span class="plain">);</span>
<span class="identifier">holder</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">test_tree</span><span class="plain">;</span>
<span class="identifier">test_tree</span><span class="plain"> = </span><span class="identifier">holder</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$m\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">test_tree</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Dash: value of kind $u\</span><span class="plain">n</span><span class="string">"</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">full</span><span class="plain">) </span><span class="functiontext">Dash::tracing_phrases</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="identifier">rv</span><span class="plain"> = </span><span class="functiontext">Dash::check_value</span><span class="plain">(</span><span class="identifier">test_tree</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">trv</span><span class="plain"> = </span><span class="string">"ALWAYS"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rv</span><span class="plain"> == </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">) </span><span class="identifier">trv</span><span class="plain"> = </span><span class="string">"SOMETIMES"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rv</span><span class="plain"> == </span><span class="identifier">NEVER_MATCH</span><span class="plain">) </span><span class="identifier">trv</span><span class="plain"> = </span><span class="string">"NEVER"</span><span class="plain">;</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Result: %s\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">trv</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">full</span><span class="plain">) </span><span class="functiontext">Dash::tracing_phrases</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$m\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">test_tree</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Dash::experiment is used in 26/ts (<a href="26-ts.html#SP11">&#167;11</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="14-cfs.html">Back to 'Compiling from Specifications'</a></li><li><i>(This section ends Chapter 14: Specifications.)</i></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>