mirror of
https://github.com/ganelson/inform.git
synced 2024-07-05 16:44:21 +03:00
5342 lines
572 KiB
HTML
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">★</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">§1. Definitions</a></li><li><a href="#SP4">§4. The Dashboard</a></li><li><a href="#SP8">§8. Return values</a></li><li><a href="#SP9">§9. (1) Entering Dash</a></li><li><a href="#SP10">§10. (2) Recursion point</a></li><li><a href="#SP11">§11. (3) Context switching</a></li><li><a href="#SP11_8">§11.8. New variables</a></li><li><a href="#SP11_9">§11.9. (4) Typechecking within current context</a></li><li><a href="#SP11_9_1_2">§11.9.1.2. (4S) Verifying single non-invocation readings</a></li><li><a href="#SP13">§13. Arithmetic operands</a></li><li><a href="#SP14">§14. Local variable markers</a></li><li><a href="#SP15">§15. Problems, problems, problems</a></li><li><a href="#SP19">§19. (5) Single nodes</a></li><li><a href="#SP19_2">§19.2. Rule (5.a)</a></li><li><a href="#SP19_3">§19.3. Rule (5.b)</a></li><li><a href="#SP19_4">§19.4. Rule (5.c)</a></li><li><a href="#SP19_5">§19.5. Rule (5.d)</a></li><li><a href="#SP19_6">§19.6. Rule (5.e)</a></li><li><a href="#SP22">§22. Ambiguity testing flags</a></li><li><a href="#SP27">§27. Value checking</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. Definitions. </b></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§2. </b>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>§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>§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"> &= (~</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"> & </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>§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">) &&</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"> < </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">§11.9.2</a>, <a href="#SP11_9_2_2">§11.9.2.2</a>, <a href="#SP11_9_1_1_3_1">§11.9.1.1.3.1</a>, <a href="#SP11_9_1_1_4">§11.9.1.1.4</a>, <a href="#SP15">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§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>§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>§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">§11.5</a>, <a href="#SP11_6">§11.6</a>, <a href="#SP11_9_2_2_1">§11.9.2.2.1</a>, <a href="#SP11_9_1_1">§11.9.1.1</a>, <a href="#SP11_9_1_1_4">§11.9.1.1.4</a>, <a href="#SP11_9_1_1_6">§11.9.1.1.6</a>, <a href="#SP11_9_1_2">§11.9.1.2</a>, <a href="#SP27">§27</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§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">>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">>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">>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">§24</a>, <a href="#SP25">§25</a>, 21/rl (<a href="21-rl.html#SP11_1">§11.1</a>), 25/cp (<a href="25-cp.html#SP5_3_2">§5.3.2</a>).</p>
|
|
|
|
<p class="endnote">The function Dash::check_value is used in <a href="#SP25">§25</a>, <a href="#SP28">§28</a>, 11/tr (<a href="11-tr.html#SP10">§10</a>), 11/tcp (<a href="11-tcp.html#SP6_1">§6.1</a>), 12/cad (<a href="12-cad.html#SP6">§6</a>), 25/cii (<a href="25-cii.html#SP8">§8</a>), 25/cp (<a href="25-cp.html#SP5_3_5">§5.3.5</a>), 26/ts (<a href="26-ts.html#SP11">§11</a>).</p>
|
|
|
|
<p class="endnote">The function Dash::check_value_silently is used in 11/tcp (<a href="11-tcp.html#SP6_1">§6.1</a>), 18/lc (<a href="18-lc.html#SP8">§8</a>).</p>
|
|
|
|
<p class="endnote">The function Dash::check_invl is used in 25/cp (<a href="25-cp.html#SP6">§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>§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"> >= </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"> > </span><span class="identifier">problem_count_before</span><span class="plain">) && (</span><span class="identifier">consider_alternatives</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">Consider adding a backtrace of what the type-checker was up to</span> <span class="cwebmacronumber">10.1</span>><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">§9</a>, <a href="#SP11_1">§11.1</a>, <a href="#SP11_9_1">§11.9.1</a>, <a href="#SP11_9_2_2_1">§11.9.2.2.1</a>, <a href="#SP11_9_1_1_2_1">§11.9.1.1.2.1</a>, <a href="#SP11_9_1_1_3_1">§11.9.1.1.3.1</a>, <a href="#SP11_9_1_2">§11.9.1.2</a>, <a href="#SP13">§13</a>, <a href="#SP15_3">§15.3</a>, <a href="#SP15_4">§15.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Consider adding a backtrace of what the type-checker was up to</span> <span class="cwebmacronumber">10.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> > </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">) && (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">>down</span><span class="plain">) &&</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>
|
|
<<span class="cwebmacro">Backtrace what phrase definitions the type-checker was looking at</span> <span class="cwebmacronumber">10.1.1</span>><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">§10</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10_1_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Backtrace what phrase definitions the type-checker was looking at</span> <span class="cwebmacronumber">10.1.1</span>> =
|
|
</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">>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">>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">(&(</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">>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><<span class="cwebmacro">Produce the I was trying... banner</span> <span class="cwebmacronumber">10.1.1.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Produce the list of possibilities</span> <span class="cwebmacronumber">10.1.1.2</span>><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>
|
|
<<span class="cwebmacro">Produce the tokens which were recognisable as something</span> <span class="cwebmacronumber">10.1.1.3</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Produce the tokens which weren't recognisable as something</span> <span class="cwebmacronumber">10.1.1.5</span>><span class="character">;</span>
|
|
<<span class="cwebmacro">Produce the tokens which were intentionally not recognisable as something</span> <span class="cwebmacronumber">10.1.1.4</span>><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">real_found</span><span class="plain">) </span><<span class="cwebmacro">Produce a note about real versus integer</span> <span class="cwebmacronumber">10.1.1.6</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP10_1">§10.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10_1_1_1"></a><b>§10.1.1.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Produce the I was trying... banner</span> <span class="cwebmacronumber">10.1.1.1</span>> =
|
|
</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"> > 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">§10.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10_1_1_2"></a><b>§10.1.1.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Produce the list of possibilities</span> <span class="cwebmacronumber">10.1.1.2</span>> =
|
|
</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">>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">(&(</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">>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, &</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"> > 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">§10.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10_1_1_3"></a><b>§10.1.1.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Produce the tokens which were recognisable as something</span> <span class="cwebmacronumber">10.1.1.3</span>> =
|
|
</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">>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">>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">>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>
|
|
<<span class="cwebmacro">Produce this token</span> <span class="cwebmacronumber">10.1.1.3.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP10_1_1">§10.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10_1_1_3_1"></a><b>§10.1.1.3.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Produce this token</span> <span class="cwebmacronumber">10.1.1.3.1</span>> =
|
|
</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">>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">>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">>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">>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">, &</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">>as_parsed</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">Produce the token for an lvalue</span> <span class="cwebmacronumber">10.1.1.3.1.1</span>>
|
|
<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">>as_parsed</span><span class="plain">, </span><span class="constant">PHRASE_TO_DECIDE_VALUE_NT</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">Produce the token for a phrase deciding a value</span> <span class="cwebmacronumber">10.1.1.3.1.2</span>>
|
|
<span class="reserved">else</span>
|
|
<<span class="cwebmacro">Produce the token for a constant rvalue</span> <span class="cwebmacronumber">10.1.1.3.1.3</span>><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 = <i>%2</i>"</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">§10.1.1.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10_1_1_3_1_1"></a><b>§10.1.1.3.1.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Produce the token for an lvalue</span> <span class="cwebmacronumber">10.1.1.3.1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span><span class="string">"%1 = <i>%2</i>, holding <i>%3</i>"</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">§10.1.1.3.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10_1_1_3_1_2"></a><b>§10.1.1.3.1.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Produce the token for a phrase deciding a value</span> <span class="cwebmacronumber">10.1.1.3.1.2</span>> =
|
|
</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 <i>%3</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="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">>as_parsed</span><span class="plain">-</span><span class="element">>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 <i>%3</i>, "</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"><</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 <i>%3</i>, "</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">§10.1.1.3.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10_1_1_3_1_3"></a><b>§10.1.1.3.1.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Produce the token for a constant rvalue</span> <span class="cwebmacronumber">10.1.1.3.1.3</span>> =
|
|
</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 = <i>%3</i>"</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">>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">>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 = <i>%3</i>, 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">§10.1.1.3.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10_1_1_4"></a><b>§10.1.1.4. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Produce the tokens which were intentionally not recognisable as something</span> <span class="cwebmacronumber">10.1.1.4</span>> =
|
|
</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">>as_parsed</span><span class="plain">, </span><span class="constant">UNKNOWN_NT</span><span class="plain">)) && (</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">>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">>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">>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"> < 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">>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"> > 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">§10.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10_1_1_5"></a><b>§10.1.1.5. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Produce the tokens which weren't recognisable as something</span> <span class="cwebmacronumber">10.1.1.5</span>> =
|
|
</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">>as_parsed</span><span class="plain">, </span><span class="constant">UNKNOWN_NT</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="identifier">itpt</span><span class="plain">-</span><span class="element">>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">>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">>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"> < 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">>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"> > 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">§10.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10_1_1_6"></a><b>§10.1.1.6. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Produce a note about real versus integer</span> <span class="cwebmacronumber">10.1.1.6</span>> =
|
|
</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">§10.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§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">-></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><<span class="cwebmacro">Switch context</span> <span class="cwebmacronumber">11.1</span>><span class="plain">;</span>
|
|
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">RVALUE_CONTEXT_NT</span><span class="plain">: </span><<span class="cwebmacro">Switch context</span> <span class="cwebmacronumber">11.1</span>><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><<span class="cwebmacro">Switch context to an rvalue matching a description</span> <span class="cwebmacronumber">11.5</span>><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><<span class="cwebmacro">Switch context to an rvalue matching a value</span> <span class="cwebmacronumber">11.6</span>><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">VOID_CONTEXT_NT</span><span class="plain">: </span><<span class="cwebmacro">Switch to a void context</span> <span class="cwebmacronumber">11.7</span>><span class="plain">;</span>
|
|
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">LVALUE_CONTEXT_NT</span><span class="plain">: </span><<span class="cwebmacro">Switch context to an lvalue</span> <span class="cwebmacronumber">11.2</span>><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><<span class="cwebmacro">Switch context to a table reference lvalue</span> <span class="cwebmacronumber">11.3</span>><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><<span class="cwebmacro">Switch context to an existing local variable lvalue</span> <span class="cwebmacronumber">11.4</span>><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><<span class="cwebmacro">Deal with a new local variable name</span> <span class="cwebmacronumber">11.8</span>><span class="plain">;</span>
|
|
|
|
<span class="reserved">default</span><span class="plain">: </span><<span class="cwebmacro">Typecheck within current context</span> <span class="cwebmacronumber">11.9</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="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">§10</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_1"></a><b>§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">>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">
|
|
<<span class="cwebmacrodefn">Switch context</span> <span class="cwebmacronumber">11.1</span>> =
|
|
</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">§11</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_2"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Switch context to an lvalue</span> <span class="cwebmacronumber">11.2</span>> =
|
|
</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">>down</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Issue problem for not being an lvalue</span> <span class="cwebmacronumber">11.2.1</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">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_3"></a><b>§11.3. </b>More specifically:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Switch context to a table reference lvalue</span> <span class="cwebmacronumber">11.3</span>> =
|
|
</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">>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>
|
|
<<span class="cwebmacro">Issue problem for not being a table reference</span> <span class="cwebmacronumber">11.3.1</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">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_4"></a><b>§11.4. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Switch context to an existing local variable lvalue</span> <span class="cwebmacronumber">11.4</span>> =
|
|
</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">>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>
|
|
<<span class="cwebmacro">Issue problem for not being an existing local</span> <span class="cwebmacronumber">11.4.1</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">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_5"></a><b>§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 — here "the Marble Portal" —
|
|
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">
|
|
<<span class="cwebmacrodefn">Switch context to an rvalue matching a description</span> <span class="cwebmacronumber">11.5</span>> =
|
|
</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">>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">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_6"></a><b>§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 — for one thing, we
|
|
don't know what text substitutions will then expand to — 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">
|
|
<<span class="cwebmacrodefn">Switch context to an rvalue matching a value</span> <span class="cwebmacronumber">11.6</span>> =
|
|
</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">>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">) &&</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">>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">>down</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">)))</span>
|
|
<<span class="cwebmacro">Issue problem for being the wrong rvalue</span> <span class="cwebmacronumber">11.6.1</span>><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">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_7"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Switch to a void context</span> <span class="cwebmacronumber">11.7</span>> =
|
|
</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">>down</span><span class="plain">, </span><span class="constant">PHRASE_TO_DECIDE_VALUE_NT</span><span class="plain">))) {</span>
|
|
<<span class="cwebmacro">Issue problem for not being a phrase</span> <span class="cwebmacronumber">11.7.1</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">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_2_1"></a><b>§11.2.1. </b>A whole set of problem messages arise out of contextual failures:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Issue problem for not being an lvalue</span> <span class="cwebmacronumber">11.2.1</span>> =
|
|
</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">>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">§11.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_3_1"></a><b>§11.3.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue problem for not being a table reference</span> <span class="cwebmacronumber">11.3.1</span>> =
|
|
</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">>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">§11.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_4_1"></a><b>§11.4.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue problem for not being an existing local</span> <span class="cwebmacronumber">11.4.1</span>> =
|
|
</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">>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">>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">§11.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_6_1"></a><b>§11.6.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue problem for being the wrong rvalue</span> <span class="cwebmacronumber">11.6.1</span>> =
|
|
</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">>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">>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">§11.6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_7_1"></a><b>§11.7.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue problem for not being a phrase</span> <span class="cwebmacronumber">11.7.1</span>> =
|
|
</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">>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">§11.7</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_8"></a><b>§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 — 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">
|
|
<<span class="cwebmacrodefn">Deal with a new local variable name</span> <span class="cwebmacronumber">11.8</span>> =
|
|
</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">>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">>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>
|
|
<<span class="cwebmacro">Issue a problem for an inappropriate variable name</span> <span class="cwebmacronumber">11.8.1</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">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_8_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Issue a problem for an inappropriate variable name</span> <span class="cwebmacronumber">11.8.1</span>> =
|
|
</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">>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">>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">§11.8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Typecheck within current context</span> <span class="cwebmacronumber">11.9</span>> =
|
|
</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">) && (</span><span class="identifier">p</span><span class="plain">-></span><span class="identifier">next_alternative</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">Resolve an ambiguous reading</span> <span class="cwebmacronumber">11.9.2</span>>
|
|
<span class="reserved">else</span>
|
|
<<span class="cwebmacro">Verify an unambiguous reading</span> <span class="cwebmacronumber">11.9.1</span>><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">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Verify an unambiguous reading</span> <span class="cwebmacronumber">11.9.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-></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">>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">>down</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><<span class="cwebmacro">Unknown found text occurs as a command</span> <span class="cwebmacronumber">11.9.1.3</span>><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">>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><<span class="cwebmacro">Step (4I) Verify an invocation</span> <span class="cwebmacronumber">11.9.1.1</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="cwebmacro">Step (4S) Verify anything else</span> <span class="cwebmacronumber">11.9.1.2</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">§11.9</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_2"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Resolve an ambiguous reading</span> <span class="cwebmacronumber">11.9.2</span>> =
|
|
</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>
|
|
|
|
<<span class="cwebmacro">Step (4A.a) Set up the list of readings to test</span> <span class="cwebmacronumber">11.9.2.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Step (4A.b) Recurse Dash to try each reading in turn</span> <span class="cwebmacronumber">11.9.2.2</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="reserved">if</span><span class="plain"> (</span><span class="identifier">no_of_passed_readings</span><span class="plain"> > 0) </span><<span class="cwebmacro">Step (4A.c) Preserve successful readings</span> <span class="cwebmacronumber">11.9.2.3</span>>
|
|
<span class="reserved">else</span><span class="plain"> </span><<span class="cwebmacro">Step (4A.d) Give up with no readings possible</span> <span class="cwebmacronumber">11.9.2.4</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">"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">§11.9</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_2_1"></a><b>§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<= 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">
|
|
<<span class="cwebmacrodefn">Step (4A.a) Set up the list of readings to test</span> <span class="cwebmacronumber">11.9.2.1</span>> =
|
|
</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">)) &&</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>
|
|
<<span class="cwebmacro">Add this reading to the list of test cases</span> <span class="cwebmacronumber">11.9.2.1.1</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">)) &&</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>
|
|
<<span class="cwebmacro">Add this reading to the list of test cases</span> <span class="cwebmacronumber">11.9.2.1.1</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">"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"><</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">§11.9.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_2_1_1"></a><b>§11.9.2.1.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Add this reading to the list of test cases</span> <span class="cwebmacronumber">11.9.2.1.1</span>> =
|
|
</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"> >= </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">§11.9.2.1</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_2_2"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (4A.b) Recurse Dash to try each reading in turn</span> <span class="cwebmacronumber">11.9.2.2</span>> =
|
|
</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"><</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="cwebmacro">Test the current reading and set its results flags accordingly</span> <span class="cwebmacronumber">11.9.2.2.1</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">"(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"> > 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"><</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">§11.9.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_2_2_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Test the current reading and set its results flags accordingly</span> <span class="cwebmacronumber">11.9.2.2.1</span>> =
|
|
</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 <%W>: $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">§11.9.2.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_2_3"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (4A.c) Preserve successful readings</span> <span class="cwebmacronumber">11.9.2.3</span>> =
|
|
</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>
|
|
<<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>><span class="plain">;</span>
|
|
<<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>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP11_9_2">§11.9.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_2_3_1"></a><b>§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 — failed, grossly failed,
|
|
or never reached — 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">
|
|
<<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>> =
|
|
</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">>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"><</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">-></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">-></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">>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">>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">>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">-></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">>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><<span class="cwebmacro">Issue the number ambiguity problem message</span> <span class="cwebmacronumber">11.9.2.3.1.1</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">"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">§11.9.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_2_3_1_1"></a><b>§11.9.2.3.1.1. </b>This is another sort of error which couldn't happen with a conventional
|
|
programming language — 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">
|
|
<<span class="cwebmacrodefn">Issue the number ambiguity problem message</span> <span class="cwebmacronumber">11.9.2.3.1.1</span>> =
|
|
</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">§11.9.2.3.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_2_3_2"></a><b>§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">
|
|
<<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>> =
|
|
</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">§11.9.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_2_4"></a><b>§11.9.2.4. </b>And this is the unhappy ending:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Step (4A.d) Give up with no readings possible</span> <span class="cwebmacronumber">11.9.2.4</span>> =
|
|
</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">§11.9.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (4I) Verify an invocation</span> <span class="cwebmacronumber">11.9.1.1</span>> =
|
|
</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">(&(</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">>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><<span class="cwebmacro">Step (4I.a) Take care of arithmetic phrases</span> <span class="cwebmacronumber">11.9.1.1.2</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="cwebmacro">Step (4I.b) Take care of non-arithmetic phrases</span> <span class="cwebmacronumber">11.9.1.1.3</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="cwebmacro">Step (4I.c) Match type templates in the argument specifications</span> <span class="cwebmacronumber">11.9.1.1.4</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="cwebmacro">Step (4I.d) Match kinds in assignment phrases</span> <span class="cwebmacronumber">11.9.1.1.5</span>><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><<span class="cwebmacro">Step (4I.e) Check kind of value returned</span> <span class="cwebmacronumber">11.9.1.1.6</span>><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><<span class="cwebmacro">Step (4I.f) Check any phrase options</span> <span class="cwebmacronumber">11.9.1.1.7</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="cwebmacro">Step (4I.g) Worry about self in say property of</span> <span class="cwebmacronumber">11.9.1.1.8</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="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>><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="cwebmacro">Step (4I.i) Disallow any phrases which are now deprecated</span> <span class="cwebmacronumber">11.9.1.1.10</span>><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">) && (</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><<span class="cwebmacro">Step (4I.j) Cope with failure</span> <span class="cwebmacronumber">11.9.1.1.11</span>>
|
|
<span class="reserved">else</span><span class="plain"> </span><<span class="cwebmacro">Step (4I.k) Cope with success</span> <span class="cwebmacronumber">11.9.1.1.12</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP11_9_1">§11.9.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_1"></a><b>§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>§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">
|
|
<<span class="cwebmacrodefn">Step (4I.a) Take care of arithmetic phrases</span> <span class="cwebmacronumber">11.9.1.1.2</span>> =
|
|
</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>
|
|
<<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>>
|
|
<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><<span class="cwebmacro">Step (4I.a.2) Dimension-check arithmetic phrases</span> <span class="cwebmacronumber">11.9.1.1.2.2</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP11_9_1_1">§11.9.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_2_1"></a><b>§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">
|
|
<<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>> =
|
|
</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">) && (</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><<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>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP11_9_1_1_2">§11.9.1.1.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_2_1_1"></a><b>§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">
|
|
<<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>> =
|
|
</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">§11.9.1.1.2.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_2_2"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (4I.a.2) Dimension-check arithmetic phrases</span> <span class="cwebmacronumber">11.9.1.1.2.2</span>> =
|
|
</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 <op-%d>\</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>
|
|
<<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>><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><<span class="cwebmacro">Fail the invocation for a dimensional problem</span> <span class="cwebmacronumber">11.9.1.1.2.2.2</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">§11.9.1.1.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_2_2_1"></a><b>§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">
|
|
<<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>> =
|
|
</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">) && (</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">) && (</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">§11.9.1.1.2.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_2_2_2"></a><b>§11.9.1.1.2.2.2. </b>Note that "value" — the vaguest kind of all — 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">
|
|
<<span class="cwebmacrodefn">Fail the invocation for a dimensional problem</span> <span class="cwebmacronumber">11.9.1.1.2.2.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">left_kind</span><span class="plain">) && (</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">) &&</span>
|
|
<span class="plain">(</span><span class="identifier">right_kind</span><span class="plain">) && (</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">§11.9.1.1.2.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_3"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (4I.b) Take care of non-arithmetic phrases</span> <span class="cwebmacronumber">11.9.1.1.3</span>> =
|
|
</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"><</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>
|
|
<<span class="cwebmacro">Type-check a single token from the list</span> <span class="cwebmacronumber">11.9.1.1.3.1</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="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">§11.9.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_3_1"></a><b>§11.9.1.1.3.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Type-check a single token from the list</span> <span class="cwebmacronumber">11.9.1.1.3.1</span>> =
|
|
</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">>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">>type_data.token_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.construct</span><span class="plain"> == </span><span class="constant">KIND_NAME_PT_CONSTRUCT</span><span class="plain">) && (</span><span class="identifier">outcome</span><span class="plain"> != </span><span class="identifier">NEVER_MATCH</span><span class="plain">))</span>
|
|
<<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>>
|
|
<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">(&</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">()) && (</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">§11.9.1.1.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_3_1_1"></a><b>§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">
|
|
<<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>> =
|
|
</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">>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">) &&</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"> (<</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">>(</span><span class="identifier">W</span><span class="plain">)) </span><span class="identifier">reparsed</span><span class="plain"> = <<</span><span class="identifier">rp</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">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">) && (<</span><span class="identifier">k</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">K</span><span class="plain"> = <<</span><span class="identifier">rp</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="reserved">if</span><span class="plain"> ((<</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">>(</span><span class="identifier">W</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Properties::Valued::coincides_with_kind</span><span class="plain">(<<</span><span class="identifier">rp</span><span class="plain">>>)))</span>
|
|
<span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Properties::Valued::kind</span><span class="plain">(<<</span><span class="identifier">rp</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) 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">) && (</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">)) && (</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">§11.9.1.1.3.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_4"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (4I.c) Match type templates in the argument specifications</span> <span class="cwebmacronumber">11.9.1.1.4</span>> =
|
|
</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">(&(</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">>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"> <= 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"><</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">>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="plain">(</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">>type_data.token_sequence</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.construct</span><span class="plain"> != </span><span class="constant">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">>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">>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> — 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) && (</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">>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">, &</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><<span class="cwebmacro">Disallow an undeclared kind variable as return kind</span> <span class="cwebmacronumber">11.9.1.1.4.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP11_9_1_1">§11.9.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_4_1"></a><b>§11.9.1.1.4.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Disallow an undeclared kind variable as return kind</span> <span class="cwebmacronumber">11.9.1.1.4.1</span>> =
|
|
</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">§11.9.1.1.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_5"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (4I.d) Match kinds in assignment phrases</span> <span class="cwebmacronumber">11.9.1.1.5</span>> =
|
|
</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">>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">>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">) && (</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>
|
|
<<span class="cwebmacro">Step (4I.d.1) Police an assignment to an object</span> <span class="cwebmacronumber">11.9.1.1.5.1</span>><span class="plain">;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">>type_data.token_sequence</span><span class="plain">[0]</span><span class="element">.construct</span><span class="plain"> != </span><span class="constant">NEW_LOCAL_PT_CONSTRUCT</span><span class="plain">)</span>
|
|
<<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>><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">§11.9.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_5_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (4I.d.1) Police an assignment to an object</span> <span class="cwebmacronumber">11.9.1.1.5.1</span>> =
|
|
</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>
|
|
<<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>><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>
|
|
<<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>><span class="character">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">make_check</span><span class="plain">)</span>
|
|
<<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>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP11_9_1_1_5">§11.9.1.1.5</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_5_1_1"></a><b>§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 — it assigns the value "blue"
|
|
to the colour property of the canvas.)
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<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>> =
|
|
</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">§11.9.1.1.5.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_5_1_2"></a><b>§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">
|
|
<<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>> =
|
|
</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">§11.9.1.1.5.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_5_1_3"></a><b>§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">
|
|
<<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>> =
|
|
</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">) && (</span><span class="identifier">prn</span><span class="plain">) &&</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">§11.9.1.1.5.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_5_2"></a><b>§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">
|
|
<<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>> =
|
|
</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">>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">) && (</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">)) &&</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">§11.9.1.1.5</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_6"></a><b>§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->kind_resulting</span></code>. We now check to see if this matches the kind
|
|
expected — in this example, it won't, because a stored action does not cast
|
|
to a number.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Step (4I.e) Check kind of value returned</span> <span class="cwebmacronumber">11.9.1.1.6</span>> =
|
|
</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">§11.9.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_7"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (4I.f) Check any phrase options</span> <span class="cwebmacronumber">11.9.1.1.7</span>> =
|
|
</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">) && (</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">§11.9.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_8"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (4I.g) Worry about self in say property of</span> <span class="cwebmacronumber">11.9.1.1.8</span>> =
|
|
</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">)) &&</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) &&</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">§11.9.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_9"></a><b>§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">
|
|
<<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>> =
|
|
</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">) && (</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">§11.9.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_10"></a><b>§11.9.1.1.10. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Step (4I.i) Disallow any phrases which are now deprecated</span> <span class="cwebmacronumber">11.9.1.1.10</span>> =
|
|
</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">) && (</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">>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">§11.9.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_11"></a><b>§11.9.1.1.11. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Step (4I.j) Cope with failure</span> <span class="cwebmacronumber">11.9.1.1.11</span>> =
|
|
</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"> > </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"> > </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">) && (</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">§11.9.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_1_12"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (4I.k) Cope with success</span> <span class="cwebmacronumber">11.9.1.1.12</span>> =
|
|
</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">>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">§11.9.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_2"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (4S) Verify anything else</span> <span class="cwebmacronumber">11.9.1.2</span>> =
|
|
</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>
|
|
<<span class="cwebmacro">Allow listed-in table references only where these are expected</span> <span class="cwebmacronumber">11.9.1.2.1</span>><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">>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">>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">) && (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">>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>
|
|
<<span class="cwebmacro">Step (4S.c) Check arguments of a list entry</span> <span class="cwebmacronumber">11.9.1.2.2</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">PROPERTY_VALUE_NT</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">Step (4S.d) Check arguments of a property value</span> <span class="cwebmacronumber">11.9.1.2.3</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">TABLE_ENTRY_NT</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">Step (4S.e) Check arguments of a table reference</span> <span class="cwebmacronumber">11.9.1.2.4</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">§11.9.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_2_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Allow listed-in table references only where these are expected</span> <span class="cwebmacronumber">11.9.1.2.1</span>> =
|
|
</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">)) &&</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) &&</span>
|
|
<span class="plain">(</span><span class="identifier">kind_needed</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">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">§11.9.1.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_2_2"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (4S.c) Check arguments of a list entry</span> <span class="cwebmacronumber">11.9.1.2.2</span>> =
|
|
</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">>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">>down</span><span class="plain">-</span><span class="element">>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">§11.9.1.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_2_3"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (4S.d) Check arguments of a property value</span> <span class="cwebmacronumber">11.9.1.2.3</span>> =
|
|
</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">>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><<span class="cwebmacro">Issue a "not a property" problem message</span> <span class="cwebmacronumber">11.9.1.2.3.1</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">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><<span class="cwebmacro">Issue a "not a value property" problem message</span> <span class="cwebmacronumber">11.9.1.2.3.2</span>><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">>down</span><span class="plain">-</span><span class="element">>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>
|
|
<<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>><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">)) &&</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>
|
|
<<span class="cwebmacro">Issue a problem message for not being allowed this property</span> <span class="cwebmacronumber">11.9.1.2.3.4</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">§11.9.1.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_2_3_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Issue a "not a property" problem message</span> <span class="cwebmacronumber">11.9.1.2.3.1</span>> =
|
|
</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">§11.9.1.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_2_3_2"></a><b>§11.9.1.2.3.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue a "not a value property" problem message</span> <span class="cwebmacronumber">11.9.1.2.3.2</span>> =
|
|
</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">§11.9.1.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_2_3_3"></a><b>§11.9.1.2.3.3. </b><code class="display">
|
|
<<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>> =
|
|
</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">)) &&</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">§11.9.1.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_2_3_4"></a><b>§11.9.1.2.3.4. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue a problem message for not being allowed this property</span> <span class="cwebmacronumber">11.9.1.2.3.4</span>> =
|
|
</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">>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">§11.9.1.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_2_4"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (4S.e) Check arguments of a table reference</span> <span class="cwebmacronumber">11.9.1.2.4</span>> =
|
|
</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">>down</span><span class="plain">-</span><span class="element">>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">>down</span><span class="plain">-</span><span class="element">>next</span><span class="plain">-</span><span class="element">>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">§11.9.1.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_9_1_3"></a><b>§11.9.1.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Unknown found text occurs as a command</span> <span class="cwebmacronumber">11.9.1.3</span>> =
|
|
</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"> (<</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">>(</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">§11.9.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12"></a><b>§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"><</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">> ::=</span>
|
|
<span class="reserved">continue</span><span class="plain"> ==> </span><<span class="cwebmacro">Issue PM_WrongContinue problem</span> <span class="cwebmacronumber">12.1</span>>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12_1"></a><b>§12.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_WrongContinue problem</span> <span class="cwebmacronumber">12.1</span>> =
|
|
</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">§12</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13"></a><b>§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">>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">>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">>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">>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">§11.9.1.1.2.2.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14"></a><b>§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 — 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"><</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) && (</span><span class="identifier">N</span><span class="plain"> >= 2) && (</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">)) &&</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>
|
|
<<span class="cwebmacro">Infer the kind of the new variable</span> <span class="cwebmacronumber">14.1</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">, &</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">§11.9.2.3.2</a>, <a href="#SP11_9_1_1">§11.9.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14_1"></a><b>§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 — 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">
|
|
<<span class="cwebmacrodefn">Infer the kind of the new variable</span> <span class="cwebmacronumber">14.1</span>> =
|
|
</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">>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>
|
|
<<span class="cwebmacro">Where no kind was explicitly stated, infer this from the supplied initial value</span> <span class="cwebmacronumber">14.1.1</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP14">§14</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14_1_1"></a><b>§14.1.1. </b>Unusually, it's legal for the initial value to be a generic constant —
|
|
</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 —
|
|
</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">
|
|
<<span class="cwebmacrodefn">Where no kind was explicitly stated, infer this from the supplied initial value</span> <span class="cwebmacronumber">14.1.1</span>> =
|
|
</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">)) &&</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><<span class="cwebmacro">Fail: the initial value of the local is unknown</span> <span class="cwebmacronumber">14.1.1.1</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">seems_to_be</span><span class="plain">) == </span><span class="identifier">CON_list_of</span><span class="plain">) &&</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>
|
|
<<span class="cwebmacro">Fail: the initial value of the local is the empty list</span> <span class="cwebmacronumber">14.1.1.2</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">seems_to_be</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Fail: the initial value can't be stored</span> <span class="cwebmacronumber">14.1.1.3</span>><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">§14.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14_1_1_1"></a><b>§14.1.1.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Fail: the initial value of the local is unknown</span> <span class="cwebmacronumber">14.1.1.1</span>> =
|
|
</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">§14.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14_1_1_2"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Fail: the initial value of the local is the empty list</span> <span class="cwebmacronumber">14.1.1.2</span>> =
|
|
</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">§14.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14_1_1_3"></a><b>§14.1.1.3. </b>And some kinds are just forbidden in storage:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Fail: the initial value can't be stored</span> <span class="cwebmacronumber">14.1.1.3</span>> =
|
|
</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">§14.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15"></a><b>§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 — 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>
|
|
<<span class="cwebmacro">Scan through the invocations in the problematic group, gathering information</span> <span class="cwebmacronumber">15.1</span>><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>
|
|
<<span class="cwebmacro">Decide which invocation is the one most likely to have been intended</span> <span class="cwebmacronumber">15.2</span>><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>
|
|
<<span class="cwebmacro">Re-type-check the first interesting invocation, allowing interesting problems this time</span> <span class="cwebmacronumber">15.3</span>>
|
|
<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>
|
|
<<span class="cwebmacro">Re-type-check the tokens of the most likely invocation with silence off</span> <span class="cwebmacronumber">15.4</span>>
|
|
<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">)) <</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">>(</span><span class="identifier">SW</span><span class="plain">);</span>
|
|
<span class="reserved">else</span><span class="plain"> </span><<span class="cwebmacro">Issue a problem for a regular phrase with multiple failed possibilities</span> <span class="cwebmacronumber">15.5</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>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Dash::failed_one is used in <a href="#SP11_9_1_1_11">§11.9.1.1.11</a>.</p>
|
|
|
|
<p class="endnote">The function Dash::failed is used in <a href="#SP11_9_2_4">§11.9.2.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_1"></a><b>§15.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Scan through the invocations in the problematic group, gathering information</span> <span class="cwebmacronumber">15.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">ref</span><span class="plain">=0; </span><span class="identifier">ref</span><span class="plain"><</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">)) &&</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">(&(</span><span class="identifier">ph</span><span class="plain">-</span><span class="element">>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">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_2"></a><b>§15.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Decide which invocation is the one most likely to have been intended</span> <span class="cwebmacronumber">15.2</span>> =
|
|
</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"> > 1) && (</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) && (</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">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_3"></a><b>§15.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Re-type-check the first interesting invocation, allowing interesting problems this time</span> <span class="cwebmacronumber">15.3</span>> =
|
|
</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">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_4"></a><b>§15.4. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Re-type-check the tokens of the most likely invocation with silence off</span> <span class="cwebmacronumber">15.4</span>> =
|
|
</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"><</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"> > </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"><</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"> > </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">) && (</span><span class="identifier">W</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">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">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_5"></a><b>§15.5. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue a problem for a regular phrase with multiple failed possibilities</span> <span class="cwebmacronumber">15.5</span>> =
|
|
</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">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16"></a><b>§16. </b>The following chooses a problem message for a text substitution which is
|
|
unrecognised.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain"><</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">> ::=</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"> ... | ==> </span><<span class="cwebmacro">Issue PM_SayAList problem</span> <span class="cwebmacronumber">16.1</span>>
|
|
<span class="plain">... ==> </span><<span class="cwebmacro">Issue last-resort failed ts problem</span> <span class="cwebmacronumber">16.2</span>>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16_1"></a><b>§16.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_SayAList problem</span> <span class="cwebmacronumber">16.1</span>> =
|
|
</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">§16</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16_2"></a><b>§16.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue last-resort failed ts problem</span> <span class="cwebmacronumber">16.2</span>> =
|
|
</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">§16</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP17"></a><b>§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">>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">>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">>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">>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">>down</span><span class="plain">;</span>
|
|
<span class="identifier">itpt</span><span class="plain">-</span><span class="element">>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">>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">>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">§3.1.2</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18"></a><b>§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"><</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">> ::=</span>
|
|
<span class="plain"><</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">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">> | ==> </span><span class="identifier">R</span><span class="plain">[1] | </span><span class="identifier">R</span><span class="plain">[2]</span>
|
|
<span class="plain"><</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">R</span><span class="plain">[1]</span>
|
|
|
|
<span class="plain"><</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">> ::=</span>
|
|
<span class="plain">, </span><span class="identifier">and</span><span class="plain">/</span><span class="identifier">or</span><span class="plain"> <</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">> | ==> </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"> <</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">> ==> </span><span class="identifier">R</span><span class="plain">[1]</span>
|
|
|
|
<span class="plain"><</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="plain"><</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">> | ==> 0; </span><<span class="cwebmacro">Quote this-condition-okay segment</span> <span class="cwebmacronumber">18.1</span>><span class="plain">;</span>
|
|
<span class="plain"><</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">> | ==> </span><span class="constant">INVALID_CP_BIT</span><span class="plain">; </span><<span class="cwebmacro">Quote this-condition-value segment</span> <span class="cwebmacronumber">18.2</span>><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"> | ==> </span><span class="constant">WHENWHILE_CP_BIT</span><span class="plain">+</span><span class="constant">INVALID_CP_BIT</span><span class="plain">; </span><<span class="cwebmacro">Quote scene-begins-or-ends segment</span> <span class="cwebmacronumber">18.3</span>><span class="plain">;</span>
|
|
<span class="identifier">when</span><span class="plain">/</span><span class="reserved">while</span><span class="plain"> *** | ==> </span><span class="constant">WHENWHILE_CP_BIT</span><span class="plain">+</span><span class="constant">INVALID_CP_BIT</span><span class="plain">; </span><<span class="cwebmacro">Quote this-condition-bad segment</span> <span class="cwebmacronumber">18.4</span>><span class="plain">;</span>
|
|
<span class="plain">... ==> </span><span class="constant">INVALID_CP_BIT</span><span class="plain">; </span><<span class="cwebmacro">Quote this-condition-bad segment</span> <span class="cwebmacronumber">18.4</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18_1"></a><b>§18.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Quote this-condition-okay segment</span> <span class="cwebmacronumber">18.1</span>> =
|
|
</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">§18</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18_2"></a><b>§18.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Quote this-condition-value segment</span> <span class="cwebmacronumber">18.2</span>> =
|
|
</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">§18</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18_3"></a><b>§18.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Quote scene-begins-or-ends segment</span> <span class="cwebmacronumber">18.3</span>> =
|
|
</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">§18</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18_4"></a><b>§18.4. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Quote this-condition-bad segment</span> <span class="cwebmacronumber">18.4</span>> =
|
|
</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">§18</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19"></a><b>§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">)) &&</span>
|
|
<span class="plain">(</span><span class="identifier">kind_expected</span><span class="plain">) && (</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>
|
|
<<span class="cwebmacro">Disallow "nothing" as a match for a description requiring a kind of object</span> <span class="cwebmacronumber">19.1</span>><span class="plain">;</span>
|
|
|
|
<<span class="cwebmacro">Step (5.a) Deal with the UNKNOWN_NT</span> <span class="cwebmacronumber">19.2</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Step (5.b) Deal with bare property names</span> <span class="cwebmacronumber">19.3</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Step (5.c) Deal with any attached proposition</span> <span class="cwebmacronumber">19.4</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Step (5.d) Apply miscellaneous other coercions</span> <span class="cwebmacronumber">19.5</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Step (5.e) The Main Rule of Type-Checking</span> <span class="cwebmacronumber">19.6</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="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">§11.9.1.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_1"></a><b>§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 —
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Disallow "nothing" as a match for a description requiring a kind of object</span> <span class="cwebmacronumber">19.1</span>> =
|
|
</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">§19</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_2"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (5.a) Deal with the UNKNOWN_NT</span> <span class="cwebmacronumber">19.2</span>> =
|
|
</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>
|
|
<<span class="cwebmacro">Unknown found text occurs as an action to try</span> <span class="cwebmacronumber">19.2.1</span>><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"><</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">>(</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"> = <<</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">shape</span><span class="plain"> == </span><span class="constant">NO_UTSHAPE</span><span class="plain">) {</span>
|
|
<span class="plain"><</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">>(</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"> = <<</span><span class="identifier">r</span><span class="plain">>>;</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"> >= 0) && (</span><span class="identifier">current_sentence</span><span class="plain">) &&</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">))) &&</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>
|
|
<<span class="cwebmacro">Unknown found text occurs as a text substitution</span> <span class="cwebmacronumber">19.2.2</span>>
|
|
<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">) && (</span><span class="identifier">shape</span><span class="plain"> == </span><span class="constant">LIST_UTSHAPE</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">Issue a problem message for a compound condition which has gone bad</span> <span class="cwebmacronumber">19.2.3</span>>
|
|
<span class="reserved">else</span>
|
|
<<span class="cwebmacro">Issue a problem message for miscellaneous suspicious wordings</span> <span class="cwebmacronumber">19.2.4</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">§19</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_2_1"></a><b>§19.2.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Unknown found text occurs as an action to try</span> <span class="cwebmacronumber">19.2.1</span>> =
|
|
</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"><</span><span class="identifier">action</span><span class="plain">-</span><span class="identifier">pattern</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="functiontext">Dash::get_validation_case</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="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">§19.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20"></a><b>§20. </b>The <unknown-text-shape> 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"><</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">> ::=</span>
|
|
<span class="identifier">say</span><span class="plain"> ... | ==> </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"> ... | ==> </span><span class="constant">LIST_UTSHAPE</span>
|
|
<span class="plain">... ==> </span><span class="constant">NO_UTSHAPE</span>
|
|
|
|
<span class="plain"><</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">> ::=</span>
|
|
<span class="plain">, ... | ==> </span><<span class="cwebmacro">Issue PM_SayComma problem</span> <span class="cwebmacronumber">20.1</span>>
|
|
<span class="identifier">unicode</span><span class="plain"> ... | ==> </span><<span class="cwebmacro">Issue PM_SayUnicode problem</span> <span class="cwebmacronumber">20.2</span>>
|
|
<span class="plain">...</span><span class="element"> condition</span><span class="plain"> | ==> </span><<span class="cwebmacro">Issue PM_SayUnknownCondition problem</span> <span class="cwebmacronumber">20.4</span>>
|
|
<span class="identifier">otherwise</span><span class="plain">/</span><span class="reserved">else</span><span class="plain"> *** | ==> </span><<span class="cwebmacro">Issue PM_SayElseMisplaced problem</span> <span class="cwebmacronumber">20.3</span>>
|
|
<span class="plain">... ==> </span><<span class="cwebmacro">Issue PM_SayUnknown problem</span> <span class="cwebmacronumber">20.5</span>>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20_1"></a><b>§20.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_SayComma problem</span> <span class="cwebmacronumber">20.1</span>> =
|
|
</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">§20</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20_2"></a><b>§20.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_SayUnicode problem</span> <span class="cwebmacronumber">20.2</span>> =
|
|
</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">§20</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20_3"></a><b>§20.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_SayElseMisplaced problem</span> <span class="cwebmacronumber">20.3</span>> =
|
|
</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">§20</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20_4"></a><b>§20.4. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_SayUnknownCondition problem</span> <span class="cwebmacronumber">20.4</span>> =
|
|
</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">§20</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20_5"></a><b>§20.5. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_SayUnknown problem</span> <span class="cwebmacronumber">20.5</span>> =
|
|
</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">§20</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_2_2"></a><b>§19.2.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Unknown found text occurs as a text substitution</span> <span class="cwebmacronumber">19.2.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="plain"><</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">>(</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">§19.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_2_3"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Issue a problem message for a compound condition which has gone bad</span> <span class="cwebmacronumber">19.2.3</span>> =
|
|
</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"><</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">>(</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"> = <<</span><span class="identifier">r</span><span class="plain">>>;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">dubious</span><span class="plain"> & </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"> & </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">§19.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21"></a><b>§21. </b>These are cases where the wording used in the source text suggests some
|
|
common misunderstanding.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain"><</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">> ::=</span>
|
|
<span class="identifier">turns</span><span class="plain"> | ==> </span><<span class="cwebmacro">Issue PM_NumberOfTurns problem</span> <span class="cwebmacronumber">21.1</span>>
|
|
<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"> | ==> </span><<span class="cwebmacro">Issue PM_OutOfPlay problem</span> <span class="cwebmacronumber">21.2</span>>
|
|
<span class="identifier">unicode</span><span class="plain"> ... | ==> </span><<span class="cwebmacro">Issue PM_MidTextUnicode problem</span> <span class="cwebmacronumber">21.5</span>>
|
|
<span class="plain">...</span><span class="element"> condition</span><span class="plain"> | ==> </span><<span class="cwebmacro">Issue PM_UnknownCondition problem</span> <span class="cwebmacronumber">21.6</span>>
|
|
<span class="plain">... ==> </span><<span class="cwebmacro">Issue PM_Unknown problem</span> <span class="cwebmacronumber">21.8</span>>
|
|
|
|
<span class="plain"><</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">> ::=</span>
|
|
<span class="plain">... ^</span><span class="identifier">option</span><span class="plain"> | ==> </span><<span class="cwebmacro">Issue PM_OptionlessOption problem</span> <span class="cwebmacronumber">21.3</span>>
|
|
<span class="plain">... ==> </span><<span class="cwebmacro">Issue PM_Unknown problem</span> <span class="cwebmacronumber">21.8</span>>
|
|
|
|
<span class="plain"><</span><span class="identifier">unknown</span><span class="reserved">-activity</span><span class="plain">-</span><span class="identifier">diagnosis</span><span class="plain">> ::=</span>
|
|
<span class="plain">... </span><span class="identifier">of</span><span class="plain"> | ==> </span><<span class="cwebmacro">Issue PM_ActivityOf problem</span> <span class="cwebmacronumber">21.4</span>>
|
|
<span class="plain">... </span><span class="reserved">for</span><span class="plain"> | ==> </span><<span class="cwebmacro">Issue PM_ActivityWithFor problem</span> <span class="cwebmacronumber">21.7</span>>
|
|
<span class="plain">... ==> </span><<span class="cwebmacro">Issue PM_Unknown problem</span> <span class="cwebmacronumber">21.8</span>>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21_1"></a><b>§21.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_NumberOfTurns problem</span> <span class="cwebmacronumber">21.1</span>> =
|
|
</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>
|
|
<<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>><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">§21</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21_2"></a><b>§21.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_OutOfPlay problem</span> <span class="cwebmacronumber">21.2</span>> =
|
|
</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>
|
|
<<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>><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">§21</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21_3"></a><b>§21.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_OptionlessOption problem</span> <span class="cwebmacronumber">21.3</span>> =
|
|
</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>
|
|
<<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>><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">§21</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21_4"></a><b>§21.4. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_ActivityOf problem</span> <span class="cwebmacronumber">21.4</span>> =
|
|
</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>
|
|
<<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>><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">§21</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21_5"></a><b>§21.5. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_MidTextUnicode problem</span> <span class="cwebmacronumber">21.5</span>> =
|
|
</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>
|
|
<<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>><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">§21</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21_6"></a><b>§21.6. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_UnknownCondition problem</span> <span class="cwebmacronumber">21.6</span>> =
|
|
</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>
|
|
<<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</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. 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">§21</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21_7"></a><b>§21.7. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_ActivityWithFor problem</span> <span class="cwebmacronumber">21.7</span>> =
|
|
</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>
|
|
<<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>><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">§21</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21_8"></a><b>§21.8. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_Unknown problem</span> <span class="cwebmacronumber">21.8</span>> =
|
|
</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>
|
|
<<span class="cwebmacro">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</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">§21</a> (three times).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21_1_1"></a><b>§21.1.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue the generic unknown wording message</span> <span class="cwebmacronumber">21.1.1</span>> =
|
|
</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">§21.1</a>, <a href="#SP21_2">§21.2</a>, <a href="#SP21_3">§21.3</a>, <a href="#SP21_4">§21.4</a>, <a href="#SP21_5">§21.5</a>, <a href="#SP21_6">§21.6</a>, <a href="#SP21_7">§21.7</a>, <a href="#SP21_8">§21.8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_2_4"></a><b>§19.2.4. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue a problem message for miscellaneous suspicious wordings</span> <span class="cwebmacronumber">19.2.4</span>> =
|
|
</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"><</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">>(</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"><</span><span class="identifier">unknown</span><span class="reserved">-activity</span><span class="plain">-</span><span class="identifier">diagnosis</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="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="plain"><</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">>(</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">§19.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_3"></a><b>§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 — where a property's name is used without any indication of
|
|
its owner.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Step (5.b) Deal with bare property names</span> <span class="cwebmacronumber">19.3</span>> =
|
|
</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">>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="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>><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">§19</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_3_1"></a><b>§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">
|
|
<<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>> =
|
|
</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>
|
|
<<span class="cwebmacro">Coerce into a property of the "self" object</span> <span class="cwebmacronumber">19.3.1.1</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">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="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">>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">§19.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_3_1_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Coerce into a property of the "self" object</span> <span class="cwebmacronumber">19.3.1.1</span>> =
|
|
</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">-></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">-></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">-></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">§19.3.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_4"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (5.c) Deal with any attached proposition</span> <span class="cwebmacronumber">19.4</span>> =
|
|
</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">§19</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_5"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (5.d) Apply miscellaneous other coercions</span> <span class="cwebmacronumber">19.5</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
|
|
<<span class="cwebmacro">Step (5.d.1) Coerce TEST ACTION to constant action</span> <span class="cwebmacronumber">19.5.1</span>><span class="plain">;</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<<span class="cwebmacro">Step (5.d.2) Coerce constant TEXT and TEXT ROUTINE to UNDERSTANDING</span> <span class="cwebmacronumber">19.5.2</span>><span class="plain">;</span>
|
|
<<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>><span class="plain">;</span>
|
|
<<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>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP19">§19</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_5_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (5.d.1) Coerce TEST ACTION to constant action</span> <span class="cwebmacronumber">19.5.1</span>> =
|
|
</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">)) && (</span><span class="identifier">kind_expected</span><span class="plain">) &&</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">>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">>down</span><span class="plain">);</span>
|
|
<span class="identifier">p</span><span class="plain">-</span><span class="element">>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">) &&</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">>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">§19.5</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_5_2"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (5.d.2) Coerce constant TEXT and TEXT ROUTINE to UNDERSTANDING</span> <span class="cwebmacronumber">19.5.2</span>> =
|
|
</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">)) &&</span>
|
|
<span class="plain">(</span><span class="identifier">K_understanding</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_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">§19.5</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_5_3"></a><b>§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 — 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">
|
|
<<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>> =
|
|
</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">) && (</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>
|
|
<<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>><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">) && (</span><span class="identifier">q</span><span class="plain"> != </span><span class="identifier">not_exists_quantifier</span><span class="plain">) && (</span><span class="identifier">q</span><span class="plain"> != </span><span class="identifier">for_all_quantifier</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">Issue a problem message for a quantified proposition in the description</span> <span class="cwebmacronumber">19.5.3.1</span>><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>
|
|
<<span class="cwebmacro">Issue a problem message for a malformed proposition in the description</span> <span class="cwebmacronumber">19.5.3.3</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">as_con</span><span class="plain">);</span>
|
|
<span class="identifier">p</span><span class="plain">-</span><span class="element">>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">§19.5</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_5_3_1"></a><b>§19.5.3.1. </b>This is for undescriptive descriptions, really.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Issue a problem message for a quantified proposition in the description</span> <span class="cwebmacronumber">19.5.3.1</span>> =
|
|
</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">§19.5.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_5_3_2"></a><b>§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">
|
|
<<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>> =
|
|
</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">§19.5.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_5_3_3"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Issue a problem message for a malformed proposition in the description</span> <span class="cwebmacronumber">19.5.3.3</span>> =
|
|
</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">§19.5.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_5_4"></a><b>§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">
|
|
<<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>> =
|
|
</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">§19.5</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_6"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (5.e) The Main Rule of Type-Checking</span> <span class="cwebmacronumber">19.6</span>> =
|
|
</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>
|
|
<<span class="cwebmacro">Step (5.e.2) Exception: when expecting a generic or actual CONSTANT</span> <span class="cwebmacronumber">19.6.1</span>><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><<span class="cwebmacro">Step (5.e.3) Main rule</span> <span class="cwebmacronumber">19.6.2</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP19">§19</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_6_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (5.e.2) Exception: when expecting a generic or actual CONSTANT</span> <span class="cwebmacronumber">19.6.1</span>> =
|
|
</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">) && (</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>
|
|
<<span class="cwebmacro">Fail with a mismatched value problem message</span> <span class="cwebmacronumber">19.6.1.1</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="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">§19.6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_6_1_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Fail with a mismatched value problem message</span> <span class="cwebmacronumber">19.6.1.1</span>> =
|
|
</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">§19.6.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_6_2"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Step (5.e.3) Main rule</span> <span class="cwebmacronumber">19.6.2</span>> =
|
|
</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">)) && (</span><span class="identifier">kind_expected</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">Fail with a warning about literal descriptions</span> <span class="cwebmacronumber">19.6.2.1</span>>
|
|
<span class="reserved">else</span>
|
|
<<span class="cwebmacro">Fail with a catch-all typechecking problem message</span> <span class="cwebmacronumber">19.6.2.2</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_6">§19.6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_6_2_1"></a><b>§19.6.2.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Fail with a warning about literal descriptions</span> <span class="cwebmacronumber">19.6.2.1</span>> =
|
|
</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">)) &&</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">§19.6.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19_6_2_2"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Fail with a catch-all typechecking problem message</span> <span class="cwebmacronumber">19.6.2.2</span>> =
|
|
</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">§19.6.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP22"></a><b>§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">§10.1.1.3.1.2</a>, 22/dptd (<a href="22-dptd.html#SP4">§4</a>).</p>
|
|
|
|
<p class="endnote">The function Dash::verdict_to_text is used in <a href="#SP11_9_2_2">§11.9.2.2</a>, 25/in (<a href="25-in.html#SP10">§10</a>).</p>
|
|
|
|
<p class="endnote">The function Dash::quick_verdict_to_text is used in <a href="#SP11_9_2_2">§11.9.2.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23"></a><b>§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"> & (~</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"> & </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">§11.9.2.2.1</a>, <a href="#SP11_9_1_1">§11.9.1.1</a>, <a href="#SP11_9_1_1_11">§11.9.1.1.11</a>, <a href="#SP11_9_1_1_12">§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">§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">§11.9.2.2</a>, <a href="#SP11_9_2_3_1">§11.9.2.3.1</a>, <a href="#SP11_9_1_1_5_2">§11.9.1.1.5.2</a>, <a href="#SP15_1">§15.1</a>, <a href="#SP22">§22</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24"></a><b>§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">§30</a>), 21/ac (<a href="21-ac.html#SP10_7">§10.7</a>), 23/abc (<a href="23-abc.html#SP1">§1</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP25"></a><b>§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">) && (</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">) && (</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">) && (</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">)) &&</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">) && (</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="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">) &&</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">) && (</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="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">§19.2.1</a>.</p>
|
|
|
|
<p class="endnote">The function Dash::get_validation_case is used in <a href="#SP19_2_1">§19.2.1</a>.</p>
|
|
|
|
<p class="endnote">The function Dash::suspend_validation is used in 25/pi (<a href="25-pi.html#SP4">§4</a>).</p>
|
|
|
|
<p class="endnote">The function Dash::validate_parameter is used in 10/teav (<a href="10-teav.html#SP23">§23</a>), 21/ac (<a href="21-ac.html#SP10_5">§10.5</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP26"></a><b>§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">) && (</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">§28</a>, 25/cii (<a href="25-cii.html#SP3_7">§3.7</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP27"></a><b>§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 — 12 is indeed a number — 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">) && (</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">§11.5</a>, <a href="#SP25">§25</a>, 14/sp (<a href="14-sp.html#SP7_5">§7.5</a>), 14/ds (<a href="14-ds.html#SP12_2">§12.2</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP28"></a><b>§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"><</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">>-></span><span class="identifier">multiplicitous</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain"><</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">>-></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"> (<</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">>(</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">(<</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">>, 1);</span>
|
|
<span class="identifier">W</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(<</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">>, 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"> (<</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">kind</span><span class="plain">>(</span><span class="identifier">T</span><span class="plain">)) </span><span class="identifier">K</span><span class="plain"> = <<</span><span class="identifier">rp</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">s</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">-</span><span class="identifier">uncached</span><span class="plain">>(</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"> = <<</span><span class="identifier">rp</span><span class="plain">>>;</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">-></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"><</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">>-></span><span class="identifier">multiplicitous</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain"><</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">>-></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"> > 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">>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">§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>
|
|
|