1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/core-module/11-tcp.html
2020-04-07 23:02:44 +01:00

956 lines
111 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>11/sm</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../compiler.html"><b>compiler tools</b></a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul>
<h2>Compiler Webs</h2>
<ul>
<li><a href="../inbuild/index.html">inbuild</a></li>
<li><a href="../inform7/index.html">inform7</a></li>
<li><a href="../inter/index.html">inter</a></li>
</ul>
<h2>Inbuild Modules</h2>
<ul>
<li><a href="../inbuild-module/index.html">inbuild</a></li>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../syntax-module/index.html">syntax</a></li>
<li><a href="../html-module/index.html">html</a></li>
</ul>
<h2>Inform7 Modules</h2>
<ul>
<li><a href="../core-module/index.html">core</a></li>
<li><a href="../problems-module/index.html">problems</a></li>
<li><a href="../inflections-module/index.html">inflections</a></li>
<li><a href="../linguistics-module/index.html">linguistics</a></li>
<li><a href="../kinds-module/index.html">kinds</a></li>
<li><a href="../if-module/index.html">if</a></li>
<li><a href="../multimedia-module/index.html">multimedia</a></li>
<li><a href="../index-module/index.html">index</a></li>
</ul>
<h2>Inter Modules</h2>
<ul>
<li><a href="../inter-module/index.html">inter</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../codegen-module/index.html">codegen</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '11/tcp' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="../compiler.html">Compiler Modules</a></li><li><a href="index.html">core</a></li><li><a href="index.html#11">Chapter 11: Predicate Calculus</a></li><li><b>Type Check Propositions</b></li></ul><p class="purpose">Predicate calculus is a largely symbolic exercise, and its rules of working tend to assume that all predicates are meaningful for all terms: this means, for instance, that "if blue is 14" is likely to make a well-formed sentence in predicate calculus. In this section we reject such propositions on the grounds that they violate type-checking requirements on relations -- in this example, the equality relation.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP4">&#167;4. Problem reporting kit</a></li><li><a href="#SP6">&#167;6. Type-checking whole propositions</a></li><li><a href="#SP6_1">&#167;6.1. Finding kinds for variables</a></li><li><a href="#SP6_5">&#167;6.5. Type-checking enforced on predicate-like atoms</a></li><li><a href="#SP7">&#167;7. The kind of a term</a></li><li><a href="#SP10">&#167;10. Type-checking predicates</a></li><li><a href="#SP12">&#167;12. Two problem messages needed more than once</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Definitions. </b></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>We can unambiguously find the kind of value of any constant C, so if a
proposition's terms are all constant then type-checking is easy. is(4, <code class="display"><span class="extract">score</span></code>)
good, is(4, <code class="display"><span class="extract">"fish"</span></code>) bad. The subtlety comes in interpreting
is(4, x), where x is a variable. Our calculus allows variables to
range over many domains &mdash; numbers, texts, scenes, objects, and so on.
So it turns out to be convenient to have a structure holding a choice of kinds
of value for the contents of the variables; such structures exist temporarily
on the stack while we work.
</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">variable_type_assignment</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">assigned_kinds</span><span class="plain">[26]; </span><span class="comment">one for each of the 26 variables</span>
<span class="plain">} </span><span class="reserved">variable_type_assignment</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure variable_type_assignment is private to this section.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Another convenience is a sort of kit for preparing problem messages:
</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">tc_problem_kit</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">issue_error</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">ew_text</span><span class="plain">;</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">intention</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">log_to_I6_text</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">flag_problem</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">tc_problem_kit</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure tc_problem_kit is accessed in 2/si, 12/ter, 12/qr, 15/cr and here.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Problem reporting kit. </b>The caller to <code class="display"><span class="extract">Calculus::Propositions::Checker::type_check</span></code> has to fill this form out first. Paperwork,
what can you do, eh?
</p>
<pre class="display">
<span class="reserved">tc_problem_kit</span><span class="plain"> </span><span class="functiontext">Calculus::Propositions::Checker::tc_no_problem_reporting</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">tc_problem_kit</span><span class="plain"> </span><span class="identifier">tck</span><span class="plain">;</span>
<span class="identifier">tck</span><span class="plain">.</span><span class="element">issue_error</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="identifier">tck</span><span class="plain">.</span><span class="element">ew_text</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">; </span><span class="identifier">tck</span><span class="plain">.</span><span class="element">intention</span><span class="plain"> = </span><span class="string">"be silent checking"</span><span class="plain">;</span>
<span class="identifier">tck</span><span class="plain">.</span><span class="element">log_to_I6_text</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="identifier">tck</span><span class="plain">.</span><span class="element">flag_problem</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">tck</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">tc_problem_kit</span><span class="plain"> </span><span class="functiontext">Calculus::Propositions::Checker::tc_problem_reporting</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">char</span><span class="plain"> *</span><span class="identifier">intent</span><span class="plain">) {</span>
<span class="reserved">tc_problem_kit</span><span class="plain"> </span><span class="identifier">tck</span><span class="plain"> = </span><span class="functiontext">Calculus::Propositions::Checker::tc_no_problem_reporting</span><span class="plain">();</span>
<span class="identifier">tck</span><span class="plain">.</span><span class="element">issue_error</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="identifier">tck</span><span class="plain">.</span><span class="element">ew_text</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">; </span><span class="identifier">tck</span><span class="plain">.</span><span class="element">intention</span><span class="plain"> = </span><span class="identifier">intent</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">tck</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Propositions::Checker::tc_no_problem_reporting is used in <a href="#SP5">&#167;5</a>, 11/pr (<a href="11-pr.html#SP35_1_1">&#167;35.1.1</a>), 12/dtd (<a href="12-dtd.html#SP10">&#167;10</a>, <a href="12-dtd.html#SP13">&#167;13</a>, <a href="12-dtd.html#SP21">&#167;21</a>), 14/ds (<a href="14-ds.html#SP3">&#167;3</a>, <a href="14-ds.html#SP5">&#167;5</a>, <a href="14-ds.html#SP8">&#167;8</a>, <a href="14-ds.html#SP9">&#167;9</a>, <a href="14-ds.html#SP10">&#167;10</a>), 14/ds2 (<a href="14-ds2.html#SP19_4">&#167;19.4</a>), 25/cp (<a href="25-cp.html#SP5_3_5_3">&#167;5.3.5.3</a>), 26/ts (<a href="26-ts.html#SP11_1">&#167;11.1</a>, <a href="26-ts.html#SP13">&#167;13</a>).</p>
<p class="endnote">The function Calculus::Propositions::Checker::tc_problem_reporting is used in 12/ap (<a href="12-ap.html#SP9_3">&#167;9.3</a>), 12/dtd (<a href="12-dtd.html#SP28">&#167;28</a>), 14/ds2 (<a href="14-ds2.html#SP19_4">&#167;19.4</a>), 15/ma (<a href="15-ma.html#SP13">&#167;13</a>).</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>A version used only for the internal testing mode, when we print the outcome
into the debugging log, but diverted to an I6 string in the compiled code.
</p>
<pre class="display">
<span class="reserved">tc_problem_kit</span><span class="plain"> </span><span class="functiontext">Calculus::Propositions::Checker::tc_problem_logging</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">tc_problem_kit</span><span class="plain"> </span><span class="identifier">tck</span><span class="plain"> = </span><span class="functiontext">Calculus::Propositions::Checker::tc_no_problem_reporting</span><span class="plain">();</span>
<span class="identifier">tck</span><span class="plain">.</span><span class="element">intention</span><span class="plain"> = </span><span class="string">"be internal testing"</span><span class="plain">; </span><span class="identifier">tck</span><span class="plain">.</span><span class="element">log_to_I6_text</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">tck</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Propositions::Checker::tc_problem_logging is used in 26/ts (<a href="26-ts.html#SP11_1">&#167;11.1</a>, <a href="26-ts.html#SP13">&#167;13</a>).</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Type-checking whole propositions. </b>This section provides a single routine to the rest of Inform: <code class="display"><span class="extract">Calculus::Propositions::Checker::type_check</span></code>.
We determine the kinds for all variables, then work through the proposition,
ensuring that every predicate-like atom has terms which match at least one
possible reading of the meaning of the atom.
</p>
<p class="inwebparagraph">As usual in Inform, type-checking is not a passive process. If it can make
sense of the proposition by changing it, it will do so.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Calculus::Propositions::Checker::type_check</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="reserved">tc_problem_kit</span><span class="plain"> </span><span class="identifier">tck_s</span><span class="plain">) {</span>
<span class="identifier">TRAVERSE_VARIABLE</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">);</span>
<span class="reserved">variable_type_assignment</span><span class="plain"> </span><span class="identifier">vta</span><span class="plain">;</span>
<span class="reserved">tc_problem_kit</span><span class="plain"> *</span><span class="identifier">tck</span><span class="plain"> = &amp;</span><span class="identifier">tck_s</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">"Type-checking proposition: $D\n"</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</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="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="reserved">if</span><span class="plain"> (</span><span class="functiontext">Calculus::Variables::is_well_formed</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"type-checking malformed proposition"</span><span class="plain">);</span>
&lt;<span class="cwebmacro">First make sure any constants in the proposition have themselves been typechecked</span> <span class="cwebmacronumber">6.1</span>&gt;<span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;26; </span><span class="identifier">j</span><span class="plain">++) </span><span class="identifier">vta</span><span class="plain">.</span><span class="element">assigned_kinds</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Look at KIND atoms to see what kinds of value are asserted for the variables</span> <span class="cwebmacronumber">6.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Look at KIND atoms to reject unarticled shockers</span> <span class="cwebmacronumber">6.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Assume any still-unfathomable variables represent objects</span> <span class="cwebmacronumber">6.4</span>&gt;<span class="plain">;</span>
<span class="identifier">TRAVERSE_PROPOSITION</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">arity</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++) </span><span class="functiontext">Calculus::Propositions::Checker::kind_of_term</span><span class="plain">(&amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]), &amp;</span><span class="identifier">vta</span><span class="plain">, </span><span class="identifier">tck</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tck</span><span class="plain">-&gt;</span><span class="element">flag_problem</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">pl</span><span class="plain">-&gt;</span><span class="element">element</span><span class="plain"> == </span><span class="constant">KIND_ATOM</span><span class="plain">)</span>
&lt;<span class="cwebmacro">A KIND atom is not allowed if it can be proved to be false</span> <span class="cwebmacronumber">6.5</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">element</span><span class="plain"> == </span><span class="constant">PREDICATE_ATOM</span><span class="plain">) &amp;&amp; (</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">arity</span><span class="plain"> == </span><span class="constant">2</span><span class="plain">))</span>
&lt;<span class="cwebmacro">A binary predicate is required to apply to terms of the right kinds</span> <span class="cwebmacronumber">6.7</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">element</span><span class="plain"> == </span><span class="constant">PREDICATE_ATOM</span><span class="plain">) &amp;&amp; (</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">arity</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">))</span>
&lt;<span class="cwebmacro">A unary predicate is required to have an interpretation matching the kind of its term</span> <span class="cwebmacronumber">6.6</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">element</span><span class="plain"> == </span><span class="constant">EVERYWHERE_ATOM</span><span class="plain">)</span>
&lt;<span class="cwebmacro">An EVERYWHERE atom needs its term to be an object</span> <span class="cwebmacronumber">6.9</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">element</span><span class="plain"> == </span><span class="constant">NOWHERE_ATOM</span><span class="plain">)</span>
&lt;<span class="cwebmacro">A NOWHERE atom needs its term to be an object</span> <span class="cwebmacronumber">6.10</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">element</span><span class="plain"> == </span><span class="constant">ISAKIND_ATOM</span><span class="plain">)</span>
&lt;<span class="cwebmacro">An ISAKIND atom needs its term to be an object</span> <span class="cwebmacronumber">6.8</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">element</span><span class="plain"> == </span><span class="constant">HERE_ATOM</span><span class="plain">)</span>
&lt;<span class="cwebmacro">A HERE atom needs its term to be an object</span> <span class="cwebmacronumber">6.11</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tck</span><span class="plain">-&gt;</span><span class="element">log_to_I6_text</span><span class="plain">) </span>&lt;<span class="cwebmacro">Show the variable assignment in the debugging log</span> <span class="cwebmacronumber">6.12</span>&gt;<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 Calculus::Propositions::Checker::type_check is used in 11/pr (<a href="11-pr.html#SP35_1_1">&#167;35.1.1</a>), 12/ap (<a href="12-ap.html#SP9_3">&#167;9.3</a>), 12/dtd (<a href="12-dtd.html#SP10">&#167;10</a>, <a href="12-dtd.html#SP13">&#167;13</a>, <a href="12-dtd.html#SP21">&#167;21</a>, <a href="12-dtd.html#SP28">&#167;28</a>), 14/ds (<a href="14-ds.html#SP3">&#167;3</a>, <a href="14-ds.html#SP5">&#167;5</a>, <a href="14-ds.html#SP8">&#167;8</a>, <a href="14-ds.html#SP9">&#167;9</a>, <a href="14-ds.html#SP10">&#167;10</a>), 14/ds2 (<a href="14-ds2.html#SP19_4">&#167;19.4</a>), 15/ma (<a href="15-ma.html#SP13">&#167;13</a>), 25/cp (<a href="25-cp.html#SP5_3_5_3">&#167;5.3.5.3</a>), 26/ts (<a href="26-ts.html#SP11_1">&#167;11.1</a>, <a href="26-ts.html#SP13">&#167;13</a>).</p>
<p class="inwebparagraph"><a id="SP6_1"></a><b>&#167;6.1. Finding kinds for variables. </b>Every specification compiled by Inform has to pass through type-checking.
That includes the ones which occur as constants inside propositions, and this is
where.
</p>
<p class="inwebparagraph">The presence of an <code class="display"><span class="extract">UNKNOWN_NT</span></code> constant indicates something which failed to be
recognised by the S-parser. That shouldn't happen, but we allow for it so that
we can recover from an already reported problem.
</p>
<p class="inwebparagraph">Perhaps surprisingly, we don't reject generic constants: this is so that
sentences like
</p>
<blockquote>
<p>A thing usually weighs 10kg.</p>
</blockquote>
<p class="inwebparagraph">...can work &mdash; here the generic constant for "thing" is treated as a noun,
since it can be the subject of inferences all by itself. So it can legitimately
be a term in a proposition.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">First make sure any constants in the proposition have themselves been typechecked</span> <span class="cwebmacronumber">6.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TRAVERSE_PROPOSITION</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">arity</span><span class="plain">; </span><span class="identifier">j</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="functiontext">Calculus::Terms::constant_underlying</span><span class="plain">(&amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[</span><span class="identifier">j</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="reserved">int</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">spec</span><span class="plain">, </span><span class="constant">UNKNOWN_NT</span><span class="plain">))) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tck</span><span class="plain">-&gt;</span><span class="element">issue_error</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">spec</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext">Dash::check_value_silently</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="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>&lt;<span class="cwebmacro">Recover from problem in S-parser by not issuing problem</span> <span class="cwebmacronumber">6.1.1</span>&gt;<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="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_2"></a><b>&#167;6.2. </b>If the proposition contains contradictory <code class="display"><span class="extract">KIND</span></code> atoms, it automatically fails
type-checking, even if there is no implication that both apply at once. This
throws out, for instance:
</p>
<pre class="display">
<span class="plain">1. a scene which is not a number</span>
<span class="plain">[ scene(x) &amp; NOT[ number(x) NOT] ]</span>
<span class="plain">Failed: proposition would not type-check</span>
<span class="plain">x is both scene and number</span>
</pre>
<p class="inwebparagraph">It could be argued that all scenes ought to pass this proposition, but we will
treat it as a piece of nonsense, like "if Wednesday is not custard".
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Look at KIND atoms to see what kinds of value are asserted for the variables</span> <span class="cwebmacronumber">6.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TRAVERSE_PROPOSITION</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">element</span><span class="plain"> == </span><span class="constant">KIND_ATOM</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">v</span><span class="plain"> = </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[0].</span><span class="element">variable</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">v</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">new_kind</span><span class="plain"> = </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">assert_kind</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">new_kind</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">)) </span><span class="identifier">new_kind</span><span class="plain"> = </span><span class="identifier">K_object</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">old_kind</span><span class="plain"> = </span><span class="identifier">vta</span><span class="plain">.</span><span class="element">assigned_kinds</span><span class="plain">[</span><span class="identifier">v</span><span class="plain">];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">old_kind</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">old_kind</span><span class="plain">, </span><span class="identifier">new_kind</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">tck</span><span class="plain">-&gt;</span><span class="element">log_to_I6_text</span><span class="plain">)</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%c is both $u and $u\n"</span><span class="plain">, </span><span class="identifier">pcalc_vars</span><span class="plain">[</span><span class="identifier">v</span><span class="plain">], </span><span class="identifier">old_kind</span><span class="plain">, </span><span class="identifier">new_kind</span><span class="plain">);</span>
<span class="functiontext">Calculus::Propositions::Checker::issue_kind_typecheck_error</span><span class="plain">(</span><span class="identifier">old_kind</span><span class="plain">, </span><span class="identifier">new_kind</span><span class="plain">, </span><span class="identifier">tck</span><span class="plain">, </span><span class="identifier">pl</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::Behaviour::definite</span><span class="plain">(</span><span class="identifier">new_kind</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="identifier">new_kind</span><span class="plain"> = </span><span class="identifier">old_kind</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">vta</span><span class="plain">.</span><span class="element">assigned_kinds</span><span class="plain">[</span><span class="identifier">v</span><span class="plain">] = </span><span class="identifier">new_kind</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="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_3"></a><b>&#167;6.3. </b>The following is arguably a problem which should have been thrown earlier,
but it's a very subtle one, and we want to use it only when everything else
(more or less) has worked.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Look at KIND atoms to reject unarticled shockers</span> <span class="cwebmacronumber">6.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TRAVERSE_PROPOSITION</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">element</span><span class="plain"> == </span><span class="constant">KIND_ATOM</span><span class="plain">) &amp;&amp; (</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">unarticled</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tck</span><span class="plain">-&gt;</span><span class="element">log_to_I6_text</span><span class="plain">)</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Rejecting as unarticled\n"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tck</span><span class="plain">-&gt;</span><span class="element">issue_error</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="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_BareKindVariable</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The sentence %1 seems to use a kind variable by its letter "</span>
<span class="string">"alone in the context of a noun, which Inform doesn't allow. "</span>
<span class="string">"It's fine to say 'if the noun is a K', for example, but "</span>
<span class="string">"not 'if K is number'. By putting 'a' or 'an' in front of the "</span>
<span class="string">"kind variable, you make clear that I'm supposed to perform "</span>
<span class="string">"matching against a description."</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="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_4"></a><b>&#167;6.4. </b>It's possible for a proposition to specify nothing about the kind of a
variable (usually a free one). If so, it's assumed to be an object. For
instance, if we define
</p>
<blockquote>
<p>Definition: a container is empty if the number of things in it is 0.</p>
</blockquote>
<p class="inwebparagraph">then we find that, say:
</p>
<pre class="display">
<span class="plain">1. empty which is empty</span>
<span class="plain">[ 'empty'(x) &amp; 'empty'(x) ]</span>
<span class="plain">x (free) - object.</span>
</pre>
<p class="inwebparagraph">though in fact it would also have been viable for x to be a rulebook, a list,
or various other kinds of value.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Assume any still-unfathomable variables represent objects</span> <span class="cwebmacronumber">6.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;26; </span><span class="identifier">j</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">vta</span><span class="plain">.</span><span class="element">assigned_kinds</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="identifier">vta</span><span class="plain">.</span><span class="element">assigned_kinds</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] = </span><span class="identifier">K_object</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_1_1"></a><b>&#167;6.1.1. </b>The following is really rather paranoid; it ought to be certain that a
problem message has already been issued, but just in case not...
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Recover from problem in S-parser by not issuing problem</span> <span class="cwebmacronumber">6.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tck</span><span class="plain">-&gt;</span><span class="element">log_to_I6_text</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Atom $o contains failed constant\n"</span><span class="plain">, </span><span class="identifier">pl</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tck</span><span class="plain">-&gt;</span><span class="element">issue_error</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="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">spec</span><span class="plain">));</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The sentence %1 seems to contain a value '%2' which I can't make "</span>
<span class="string">"any sense of."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Stare at this, then: $P\n"</span><span class="plain">, </span><span class="identifier">spec</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="#SP6_1">&#167;6.1</a>.</p>
<p class="inwebparagraph"><a id="SP6_5"></a><b>&#167;6.5. Type-checking enforced on predicate-like atoms. </b>As with contradictory <code class="display"><span class="extract">KIND</span></code> atoms applied to variables, we will reject any
<code class="display"><span class="extract">KIND</span></code> atom applied to a constant if it necessarily fails &mdash; even when the
sense of the proposition is arguably correct. For example:
</p>
<pre class="display">
<span class="plain">1. 100 is not a text</span>
<span class="plain">[ NOT[ text('100') NOT] ]</span>
<span class="plain">Failed: proposition would not type-check</span>
<span class="plain">Term '100' is number not text</span>
</pre>
<p class="inwebparagraph">"100 is not a number" would pass, on the other hand. It is obviously false,
but not meaningless.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">A KIND atom is not allowed if it can be proved to be false</span> <span class="cwebmacronumber">6.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">need_to_find</span><span class="plain"> = </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">assert_kind</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">need_to_find</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">)) </span><span class="identifier">need_to_find</span><span class="plain"> = </span><span class="identifier">K_object</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">actually_find</span><span class="plain"> = </span><span class="functiontext">Calculus::Propositions::Checker::kind_of_term</span><span class="plain">(&amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[0]), &amp;</span><span class="identifier">vta</span><span class="plain">, </span><span class="identifier">tck</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">actually_find</span><span class="plain">, </span><span class="identifier">need_to_find</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">tck</span><span class="plain">-&gt;</span><span class="element">log_to_I6_text</span><span class="plain">)</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Term $0 is $u not $u\n"</span><span class="plain">, &amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[0]), </span><span class="identifier">actually_find</span><span class="plain">, </span><span class="identifier">need_to_find</span><span class="plain">);</span>
<span class="functiontext">Calculus::Propositions::Checker::issue_kind_typecheck_error</span><span class="plain">(</span><span class="identifier">actually_find</span><span class="plain">, </span><span class="identifier">need_to_find</span><span class="plain">, </span><span class="identifier">tck</span><span class="plain">, </span><span class="identifier">pl</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="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_6"></a><b>&#167;6.6. </b>See below, of course.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">A unary predicate is required to have an interpretation matching the kind of its term</span> <span class="cwebmacronumber">6.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Calculus::Propositions::Checker::type_check_unary_predicate</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, &amp;</span><span class="identifier">vta</span><span class="plain">, </span><span class="identifier">tck</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">tck</span><span class="plain">-&gt;</span><span class="element">log_to_I6_text</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Adjective $o cannot be applied\n"</span><span class="plain">, </span><span class="identifier">pl</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="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_7"></a><b>&#167;6.7. </b>The BP case is interesting because it forgives a failure in one case: of
is(t, C), where C is a constant representing a value of an enumerated
kind. Sentence conversion is actually quite good at distinguishing these cases
and can see the difference between "the bus is red" and "the fashionable hue
is red", but it is defeated by cases where adjectives representing values are
used about other values &mdash; "the Communist Rally is red", where "Communist
Rally" is a scene rather than an object, for instance. We first try requiring
<code class="display"><span class="extract">Rally</span></code> to be a colour: when that fails, we see if the atom red(<code class="display"><span class="extract">Rally</span></code>)
would work instead. If it would, we make the change within the proposition.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">A binary predicate is required to apply to terms of the right kinds</span> <span class="cwebmacronumber">6.7</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">binary_predicate</span><span class="plain"> *</span><span class="identifier">bp</span><span class="plain"> = </span><span class="identifier">RETRIEVE_POINTER_binary_predicate</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">predicate</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">BinaryPredicates::is_the_wrong_way_round</span><span class="plain">(</span><span class="identifier">bp</span><span class="plain">)) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"BP wrong way round"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Calculus::Propositions::Checker::type_check_binary_predicate</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, &amp;</span><span class="identifier">vta</span><span class="plain">, </span><span class="identifier">tck</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">bp</span><span class="plain"> == </span><span class="identifier">R_equality</span><span class="plain">) {</span>
<span class="identifier">adjective_usage</span><span class="plain"> *</span><span class="identifier">alt</span><span class="plain"> = </span><span class="functiontext">Calculus::Terms::noun_to_adj_conversion</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[1]);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">alt</span><span class="plain">) {</span>
<span class="reserved">pcalc_prop</span><span class="plain"> </span><span class="identifier">test_unary</span><span class="plain"> = *</span><span class="identifier">pl</span><span class="plain">;</span>
<span class="identifier">test_unary</span><span class="plain">.</span><span class="identifier">arity</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">test_unary</span><span class="plain">.</span><span class="identifier">predicate</span><span class="plain"> = </span><span class="identifier">STORE_POINTER_adjective_usage</span><span class="plain">(</span><span class="identifier">alt</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Calculus::Propositions::Checker::type_check_unary_predicate</span><span class="plain">(&amp;</span><span class="identifier">test_unary</span><span class="plain">, &amp;</span><span class="identifier">vta</span><span class="plain">, </span><span class="identifier">tck</span><span class="plain">) == </span><span class="identifier">NEVER_MATCH</span><span class="plain">)</span>
&lt;<span class="cwebmacro">The BP fails type-checking</span> <span class="cwebmacronumber">6.7.1</span>&gt;<span class="plain">;</span>
<span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">arity</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">predicate</span><span class="plain"> = </span><span class="identifier">STORE_POINTER_adjective_usage</span><span class="plain">(</span><span class="identifier">alt</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">The BP fails type-checking</span> <span class="cwebmacronumber">6.7.1</span>&gt;<span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">The BP fails type-checking</span> <span class="cwebmacronumber">6.7.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_7_1"></a><b>&#167;6.7.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">The BP fails type-checking</span> <span class="cwebmacronumber">6.7.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tck</span><span class="plain">-&gt;</span><span class="element">log_to_I6_text</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"BP $o cannot be applied\n"</span><span class="plain">, </span><span class="identifier">pl</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="#SP6_7">&#167;6.7</a> (three times).</p>
<p class="inwebparagraph"><a id="SP6_8"></a><b>&#167;6.8. </b><code class="display">
&lt;<span class="cwebmacrodefn">An ISAKIND atom needs its term to be an object</span> <span class="cwebmacronumber">6.8</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">actually_find</span><span class="plain"> = </span><span class="functiontext">Calculus::Propositions::Checker::kind_of_term</span><span class="plain">(&amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[0]), &amp;</span><span class="identifier">vta</span><span class="plain">, </span><span class="identifier">tck</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">actually_find</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">) == </span><span class="identifier">NEVER_MATCH</span><span class="plain">)</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"ISAKIND atom misapplied"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_9"></a><b>&#167;6.9. </b><code class="display">
&lt;<span class="cwebmacrodefn">An EVERYWHERE atom needs its term to be an object</span> <span class="cwebmacronumber">6.9</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">actually_find</span><span class="plain"> = </span><span class="functiontext">Calculus::Propositions::Checker::kind_of_term</span><span class="plain">(&amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[0]), &amp;</span><span class="identifier">vta</span><span class="plain">, </span><span class="identifier">tck</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">actually_find</span><span class="plain">, </span><span class="identifier">K_object</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">tck</span><span class="plain">-&gt;</span><span class="element">log_to_I6_text</span><span class="plain">)</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Term $0 is $u not an object\n"</span><span class="plain">, &amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[0]), </span><span class="identifier">actually_find</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">actually_find</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::tcp_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EverywhereMisapplied</span><span class="plain">), </span><span class="identifier">tck</span><span class="plain">,</span>
<span class="string">"that seems to say that a value - specifically, %4 - is everywhere. "</span>
<span class="string">"To Inform, everywhere means 'in every room', and only objects "</span>
<span class="string">"can be everywhere - in fact not even all of those, as it's a "</span>
<span class="string">"privilege reserved for backdrops. (For instance, 'The sky is a "</span>
<span class="string">"backdrop. The sky is everywhere.' is allowed.)"</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="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_10"></a><b>&#167;6.10. </b><code class="display">
&lt;<span class="cwebmacrodefn">A NOWHERE atom needs its term to be an object</span> <span class="cwebmacronumber">6.10</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">actually_find</span><span class="plain"> = </span><span class="functiontext">Calculus::Propositions::Checker::kind_of_term</span><span class="plain">(&amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[0]), &amp;</span><span class="identifier">vta</span><span class="plain">, </span><span class="identifier">tck</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">actually_find</span><span class="plain">, </span><span class="identifier">K_object</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">tck</span><span class="plain">-&gt;</span><span class="element">log_to_I6_text</span><span class="plain">)</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Term $0 is $u not an object\n"</span><span class="plain">, &amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[0]), </span><span class="identifier">actually_find</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">actually_find</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::tcp_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_NowhereMisapplied</span><span class="plain">), </span><span class="identifier">tck</span><span class="plain">,</span>
<span class="string">"that seems to say that a value - specifically, %4 - is nowhere. "</span>
<span class="string">"To Inform, nowhere means 'in no room', and only things can be "</span>
<span class="string">"nowhere. (For instance, 'Godot is nowhere.' is allowed - it means "</span>
<span class="string">"Godot exists, but is not initially part of the drama.)"</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="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_11"></a><b>&#167;6.11. </b>It seems to be true that the A-parser never generates propositions which
apply <code class="display"><span class="extract">HERE</span></code> incorrectly, but just in case:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">A HERE atom needs its term to be an object</span> <span class="cwebmacronumber">6.11</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">actually_find</span><span class="plain"> = </span><span class="functiontext">Calculus::Propositions::Checker::kind_of_term</span><span class="plain">(&amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[0]), &amp;</span><span class="identifier">vta</span><span class="plain">, </span><span class="identifier">tck</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">actually_find</span><span class="plain">, </span><span class="identifier">K_object</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">tck</span><span class="plain">-&gt;</span><span class="element">log_to_I6_text</span><span class="plain">)</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Term $0 is $u not an object\n"</span><span class="plain">, &amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[0]), </span><span class="identifier">actually_find</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">actually_find</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::tcp_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">tck</span><span class="plain">,</span>
<span class="string">"that seems to say that a value - specifically, %4 - is here. "</span>
<span class="string">"To Inform, here means 'in the room we're talking about', so only "</span>
<span class="string">"objects can be 'here'."</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="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_12"></a><b>&#167;6.12. </b>Not so much for the debugging log as for the internal test, in fact, which
prints the log to an I6 string. This is the type-checking report in the case
of success.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Show the variable assignment in the debugging log</span> <span class="cwebmacronumber">6.12</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">, </span><span class="identifier">var_states</span><span class="plain">[26], </span><span class="identifier">c</span><span class="plain">=0;</span>
<span class="functiontext">Calculus::Variables::determine_status</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">, </span><span class="identifier">var_states</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;26; </span><span class="identifier">j</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">var_states</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] != </span><span class="constant">UNUSED_VST</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%c%s - $u. "</span><span class="plain">, </span><span class="identifier">pcalc_vars</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">],</span>
<span class="plain">(</span><span class="identifier">var_states</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] == </span><span class="constant">FREE_VST</span><span class="plain">)?</span><span class="string">" (free)"</span><span class="plain">:</span><span class="string">""</span><span class="plain">,</span>
<span class="identifier">vta</span><span class="plain">.</span><span class="element">assigned_kinds</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]); </span><span class="identifier">c</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain">&gt;0) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. The kind of a term. </b>The following routine works out the kind of value stored in a term, something
which requires contextual information: unless we know the kind of value stored
in each variable, we cannot know the kind of value a general term represents,
which is why the routine is here and not in the Terms section.
</p>
<pre class="display">
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">Calculus::Propositions::Checker::kind_of_term</span><span class="plain">(</span><span class="reserved">pcalc_term</span><span class="plain"> *</span><span class="identifier">pt</span><span class="plain">, </span><span class="reserved">variable_type_assignment</span><span class="plain"> *</span><span class="identifier">vta</span><span class="plain">,</span>
<span class="reserved">tc_problem_kit</span><span class="plain"> *</span><span class="identifier">tck</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">Calculus::Propositions::Checker::kind_of_term_inner</span><span class="plain">(</span><span class="identifier">pt</span><span class="plain">, </span><span class="identifier">vta</span><span class="plain">, </span><span class="identifier">tck</span><span class="plain">);</span>
<span class="identifier">pt</span><span class="plain">-&gt;</span><span class="element">term_checked_as_kind</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">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">"No kind for term $0 = $T\n"</span><span class="plain">, </span><span class="identifier">pt</span><span class="plain">, </span><span class="identifier">pt</span><span class="plain">-&gt;</span><span class="element">constant</span><span class="plain">); </span><span class="identifier">tck</span><span class="plain">-&gt;</span><span class="element">flag_problem</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">K</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Propositions::Checker::kind_of_term is used in <a href="#SP6">&#167;6</a>, <a href="#SP6_5">&#167;6.5</a>, <a href="#SP6_8">&#167;6.8</a>, <a href="#SP6_9">&#167;6.9</a>, <a href="#SP6_10">&#167;6.10</a>, <a href="#SP6_11">&#167;6.11</a>, <a href="#SP8">&#167;8</a>, <a href="#SP10">&#167;10</a>, <a href="#SP11">&#167;11</a>, <a href="#SP11_2">&#167;11.2</a>.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>The case needing attention is a term in the form t = f_B(s). By recursion
we can know the kind of s, but we must check that f_B can validly be applied
to a value of that kind. If B is a binary predicate with domains R and S
(i.e., a subset of R* S) then we will either have f_B:R--&gt; S or vice
versa; so we have to check that s lies in R (or S, respectively).
</p>
<pre class="display">
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">Calculus::Propositions::Checker::kind_of_term_inner</span><span class="plain">(</span><span class="reserved">pcalc_term</span><span class="plain"> *</span><span class="identifier">pt</span><span class="plain">, </span><span class="reserved">variable_type_assignment</span><span class="plain"> *</span><span class="identifier">vta</span><span class="plain">,</span>
<span class="reserved">tc_problem_kit</span><span class="plain"> *</span><span class="identifier">tck</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pt</span><span class="plain">-&gt;</span><span class="element">constant</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">pt</span><span class="plain">-&gt;</span><span class="element">constant</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pt</span><span class="plain">-&gt;</span><span class="element">variable</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">vta</span><span class="plain">-&gt;</span><span class="element">assigned_kinds</span><span class="plain">[</span><span class="identifier">pt</span><span class="plain">-&gt;</span><span class="element">variable</span><span class="plain">];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pt</span><span class="plain">-&gt;</span><span class="element">function</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="identifier">pt</span><span class="plain">-&gt;</span><span class="element">function</span><span class="plain">-&gt;</span><span class="element">bp</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="functiontext">Calculus::Propositions::Checker::kind_of_term</span><span class="plain">(&amp;(</span><span class="identifier">pt</span><span class="plain">-&gt;</span><span class="element">function</span><span class="plain">-&gt;</span><span class="element">fn_of</span><span class="plain">), </span><span class="identifier">vta</span><span class="plain">, </span><span class="identifier">tck</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_from</span><span class="plain"> = </span><span class="functiontext">Calculus::Propositions::Checker::approximate_argument_kind</span><span class="plain">(</span><span class="identifier">bp</span><span class="plain">, </span><span class="identifier">pt</span><span class="plain">-&gt;</span><span class="element">function</span><span class="plain">-&gt;</span><span class="element">from_term</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_to</span><span class="plain"> = </span><span class="functiontext">Calculus::Propositions::Checker::approximate_argument_kind</span><span class="plain">(</span><span class="identifier">bp</span><span class="plain">, </span><span class="constant">1</span><span class="plain"> - </span><span class="identifier">pt</span><span class="plain">-&gt;</span><span class="element">function</span><span class="plain">-&gt;</span><span class="element">from_term</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">kind_from</span><span class="plain">) &amp;&amp; (</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_from</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">tck</span><span class="plain">-&gt;</span><span class="element">log_to_I6_text</span><span class="plain">)</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Term $0 applies function to $u not $u\n"</span><span class="plain">, </span><span class="identifier">pt</span><span class="plain">, </span><span class="identifier">kind_found</span><span class="plain">, </span><span class="identifier">kind_from</span><span class="plain">);</span>
<span class="functiontext">Calculus::Propositions::Checker::issue_bp_typecheck_error</span><span class="plain">(</span><span class="identifier">bp</span><span class="plain">, </span><span class="identifier">kind_found</span><span class="plain">, </span><span class="identifier">kind_to</span><span class="plain">, </span><span class="identifier">tck</span><span class="plain">);</span>
<span class="identifier">kind_found</span><span class="plain"> = </span><span class="identifier">kind_from</span><span class="plain">; </span><span class="comment">the better to recover</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kind_to</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">kind_to</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">kind_found</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Propositions::Checker::kind_of_term_inner is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>Some relations specify a kind for their terms, others do not. When they do
specify a kind of object, we usually want to be forgiving about nuances of
the kind of object &mdash; for our purposes here, any object will do. (Run-time
type checking takes care of those nuances better.)
</p>
<p class="inwebparagraph">The following gives the kind of a given term. It should be used only where
the BP is one constraining its terms, such as when it provides a f_B
function.
</p>
<pre class="display">
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">Calculus::Propositions::Checker::approximate_argument_kind</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="reserved">int</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">BinaryPredicates::term_kind</span><span class="plain">(</span><span class="identifier">bp</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="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</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">Kinds::weaken</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Propositions::Checker::approximate_argument_kind is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. Type-checking predicates. </b>We take unary predicates first, then binary. Unary predicates are just
adjectives, and all of the work for that has already been done, so we need
only produce a problem message when the worst happens.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Calculus::Propositions::Checker::type_check_unary_predicate</span><span class="plain">(</span><span class="reserved">pcalc_prop</span><span class="plain"> *</span><span class="identifier">pl</span><span class="plain">, </span><span class="reserved">variable_type_assignment</span><span class="plain"> *</span><span class="identifier">vta</span><span class="plain">,</span>
<span class="reserved">tc_problem_kit</span><span class="plain"> *</span><span class="identifier">tck</span><span class="plain">) {</span>
<span class="identifier">adjective_usage</span><span class="plain"> *</span><span class="identifier">tr</span><span class="plain"> = </span><span class="identifier">RETRIEVE_POINTER_adjective_usage</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">predicate</span><span class="plain">);</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="identifier">tr</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">Calculus::Propositions::Checker::kind_of_term</span><span class="plain">(&amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[0]), </span><span class="identifier">vta</span><span class="plain">, </span><span class="identifier">tck</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">aph</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Adjectives::Meanings::applicable_to</span><span class="plain">(</span><span class="identifier">aph</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Adjectives::get_text</span><span class="plain">(</span><span class="identifier">aph</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">tck</span><span class="plain">-&gt;</span><span class="element">log_to_I6_text</span><span class="plain">)</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Adjective '%W' undefined on $u\n"</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">Problems::quote_wording</span><span class="plain">(4, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(5, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::tcp_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_AdjectiveMisapplied</span><span class="plain">), </span><span class="identifier">tck</span><span class="plain">,</span>
<span class="string">"that seems to involve applying the adjective '%4' to %5 - and I "</span>
<span class="string">"have no definition of it which would apply in that situation. "</span>
<span class="string">"(Try looking it up in the Lexicon part of the Phrasebook index "</span>
<span class="string">"to see what definition(s) '%4' has.)"</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">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 Calculus::Propositions::Checker::type_check_unary_predicate is used in <a href="#SP6_6">&#167;6.6</a>, <a href="#SP6_7">&#167;6.7</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>Binary predicates (BPs) are both easier and harder. Easier because they
have only one definition at a time (unlike, say, the adjective "empty"),
harder because the work hasn't already been done and because some BPs &mdash;
like "is" &mdash; are polymorphic. Here goes:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Calculus::Propositions::Checker::type_check_binary_predicate</span><span class="plain">(</span><span class="reserved">pcalc_prop</span><span class="plain"> *</span><span class="identifier">pl</span><span class="plain">, </span><span class="reserved">variable_type_assignment</span><span class="plain"> *</span><span class="identifier">vta</span><span class="plain">,</span>
<span class="reserved">tc_problem_kit</span><span class="plain"> *</span><span class="identifier">tck</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="identifier">RETRIEVE_POINTER_binary_predicate</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">predicate</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kinds_of_terms</span><span class="plain">[2], *</span><span class="identifier">kinds_required</span><span class="plain">[2];</span>
&lt;<span class="cwebmacro">Work out what kinds we find</span> <span class="cwebmacronumber">11.2</span>&gt;<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">R_universal</span><span class="plain">) </span>&lt;<span class="cwebmacro">Adapt to the universal relation</span> <span class="cwebmacronumber">11.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Work out what kinds we should have found</span> <span class="cwebmacronumber">11.1</span>&gt;<span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">result</span><span class="plain"> = </span><span class="functiontext">BinaryPredicates::typecheck</span><span class="plain">(</span><span class="identifier">bp</span><span class="plain">, </span><span class="identifier">kinds_of_terms</span><span class="plain">, </span><span class="identifier">kinds_required</span><span class="plain">, </span><span class="identifier">tck</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">result</span><span class="plain"> == </span><span class="constant">NEVER_MATCH_SAYING_WHY_NOT</span><span class="plain">) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kinds_dereferencing_properties</span><span class="plain">[2];</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"0 = $u. 1 = $u\n"</span><span class="plain">, </span><span class="identifier">kinds_of_terms</span><span class="plain">[0], </span><span class="identifier">kinds_of_terms</span><span class="plain">[1]);</span>
<span class="identifier">kinds_dereferencing_properties</span><span class="plain">[0] = </span><span class="identifier">Kinds::dereference_properties</span><span class="plain">(</span><span class="identifier">kinds_of_terms</span><span class="plain">[0]);</span>
<span class="identifier">kinds_dereferencing_properties</span><span class="plain">[1] = </span><span class="identifier">kinds_of_terms</span><span class="plain">[1];</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">r2</span><span class="plain"> = </span><span class="functiontext">BinaryPredicates::typecheck</span><span class="plain">(</span><span class="identifier">bp</span><span class="plain">, </span><span class="identifier">kinds_dereferencing_properties</span><span class="plain">, </span><span class="identifier">kinds_required</span><span class="plain">, </span><span class="identifier">tck</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">r2</span><span class="plain"> == </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">) || (</span><span class="identifier">r2</span><span class="plain"> == </span><span class="identifier">SOMETIMES_MATCH</span><span class="plain">)) {</span>
<span class="identifier">result</span><span class="plain"> = </span><span class="identifier">r2</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">result</span><span class="plain"> != </span><span class="constant">DECLINE_TO_MATCH</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">result</span><span class="plain"> == </span><span class="constant">NEVER_MATCH_SAYING_WHY_NOT</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tck</span><span class="plain">-&gt;</span><span class="element">issue_error</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="reserved">if</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[0].</span><span class="element">function</span><span class="plain">)</span>
<span class="functiontext">Calculus::Propositions::Checker::issue_bp_typecheck_error</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[0].</span><span class="element">function</span><span class="plain">-&gt;</span><span class="element">bp</span><span class="plain">,</span>
<span class="functiontext">Calculus::Propositions::Checker::kind_of_term</span><span class="plain">(&amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[0].</span><span class="element">function</span><span class="plain">-&gt;</span><span class="element">fn_of</span><span class="plain">), </span><span class="identifier">vta</span><span class="plain">, </span><span class="identifier">tck</span><span class="plain">),</span>
<span class="identifier">kinds_of_terms</span><span class="plain">[1], </span><span class="identifier">tck</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">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[1].</span><span class="element">function</span><span class="plain">)</span>
<span class="functiontext">Calculus::Propositions::Checker::issue_bp_typecheck_error</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[1].</span><span class="element">function</span><span class="plain">-&gt;</span><span class="element">bp</span><span class="plain">,</span>
<span class="identifier">kinds_of_terms</span><span class="plain">[0],</span>
<span class="functiontext">Calculus::Propositions::Checker::kind_of_term</span><span class="plain">(&amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[1].</span><span class="element">function</span><span class="plain">-&gt;</span><span class="element">fn_of</span><span class="plain">), </span><span class="identifier">vta</span><span class="plain">, </span><span class="identifier">tck</span><span class="plain">),</span>
<span class="identifier">tck</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">"($u, $u) failed in $2\n"</span><span class="plain">, </span><span class="identifier">kinds_of_terms</span><span class="plain">[0], </span><span class="identifier">kinds_of_terms</span><span class="plain">[1], </span><span class="identifier">bp</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">kinds_of_terms</span><span class="plain">[0]);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(5, </span><span class="identifier">kinds_of_terms</span><span class="plain">[1]);</span>
<span class="functiontext">Problems::Issue::tcp_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ComparisonFailed</span><span class="plain">), </span><span class="identifier">tck</span><span class="plain">,</span>
<span class="string">"that would mean comparing two kinds of value which cannot mix - "</span>
<span class="string">"%4 and %5 - so this must be incorrect."</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">return</span><span class="plain"> </span><span class="identifier">result</span><span class="plain">;</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Apply default rule applying to most binary predicates</span> <span class="cwebmacronumber">11.4</span>&gt;<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 Calculus::Propositions::Checker::type_check_binary_predicate is used in <a href="#SP6_7">&#167;6.7</a>.</p>
<p class="inwebparagraph"><a id="SP11_1"></a><b>&#167;11.1. </b>Once again we treat any kind of object as just "object", but we do take
note that some BPs &mdash; like "is" &mdash; specify no kinds at all, and so
produce a <code class="display"><span class="extract">kinds_required</span></code> which is <code class="display"><span class="extract">NULL</span></code>.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Work out what kinds we should have found</span> <span class="cwebmacronumber">11.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;2; </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="identifier">Kinds::weaken</span><span class="plain">(</span><span class="functiontext">BinaryPredicates::term_kind</span><span class="plain">(</span><span class="identifier">bp</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="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">kinds_required</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>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11_2"></a><b>&#167;11.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Work out what kinds we find</span> <span class="cwebmacronumber">11.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;2; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="identifier">kinds_of_terms</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] =</span>
<span class="functiontext">Calculus::Propositions::Checker::kind_of_term</span><span class="plain">(&amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]), </span><span class="identifier">vta</span><span class="plain">, </span><span class="identifier">tck</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11_3"></a><b>&#167;11.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Adapt to the universal relation</span> <span class="cwebmacronumber">11.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">kinds_of_terms</span><span class="plain">[0]) != </span><span class="identifier">CON_relation</span><span class="plain">) {</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">kinds_of_terms</span><span class="plain">[0]);</span>
<span class="functiontext">Problems::Issue::tcp_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_BadUniversal1</span><span class="plain">), </span><span class="identifier">tck</span><span class="plain">,</span>
<span class="string">"that asks whether something relates something, and in Inform 'to relate' "</span>
<span class="string">"means that a particular relation applies between two things. Here, though, "</span>
<span class="string">"we have %4 rather than the name of a relation."</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::get_construct</span><span class="plain">(</span><span class="identifier">kinds_of_terms</span><span class="plain">[1]) != </span><span class="identifier">CON_combination</span><span class="plain">) {</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">kinds_of_terms</span><span class="plain">[1]);</span>
<span class="functiontext">Problems::Issue::tcp_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">tck</span><span class="plain">,</span>
<span class="string">"that asks whether something relates something, and in Inform 'to relate' "</span>
<span class="string">"means that a particular relation applies between two things. Here, though, "</span>
<span class="string">"we have %4 rather than the combination of the two things."</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">parse_node</span><span class="plain"> *</span><span class="identifier">left</span><span class="plain"> = </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">terms</span><span class="plain">[0].</span><span class="element">constant</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">left</span><span class="plain">, </span><span class="constant">CONSTANT_NT</span><span class="plain">)) {</span>
<span class="identifier">bp</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_binary_predicate</span><span class="plain">(</span><span class="identifier">left</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">cleft</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">cright</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">Kinds::binary_construction_material</span><span class="plain">(</span><span class="identifier">kinds_of_terms</span><span class="plain">[1], &amp;</span><span class="identifier">cleft</span><span class="plain">, &amp;</span><span class="identifier">cright</span><span class="plain">);</span>
<span class="identifier">kinds_of_terms</span><span class="plain">[0] = </span><span class="identifier">cleft</span><span class="plain">;</span>
<span class="identifier">kinds_of_terms</span><span class="plain">[1] = </span><span class="identifier">cright</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">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11_4"></a><b>&#167;11.4. </b>The default rule is straightforward: the kinds found have to match the kinds
required.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Apply default rule applying to most binary predicates</span> <span class="cwebmacronumber">11.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;2; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kinds_required</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">kinds_of_terms</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">kinds_required</span><span class="plain">[</span><span class="identifier">i</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">tck</span><span class="plain">-&gt;</span><span class="element">log_to_I6_text</span><span class="plain">)</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Term %d is $u not $u\n"</span><span class="plain">,</span>
<span class="identifier">i</span><span class="plain">, </span><span class="identifier">kinds_of_terms</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">kinds_required</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="functiontext">Calculus::Propositions::Checker::issue_bp_typecheck_error</span><span class="plain">(</span><span class="identifier">bp</span><span class="plain">,</span>
<span class="identifier">kinds_of_terms</span><span class="plain">[0], </span><span class="identifier">kinds_of_terms</span><span class="plain">[1], </span><span class="identifier">tck</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">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. Two problem messages needed more than once. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Calculus::Propositions::Checker::issue_bp_typecheck_error</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="identifier">kind</span><span class="plain"> *</span><span class="identifier">t0</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">t1</span><span class="plain">, </span><span class="reserved">tc_problem_kit</span><span class="plain"> *</span><span class="identifier">tck</span><span class="plain">) {</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">t0</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(5, </span><span class="identifier">t1</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_relation</span><span class="plain">(6, </span><span class="identifier">bp</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::tcp_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TypeCheckBP2</span><span class="plain">), </span><span class="identifier">tck</span><span class="plain">,</span>
<span class="string">"that would mean applying %6 to kinds of value which do not "</span>
<span class="string">"fit - %4 and %5 - so this must be incorrect."</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Calculus::Propositions::Checker::issue_kind_typecheck_error</span><span class="plain">(</span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">actually_find</span><span class="plain">,</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">need_to_find</span><span class="plain">, </span><span class="reserved">tc_problem_kit</span><span class="plain"> *</span><span class="identifier">tck</span><span class="plain">, </span><span class="reserved">pcalc_prop</span><span class="plain"> *</span><span class="identifier">ka</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="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ka</span><span class="plain">) &amp;&amp; (</span><span class="identifier">GENERAL_POINTER_IS_NULL</span><span class="plain">(</span><span class="identifier">ka</span><span class="plain">-&gt;</span><span class="element">predicate</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">))</span>
<span class="identifier">bp</span><span class="plain"> = </span><span class="identifier">RETRIEVE_POINTER_binary_predicate</span><span class="plain">(</span><span class="identifier">ka</span><span class="plain">-&gt;</span><span class="element">predicate</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">actually_find</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(5, </span><span class="identifier">need_to_find</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="functiontext">Problems::quote_relation</span><span class="plain">(6, </span><span class="identifier">bp</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::tcp_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TypeCheckBP2a</span><span class="plain">), </span><span class="identifier">tck</span><span class="plain">,</span>
<span class="string">"that doesn't work because you use %6 with %4 instead of %5."</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="functiontext">Problems::Issue::tcp_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TypeCheckKind</span><span class="plain">), </span><span class="identifier">tck</span><span class="plain">,</span>
<span class="string">"%4 cannot be %5, so this must be incorrect."</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Propositions::Checker::issue_bp_typecheck_error is used in <a href="#SP8">&#167;8</a>, <a href="#SP11">&#167;11</a>, <a href="#SP11_4">&#167;11.4</a>, 15/cr (<a href="15-cr.html#SP5">&#167;5</a>).</p>
<p class="endnote">The function Calculus::Propositions::Checker::issue_kind_typecheck_error is used in <a href="#SP6_2">&#167;6.2</a>, <a href="#SP6_5">&#167;6.5</a>.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="11-sm.html">Back to 'Simplifications'</a></li><li><i>(This section ends Chapter 11: Predicate Calculus.)</i></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>