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

867 lines
109 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>15/epv</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<!--Weave of '16/is' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">core</a></li><li><a href="index.html#16">Chapter 16: Inference and Model</a></li><li><b>Inference Subjects</b></li></ul><p class="purpose">The different data structures for elements of the model world are all unified by a single concept, the inference subject, about which facts can be known.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP8">&#167;8. The fundamentals</a></li><li><a href="#SP9">&#167;9. Creation</a></li><li><a href="#SP12">&#167;12. Aliasing</a></li><li><a href="#SP13">&#167;13. Breadth</a></li><li><a href="#SP18">&#167;18. Back conversions</a></li><li><a href="#SP22">&#167;22. Logging</a></li><li><a href="#SP24">&#167;24. Methods</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>"Creating a program often means that you have to create a small
universe" (Donald Knuth).
</p>
<p class="inwebparagraph">Inform's model world is the collection of objects and values which
contingently rather than necessarily exist, together with their properties
and relations. A number such as 267 exists of necessity &mdash; there would be
such a number whatever the source text had said, even if (as it turned out)
the compiled code never actually used it. But a room such as "The Great
Hall of Memphis", or a named value such as "aquamarine", need not exist.
Those are the stuff of the model.
</p>
<p class="inwebparagraph">As we have seen, the A-parser reduces assertion sentences in the source text
into logical propositions; these are then asserted in turn, reducing them
to a series of creations (such as that a ball exists) and a series of
inferences (such as that the ball is red). Inferences are elementary facts
about properties and relations, believed with different levels of certainty.
</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>An "inference subject" is anything about which an inference can be drawn.
These subjects form a hierarchy. We say that I inherits from J if a fact about I
is necessarily also a fact about J, unless directly contradicted by specific
information about J. For example,
</p>
<blockquote>
<p>The plastic bag is a container. A container is usually opaque. The bag is transparent.</p>
</blockquote>
<p class="inwebparagraph">The inference subject for the bag inherits from that for the container, so
without that final sentence, the bag would have been opaque.
</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>This is in effect a class with subclasses, but since we are using plain C
we indicate that with an enumeration of constants:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">FUND_SUB</span><span class="plain"> 1 </span> <span class="comment">one of a few fixed and fundamental subjects (see below)</span>
<span class="definitionkeyword">define</span> <span class="constant">KIND_SUB</span><span class="plain"> 2 </span> <span class="comment">a kind (number, thing, etc.)</span>
<span class="definitionkeyword">define</span> <span class="constant">INST_SUB</span><span class="plain"> 3 </span> <span class="comment">an instance (specific objects, scenes, etc.)</span>
<span class="definitionkeyword">define</span> <span class="constant">VARI_SUB</span><span class="plain"> 4 </span> <span class="comment">a non-local variable</span>
<span class="definitionkeyword">define</span> <span class="constant">RELN_SUB</span><span class="plain"> 5 </span> <span class="comment">a binary predicate, i.e., a relation</span>
<span class="definitionkeyword">define</span> <span class="constant">MAX_SUB</span><span class="plain"> 5 </span> <span class="comment">must be the largest of the values above</span>
</pre>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>Technically the hierarchy of inference subjects is a spaghetti stack, not a
tree: that is, all of the links run upwards to a common root (<code class="display"><span class="extract">model_world</span></code>).
There is no direct way to access the links downwards from any node &mdash; in other
words, we often want to know what a given subject S inherits from, but we never
ask what other subjects inherit from S.
</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">inference_subject</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">kind_of_infs</span><span class="plain">; </span> <span class="comment">one of the <code class="display"><span class="extract">*_SUB</span></code> constants above</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">general_pointer</span><span class="plain"> </span><span class="identifier">represents</span><span class="plain">; </span> <span class="comment">the individual instance, kind, etc. in question</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">infs_created_at</span><span class="plain">; </span> <span class="comment">which sentence created this</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">inf_list</span><span class="plain">; </span> <span class="comment">contingently true: inferences drawn about this subject</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">implication</span><span class="plain"> *</span><span class="identifier">imp_list</span><span class="plain">; </span> <span class="comment">necessarily true: implications applying to this</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">default_certainty</span><span class="plain">; </span> <span class="comment">by default, how certain are inferences about this?</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">property_permission</span><span class="plain"> *</span><span class="identifier">permissions_list</span><span class="plain">; </span> <span class="comment">what properties this can have, if any</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">assemblies_data</span><span class="plain"> </span><span class="identifier">assemblies</span><span class="plain">; </span> <span class="comment">what generalisations have been made about this?</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">broader_than</span><span class="plain">; </span> <span class="comment">see below</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">infs_name_in_log</span><span class="plain">; </span> <span class="comment">solely to make the debugging log more legible</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">nonlocal_variable</span><span class="plain"> *</span><span class="identifier">alias_variable</span><span class="plain">; </span> <span class="comment">alias to this variable, like "yourself" to "player"</span>
<span class="reserved">void</span><span class="plain"> *</span><span class="identifier">plugin_subj</span><span class="plain">[</span><span class="constant">MAX_PLUGINS</span><span class="plain">];</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">inference_subject</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure inference_subject is private to this section.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>Recall that plugins are pieces of Inform which provide specialist additions
to the core language; to do this, they often need to attach further data to
</p>
<ul class="items"><li>(core) Inform's existing data structures. Once again, inference subjects provide
a convenient umbrella for things we're interested in; so we handle this by
allowing plugins to attach (suitably allocated) data structures to the ominous
<code class="display"><span class="extract">void *</span></code> slots in the structure above.
</li></ul>
<p class="inwebparagraph">It's convenient to hide all of this by accessing the extra fields with the
macros below. Thus <code class="display"><span class="extract">PF_S(balloons, gas)</span></code> is the lvalue (and rvalue) for
the <code class="display"><span class="extract">gas</span></code> field added to the inference structure by <code class="display"><span class="extract">balloons_plugin</span></code>.
The variation <code class="display"><span class="extract">PF_I</span></code> is a shorthand to access the structure corresponding
to a given instance &mdash; that's actually what we want, most of the time,
since a lot of the plugins are interested more in IF concepts like rooms,
containers and people than in anything else, and all of those objects
are instances.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">PF_S</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">)</span>
<span class="plain">((</span><span class="identifier">name</span><span class="plain">##</span><span class="identifier">_data</span><span class="plain"> *) </span><span class="identifier">S</span><span class="plain">-</span><span class="element">&gt;plugin_subj</span><span class="plain">[</span><span class="identifier">name</span><span class="plain">##</span><span class="identifier">_plugin</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">])</span>
<span class="definitionkeyword">define</span> <span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">I</span><span class="plain">)</span>
<span class="plain">((</span><span class="identifier">name</span><span class="plain">##</span><span class="identifier">_data</span><span class="plain"> *) (</span><span class="functiontext">Instances::as_subject</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">))-</span><span class="element">&gt;plugin_subj</span><span class="plain">[</span><span class="identifier">name</span><span class="plain">##</span><span class="identifier">_plugin</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">])</span>
<span class="definitionkeyword">define</span> <span class="identifier">CREATE_PF_DATA</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">creator</span><span class="plain">)</span>
<span class="plain">(</span><span class="identifier">S</span><span class="plain">)-</span><span class="element">&gt;plugin_subj</span><span class="plain">[</span><span class="identifier">name</span><span class="plain">##</span><span class="identifier">_plugin</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">] = (</span><span class="reserved">void</span><span class="plain"> *) (</span><span class="identifier">creator</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">));</span>
</pre>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>The top of the inference hierarchy contains a number of "fundamental" subjects.
Thus we have:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">model_world</span>
<span class="plain"> nonlocal_variables</span>
<span class="plain"> ...all individual globals</span>
<span class="plain"> global_constants</span>
<span class="plain"> ...all kinds, including:</span>
<span class="plain"> K_object</span>
<span class="plain"> K_thing</span>
<span class="plain"> K_container</span>
<span class="plain"> ...</span>
<span class="plain"> K_room</span>
<span class="plain"> ...</span>
</pre>
<p class="inwebparagraph">(Note that objects appear within the hierarchy of values, rather than alongside
it, as in the class hierarchies of languages like Scala.)
</p>
<p class="inwebparagraph">For instance, by giving <code class="display"><span class="extract">nonlocal_variables</span></code> permission to have the "initial
value" property, we immediately grant the same to every global variable, by
inheritance.
</p>
<p class="inwebparagraph">Inheritance forms a directed acyclic graph with <code class="display"><span class="extract">model_world</span></code> as the root.
</p>
<pre class="display">
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">model_world</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">nonlocal_variables</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">global_constants</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">relations</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. The fundamentals. </b>At the start of Inform's run, the subject tree consists only of the
following.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::begin</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">model_world</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::new_fundamental</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">, </span><span class="string">"model-world"</span><span class="plain">);</span>
<span class="identifier">nonlocal_variables</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::new_fundamental</span><span class="plain">(</span><span class="identifier">model_world</span><span class="plain">, </span><span class="string">"global-variables"</span><span class="plain">);</span>
<span class="identifier">global_constants</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::new_fundamental</span><span class="plain">(</span><span class="identifier">model_world</span><span class="plain">, </span><span class="string">"global-constants"</span><span class="plain">);</span>
<span class="identifier">relations</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::new_fundamental</span><span class="plain">(</span><span class="identifier">model_world</span><span class="plain">, </span><span class="string">"relations"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::new_fundamental</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">lname</span><span class="plain">) {</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain">);</span>
<span class="functiontext">InferenceSubjects::infs_initialise</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">NULL_GENERAL_POINTER</span><span class="plain">, </span><span class="constant">FUND_SUB</span><span class="plain">, </span><span class="identifier">LIKELY_CE</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">lname</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">infs</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::begin is used in 1/mr (<a href="1-mr.html#SP4_7">&#167;4.7</a>).</p>
<p class="endnote">The function InferenceSubjects::new_fundamental appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. Creation. </b>Other inference subjects are added during the run, thus:
</p>
<pre class="display">
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::new</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">KOI</span><span class="plain">,</span>
<span class="identifier">general_pointer</span><span class="plain"> </span><span class="identifier">gp</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">cert</span><span class="plain">) {</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain">);</span>
<span class="functiontext">InferenceSubjects::infs_initialise</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">gp</span><span class="plain">, </span><span class="identifier">KOI</span><span class="plain">, </span><span class="identifier">cert</span><span class="plain">, </span><span class="identifier">from</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">infs</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::new is used in 5/ins (<a href="5-ins.html#SP6_2">&#167;6.2</a>), 5/nv (<a href="5-nv.html#SP7_3">&#167;7.3</a>), 6/bp (<a href="6-bp.html#SP30">&#167;30</a>), 13/kak (<a href="13-kak.html#SP1">&#167;1</a>).</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>Either means of creation uses the following:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_roots</span><span class="plain"> = 0;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::infs_initialise</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">,</span>
<span class="identifier">general_pointer</span><span class="plain"> </span><span class="identifier">gp</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">KOI</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">cert</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">lname</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">from</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) &amp;&amp; (++</span><span class="identifier">no_roots</span><span class="plain"> &gt; 1)) {</span>
<span class="functiontext">InferenceSubjects::log_infs_hierarchy</span><span class="plain">();</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"subject tree now disconnected"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain"> == </span><span class="identifier">infs</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"made sub-subject of itself"</span><span class="plain">);</span>
<span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;infs_created_at</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;represents</span><span class="plain"> = </span><span class="identifier">gp</span><span class="plain">;</span>
<span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain"> = </span><span class="identifier">KOI</span><span class="plain">;</span>
<span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;inf_list</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;imp_list</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;broader_than</span><span class="plain"> = </span><span class="identifier">from</span><span class="plain">;</span>
<span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;default_certainty</span><span class="plain"> = </span><span class="identifier">cert</span><span class="plain">;</span>
<span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;permissions_list</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;infs_name_in_log</span><span class="plain"> = </span><span class="identifier">lname</span><span class="plain">;</span>
<span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;alias_variable</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="functiontext">Assertions::Assemblies::initialise_assemblies_data</span><span class="plain">(&amp;(</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;assemblies</span><span class="plain">));</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">MAX_PLUGINS</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;plugin_subj</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="functiontext">Plugins::Call::new_subject_notify</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::infs_initialise is used in <a href="#SP8">&#167;8</a>, <a href="#SP9">&#167;9</a>, <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>Renewal is needed to solve a timing problem early in Inform's run, since
subjects for spatial kinds like "room" are needed before the kinds themselves
can be made. Abusing this routine could clearly violate the rule that the
subject tree must remain a connected DAG, so we don't abuse it.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::renew</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">,</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">KOI</span><span class="plain">, </span><span class="identifier">general_pointer</span><span class="plain"> </span><span class="identifier">gp</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">cert</span><span class="plain">) {</span>
<span class="functiontext">InferenceSubjects::infs_initialise</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">gp</span><span class="plain">, </span><span class="identifier">KOI</span><span class="plain">, </span><span class="identifier">cert</span><span class="plain">, </span><span class="identifier">from</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 InferenceSubjects::renew appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. Aliasing. </b>This is explained in the "The Player" plugin, which is the only place where
it's needed at present.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::alias_to_nonlocal_variable</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">, </span><span class="reserved">nonlocal_variable</span><span class="plain"> *</span><span class="identifier">q</span><span class="plain">) {</span>
<span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;alias_variable</span><span class="plain"> = </span><span class="identifier">q</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::aliased_but_diverted</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;alias_variable</span><span class="plain">) {</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">vs</span><span class="plain"> =</span>
<span class="functiontext">Instances::as_subject</span><span class="plain">(</span>
<span class="functiontext">Rvalues::to_object_instance</span><span class="plain">(</span>
<span class="functiontext">NonlocalVariables::get_initial_value</span><span class="plain">(</span>
<span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;alias_variable</span><span class="plain">)));</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">vs</span><span class="plain">) &amp;&amp; (</span><span class="identifier">vs</span><span class="plain"> != </span><span class="identifier">infs</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::alias_to_nonlocal_variable appears nowhere else.</p>
<p class="endnote">The function InferenceSubjects::aliased_but_diverted is used in 16/ic (<a href="16-ic.html#SP8">&#167;8</a>).</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. Breadth. </b>Some subjects are broad, covering many things, and others narrow &mdash; perhaps
used to specify facts about only a single person or value.
</p>
<p class="inwebparagraph">Either two different subjects are disjoint or one strictly contains the other.
This makes testing for containment simple:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::is_within</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">smaller</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">larger</span><span class="plain">) {</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">smaller</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">smaller</span><span class="plain"> == </span><span class="identifier">larger</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">smaller</span><span class="plain"> = </span><span class="identifier">smaller</span><span class="plain">-</span><span class="element">&gt;broader_than</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::is_strictly_within</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">subj</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">larger</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">subj</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::is_within</span><span class="plain">(</span><span class="identifier">subj</span><span class="plain">-</span><span class="element">&gt;broader_than</span><span class="plain">, </span><span class="identifier">larger</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::is_within is used in <a href="#SP15">&#167;15</a>, 9/ass (<a href="9-ass.html#SP11">&#167;11</a>), 13/kak (<a href="13-kak.html#SP6">&#167;6</a>), 15/ia (<a href="15-ia.html#SP1">&#167;1</a>).</p>
<p class="endnote">The function InferenceSubjects::is_strictly_within is used in 4/am (<a href="4-am.html#SP26">&#167;26</a>), 6/rlt (<a href="6-rlt.html#SP20_4">&#167;20.4</a>), 13/kak (<a href="13-kak.html#SP6">&#167;6</a>).</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. </b>Where possible, we use the above tests; where we need to perform other
operations scaling the subject tree, we use the following:
</p>
<pre class="display">
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::narrowest_broader_subject</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">narrow</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">narrow</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">narrow</span><span class="plain">-</span><span class="element">&gt;broader_than</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::narrowest_broader_subject is used in 4/am (<a href="4-am.html#SP21">&#167;21</a>), 5/ins (<a href="5-ins.html#SP18">&#167;18</a>), 9/pk (<a href="9-pk.html#SP3_1">&#167;3.1</a>), 9/ass (<a href="9-ass.html#SP12">&#167;12</a>), 9/imp (<a href="9-imp.html#SP6">&#167;6</a>, <a href="9-imp.html#SP7">&#167;7</a>), 12/ap (<a href="12-ap.html#SP9_10">&#167;9.10</a>), 13/kak (<a href="13-kak.html#SP5">&#167;5</a>, <a href="13-kak.html#SP6">&#167;6</a>), 15/pr (<a href="15-pr.html#SP25">&#167;25</a>), 15/pov (<a href="15-pov.html#SP4">&#167;4</a>), 15/epv (<a href="15-epv.html#SP1">&#167;1</a>, <a href="15-epv.html#SP1_1_4">&#167;1.1.4</a>), 16/pp (<a href="16-pp.html#SP8">&#167;8</a>), 16/in (<a href="16-in.html#SP14">&#167;14</a>, <a href="16-in.html#SP16">&#167;16</a>), 16/cmw (<a href="16-cmw.html#SP1_2_2_1">&#167;1.2.2.1</a>), 16/ic (<a href="16-ic.html#SP12_3">&#167;12.3</a>, <a href="16-ic.html#SP14">&#167;14</a>).</p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. </b>The containment hierarchy is a fluid one, but subjects may only be demoted.
This means that any information derived from a subject's position relative to
other subjects, before the change, continues to be valid. If S⊆ T
before, then this remains true afterwards.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::falls_within</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">narrow</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">broad</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">InferenceSubjects::is_within</span><span class="plain">(</span><span class="identifier">broad</span><span class="plain">, </span><span class="identifier">narrow</span><span class="plain">-</span><span class="element">&gt;broader_than</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">"subject breadth change leads to inconsistency"</span><span class="plain">);</span>
<span class="identifier">narrow</span><span class="plain">-</span><span class="element">&gt;broader_than</span><span class="plain"> = </span><span class="identifier">broad</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::falls_within is used in 5/ins (<a href="5-ins.html#SP19">&#167;19</a>), 13/kak (<a href="13-kak.html#SP6">&#167;6</a>).</p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. </b>Now access to the knowledge we possess about subjects, all of which is
read and written from specialist sections of Inform rather than here.
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::where_created</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"null INFS"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;infs_created_at</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::get_default_certainty</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;default_certainty</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">assemblies_data</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::get_assemblies_data</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to fetch assembly data for null subject"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> &amp;(</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;assemblies</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::get_inferences</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain">)?(</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;inf_list</span><span class="plain">):</span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::set_inferences</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">, </span><span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">inf</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"null INFS"</span><span class="plain">);</span>
<span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;inf_list</span><span class="plain"> = </span><span class="identifier">inf</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">implication</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::get_implications</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;imp_list</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::set_implications</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">, </span><span class="reserved">implication</span><span class="plain"> *</span><span class="identifier">imp</span><span class="plain">) {</span>
<span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;imp_list</span><span class="plain"> = </span><span class="identifier">imp</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">property_permission</span><span class="plain"> **</span><span class="functiontext">InferenceSubjects::get_permissions</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> &amp;(</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;permissions_list</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::where_created is used in 9/ma (<a href="9-ma.html#SP3_3_8">&#167;3.3.8</a>, <a href="9-ma.html#SP3_3_8_1">&#167;3.3.8.1</a>, <a href="9-ma.html#SP6">&#167;6</a>).</p>
<p class="endnote">The function InferenceSubjects::get_default_certainty is used in 16/in (<a href="16-in.html#SP8">&#167;8</a>, <a href="16-in.html#SP20_3">&#167;20.3</a>).</p>
<p class="endnote">The function InferenceSubjects::get_assemblies_data is used in 9/ass (<a href="9-ass.html#SP7">&#167;7</a>, <a href="9-ass.html#SP8">&#167;8</a>, <a href="9-ass.html#SP9_4">&#167;9.4</a>, <a href="9-ass.html#SP12">&#167;12</a>, <a href="9-ass.html#SP12_1">&#167;12.1</a>, <a href="9-ass.html#SP12_1_1">&#167;12.1.1</a>).</p>
<p class="endnote">The function InferenceSubjects::get_inferences is used in <a href="#SP22">&#167;22</a>, 16/in (<a href="16-in.html#SP13">&#167;13</a>, <a href="16-in.html#SP20">&#167;20</a>).</p>
<p class="endnote">The function InferenceSubjects::set_inferences is used in 16/in (<a href="16-in.html#SP20_1">&#167;20.1</a>, <a href="16-in.html#SP20_3_1">&#167;20.3.1</a>, <a href="16-in.html#SP20_3_4">&#167;20.3.4</a>).</p>
<p class="endnote">The function InferenceSubjects::get_implications is used in 9/imp (<a href="9-imp.html#SP4_2">&#167;4.2</a>, <a href="9-imp.html#SP7">&#167;7</a>).</p>
<p class="endnote">The function InferenceSubjects::set_implications is used in 9/imp (<a href="9-imp.html#SP4_2">&#167;4.2</a>).</p>
<p class="endnote">The function InferenceSubjects::get_permissions is used in 16/pp (<a href="16-pp.html#SP7">&#167;7</a>, <a href="16-pp.html#SP9_2">&#167;9.2</a>).</p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. </b>Forward conversions.
Suppose we have a constant value, or more generally, a specification. Does this
correspond to a subject, and if so, which one?
</p>
<pre class="display">
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::from_specification</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="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Specifications::is_kind_like</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">)) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="identifier">infs</span><span class="plain"> = </span><span class="functiontext">Kinds::Knowledge::as_subject</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_object_instance</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">I</span><span class="plain">) </span><span class="identifier">infs</span><span class="plain"> = </span><span class="functiontext">Instances::as_subject</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">nc</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_instance</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nc</span><span class="plain">) </span><span class="identifier">infs</span><span class="plain"> = </span><span class="functiontext">Instances::as_subject</span><span class="plain">(</span><span class="identifier">nc</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">infs</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::from_specification is used in 4/am (<a href="4-am.html#SP25_6">&#167;25.6</a>), 5/nv (<a href="5-nv.html#SP24">&#167;24</a>), 6/rlt (<a href="6-rlt.html#SP28">&#167;28</a>), 9/rpt (<a href="9-rpt.html#SP1">&#167;1</a>), 12/ap (<a href="12-ap.html#SP12">&#167;12</a>), 14/ds2 (<a href="14-ds2.html#SP11_9_1_2_3">&#167;11.9.1.2.3</a>), 16/in (<a href="16-in.html#SP19">&#167;19</a>), 26/i6i (<a href="26-i6i.html#SP6_4">&#167;6.4</a>).</p>
<p class="inwebparagraph"><a id="SP18"></a><b>&#167;18. Back conversions. </b>In the end subjects are, in part, wrappers to unify a range of other data
structures, and sometimes we want to tear off the wrapper. The following is
almost the inverse of the function above &mdash; for inference subjects or for
specifications they correspond to, they are indeed inverses; for other
specifications, forward conversion returns <code class="display"><span class="extract">NULL</span></code> and the question doesn't
arise.
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::as_constant</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</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">InferenceSubjects::domain</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Specifications::from_kind</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::as_object_instance</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">I</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Rvalues::from_instance</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">);</span>
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">nc</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::as_nc</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nc</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Rvalues::from_instance</span><span class="plain">(</span><span class="identifier">nc</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 InferenceSubjects::as_constant is used in 6/er (<a href="6-er.html#SP4">&#167;4</a>), 9/rpt (<a href="9-rpt.html#SP1">&#167;1</a>), 11/tc (<a href="11-tc.html#SP3">&#167;3</a>), 12/ap (<a href="12-ap.html#SP9_11">&#167;9.11</a>).</p>
<p class="inwebparagraph"><a id="SP19"></a><b>&#167;19. </b>More prosaically:
</p>
<pre class="display">
<span class="reserved">instance</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::as_instance</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">infs</span><span class="plain">) &amp;&amp; (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain"> == </span><span class="constant">INST_SUB</span><span class="plain">)) {</span>
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">nc</span><span class="plain"> = </span><span class="identifier">RETRIEVE_POINTER_instance</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;represents</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">nc</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>
<span class="reserved">instance</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::as_object_instance</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">infs</span><span class="plain">) &amp;&amp; (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain"> == </span><span class="constant">INST_SUB</span><span class="plain">)) {</span>
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">nc</span><span class="plain"> = </span><span class="identifier">RETRIEVE_POINTER_instance</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;represents</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::le</span><span class="plain">(</span><span class="functiontext">Instances::to_kind</span><span class="plain">(</span><span class="identifier">nc</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">nc</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>
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::as_nonobject_kind</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">infs</span><span class="plain">) &amp;&amp; (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain"> == </span><span class="constant">KIND_SUB</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::base_construction</span><span class="plain">(</span>
<span class="identifier">RETRIEVE_POINTER_kind_constructor</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;represents</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::lt</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K</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>
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::as_kind</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">infs</span><span class="plain">) &amp;&amp; (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain"> == </span><span class="constant">KIND_SUB</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::base_construction</span><span class="plain">(</span>
<span class="identifier">RETRIEVE_POINTER_kind_constructor</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;represents</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>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">nonlocal_variable</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::as_nlv</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">infs</span><span class="plain">) &amp;&amp; (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain"> == </span><span class="constant">VARI_SUB</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">RETRIEVE_POINTER_nonlocal_variable</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;represents</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>
<span class="reserved">binary_predicate</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::as_bp</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">infs</span><span class="plain">) &amp;&amp; (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain"> == </span><span class="constant">RELN_SUB</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">RETRIEVE_POINTER_binary_predicate</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;represents</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>
<span class="reserved">instance</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::as_nc</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">infs</span><span class="plain">) &amp;&amp; (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain"> == </span><span class="constant">INST_SUB</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">RETRIEVE_POINTER_instance</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;represents</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 InferenceSubjects::as_instance is used in 5/ins (<a href="5-ins.html#SP28">&#167;28</a>), 15/epv (<a href="15-epv.html#SP1">&#167;1</a>, <a href="15-epv.html#SP2">&#167;2</a>, <a href="15-epv.html#SP2_1">&#167;2.1</a>).</p>
<p class="endnote">The function InferenceSubjects::as_object_instance is used in <a href="#SP18">&#167;18</a>, <a href="#SP20">&#167;20</a>, 2/sq (<a href="2-sq.html#SP2">&#167;2</a>), 4/am (<a href="4-am.html#SP21">&#167;21</a>), 9/tfa (<a href="9-tfa.html#SP13">&#167;13</a>), 12/ap (<a href="12-ap.html#SP9_6">&#167;9.6</a>, <a href="12-ap.html#SP9_7">&#167;9.7</a>, <a href="12-ap.html#SP9_8">&#167;9.8</a>, <a href="12-ap.html#SP9_9">&#167;9.9</a>, <a href="12-ap.html#SP9_10">&#167;9.10</a>, <a href="12-ap.html#SP10">&#167;10</a>), 14/lv (<a href="14-lv.html#SP14_3_1">&#167;14.3.1</a>), 16/in (<a href="16-in.html#SP12">&#167;12</a>).</p>
<p class="endnote">The function InferenceSubjects::as_nonobject_kind is used in <a href="#SP22">&#167;22</a>, 4/am (<a href="4-am.html#SP26">&#167;26</a>), 9/rpt (<a href="9-rpt.html#SP9_6">&#167;9.6</a>), 9/ass (<a href="9-ass.html#SP9_1">&#167;9.1</a>).</p>
<p class="endnote">The function InferenceSubjects::as_kind is used in <a href="#SP21">&#167;21</a>, 5/ins (<a href="5-ins.html#SP18">&#167;18</a>), 9/tbath (<a href="9-tbath.html#SP7">&#167;7</a>), 12/ap (<a href="12-ap.html#SP9_6">&#167;9.6</a>), 13/kak (<a href="13-kak.html#SP2">&#167;2</a>, <a href="13-kak.html#SP4">&#167;4</a>, <a href="13-kak.html#SP5">&#167;5</a>, <a href="13-kak.html#SP6">&#167;6</a>), 15/pr (<a href="15-pr.html#SP27">&#167;27</a>), 15/epv (<a href="15-epv.html#SP1">&#167;1</a>, <a href="15-epv.html#SP2">&#167;2</a>, <a href="15-epv.html#SP2_1">&#167;2.1</a>), 16/ic (<a href="16-ic.html#SP12_3">&#167;12.3</a>, <a href="16-ic.html#SP14">&#167;14</a>).</p>
<p class="endnote">The function InferenceSubjects::as_nlv is used in 5/nv (<a href="5-nv.html#SP15">&#167;15</a>).</p>
<p class="endnote">The function InferenceSubjects::as_bp is used in <a href="#SP22">&#167;22</a>, 6/bp (<a href="6-bp.html#SP33">&#167;33</a>).</p>
<p class="endnote">The function InferenceSubjects::as_nc is used in <a href="#SP18">&#167;18</a>, 5/ins (<a href="5-ins.html#SP27">&#167;27</a>, <a href="5-ins.html#SP29">&#167;29</a>, <a href="5-ins.html#SP34">&#167;34</a>).</p>
<p class="inwebparagraph"><a id="SP20"></a><b>&#167;20. </b>...and, because it makes conditions more legible,
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::is_an_object</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">InferenceSubjects::as_object_instance</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::is_a_kind_of_object</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">infs</span><span class="plain">) &amp;&amp; (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain"> == </span><span class="constant">KIND_SUB</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::base_construction</span><span class="plain">(</span>
<span class="identifier">RETRIEVE_POINTER_kind_constructor</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;represents</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::lt</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::is_an_object is used in 9/rpt (<a href="9-rpt.html#SP9_6_1">&#167;9.6.1</a>), 9/tc (<a href="9-tc.html#SP5_2_2">&#167;5.2.2</a>, <a href="9-tc.html#SP8_4_1">&#167;8.4.1</a>), 9/ma (<a href="9-ma.html#SP3_3_8">&#167;3.3.8</a>, <a href="9-ma.html#SP3_3_39">&#167;3.3.39</a>), 9/pk (<a href="9-pk.html#SP3_1">&#167;3.1</a>), 15/epv (<a href="15-epv.html#SP3_1">&#167;3.1</a>).</p>
<p class="endnote">The function InferenceSubjects::is_a_kind_of_object is used in 9/tbath (<a href="9-tbath.html#SP7">&#167;7</a>), 9/rpt (<a href="9-rpt.html#SP9_6_1">&#167;9.6.1</a>), 9/tc (<a href="9-tc.html#SP5_2_2">&#167;5.2.2</a>, <a href="9-tc.html#SP8_4_1">&#167;8.4.1</a>), 9/ma (<a href="9-ma.html#SP3_3_8">&#167;3.3.8</a>, <a href="9-ma.html#SP3_3_39">&#167;3.3.39</a>), 9/pk (<a href="9-pk.html#SP3_1">&#167;3.1</a>), 13/kak (<a href="13-kak.html#SP5">&#167;5</a>), 15/epv (<a href="15-epv.html#SP3_1">&#167;3.1</a>).</p>
<p class="inwebparagraph"><a id="SP21"></a><b>&#167;21. </b>Finally, just as subjects can represent individual values, so they can
also represent collections of values. (At present, though, only the subjects
from kinds actually do.)
</p>
<pre class="display">
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">InferenceSubjects::domain</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::as_kind</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::domain is used in <a href="#SP18">&#167;18</a>, 6/bp (<a href="6-bp.html#SP23">&#167;23</a>), 6/rlt (<a href="6-rlt.html#SP20_4">&#167;20.4</a>), 9/tfa (<a href="9-tfa.html#SP13">&#167;13</a>), 9/rpt (<a href="9-rpt.html#SP3">&#167;3</a>, <a href="9-rpt.html#SP9_6">&#167;9.6</a>), 9/tc (<a href="9-tc.html#SP4_2">&#167;4.2</a>), 9/ma (<a href="9-ma.html#SP3_3_8">&#167;3.3.8</a>, <a href="9-ma.html#SP3_3_32">&#167;3.3.32</a>), 9/pk (<a href="9-pk.html#SP3_1">&#167;3.1</a>), 9/rk (<a href="9-rk.html#SP3_2">&#167;3.2</a>), 9/ass (<a href="9-ass.html#SP11">&#167;11</a>, <a href="9-ass.html#SP12">&#167;12</a>), 9/imp (<a href="9-imp.html#SP5">&#167;5</a>, <a href="9-imp.html#SP7_1_3">&#167;7.1.3</a>), 9/pd (<a href="9-pd.html#SP5_6">&#167;5.6</a>, <a href="9-pd.html#SP6_1">&#167;6.1</a>), 11/tc (<a href="11-tc.html#SP2">&#167;2</a>), 12/ap (<a href="12-ap.html#SP9_10">&#167;9.10</a>), 15/ep (<a href="15-ep.html#SP3">&#167;3</a>), 15/ia (<a href="15-ia.html#SP1">&#167;1</a>).</p>
<p class="inwebparagraph"><a id="SP22"></a><b>&#167;22. Logging. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::log</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;null infs&gt;"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;infs_name_in_log</span><span class="plain">) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"infs&lt;%s&gt;"</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;infs_name_in_log</span><span class="plain">); </span><span class="reserved">return</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="functiontext">InferenceSubjects::get_name_text</span><span class="plain">(</span><span class="identifier">infs</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">InferenceSubjects::as_nonobject_kind</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"infs'$u'-k"</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"infs'%W'"</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="reserved">binary_predicate</span><span class="plain"> *</span><span class="identifier">bp</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::as_bp</span><span class="plain">(</span><span class="identifier">infs</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">LOG</span><span class="plain">(</span><span class="string">"infs'%S'"</span><span class="plain">, </span><span class="functiontext">BinaryPredicates::get_log_name</span><span class="plain">(</span><span class="identifier">bp</span><span class="plain">)); }</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"infs%d"</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::log_knowledge_about</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">inf</span><span class="plain">;</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Inferences drawn about $j:\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">); </span><span class="identifier">LOG_INDENT</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">inf</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::get_inferences</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="identifier">inf</span><span class="plain">; </span><span class="identifier">inf</span><span class="plain"> = </span><span class="identifier">inf</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$I\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">inf</span><span class="plain">);</span>
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::log is used in 1/cm (<a href="1-cm.html#SP5">&#167;5</a>, <a href="1-cm.html#SP6_6">&#167;6.6</a>).</p>
<p class="endnote">The function InferenceSubjects::log_knowledge_about appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP23"></a><b>&#167;23. </b>The subjects hierarchy is unlikely to reach a depth of 20 except by a bug,
but that's exactly when we need the debugging log most, so the following is
coded to ensure that it terminates whether or not the subjects form a connected
DAG.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::log_infs_hierarchy</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Subjects hierarchy:\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="functiontext">InferenceSubjects::log_subjects_hierarchically</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">, 0);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::log_subjects_hierarchically</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">count</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">count</span><span class="plain"> &gt; 20) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"*** Pruning: too deep ***\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$j\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">);</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">narrower</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">narrower</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">narrower</span><span class="plain">-</span><span class="element">&gt;broader_than</span><span class="plain"> == </span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="identifier">LOG_INDENT</span><span class="plain">;</span>
<span class="functiontext">InferenceSubjects::log_subjects_hierarchically</span><span class="plain">(</span><span class="identifier">narrower</span><span class="plain">, </span><span class="identifier">count</span><span class="plain">+1);</span>
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::log_infs_hierarchy is used in <a href="#SP10">&#167;10</a>.</p>
<p class="endnote">The function InferenceSubjects::log_subjects_hierarchically appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP24"></a><b>&#167;24. Methods. </b>The first of these should fill in a name, if one is available, placing the
word range into the variables pointed to by <code class="display"><span class="extract">w1</span></code> and <code class="display"><span class="extract">w2</span></code>.
</p>
<pre class="display">
<span class="identifier">wording</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::get_name_text</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"null INFS"</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">EMPTY_WORDING</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">FUND_SUB</span><span class="plain">: </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">KIND_SUB</span><span class="plain">: </span><span class="identifier">W</span><span class="plain"> = </span><span class="functiontext">Kinds::Knowledge::get_name_text</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INST_SUB</span><span class="plain">: </span><span class="identifier">W</span><span class="plain"> = </span><span class="functiontext">Instances::SUBJ_get_name_text</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">VARI_SUB</span><span class="plain">: </span><span class="identifier">W</span><span class="plain"> = </span><span class="functiontext">NonlocalVariables::SUBJ_get_name_text</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">RELN_SUB</span><span class="plain">: </span><span class="identifier">W</span><span class="plain"> = </span><span class="functiontext">BinaryPredicates::SUBJ_get_name_text</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">LOOP_THROUGH_WORDING</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Lexer::word</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) == </span><span class="identifier">STROKE_V</span><span class="plain">) {</span>
<span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Wordings::up_to</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">-1);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::get_name_text is used in <a href="#SP22">&#167;22</a>, 2/sq (<a href="2-sq.html#SP2">&#167;2</a>), 2/si (<a href="2-si.html#SP8">&#167;8</a>), 4/am (<a href="4-am.html#SP41_1">&#167;41.1</a>), 6/bp (<a href="6-bp.html#SP24">&#167;24</a>, <a href="6-bp.html#SP34">&#167;34</a>), 9/tc (<a href="9-tc.html#SP8_4_1_1">&#167;8.4.1.1</a>, <a href="9-tc.html#SP8_4_1_2">&#167;8.4.1.2</a>), 15/cp (<a href="15-cp.html#SP3_1">&#167;3.1</a>), 16/pp (<a href="16-pp.html#SP11">&#167;11</a>).</p>
<p class="inwebparagraph"><a id="SP25"></a><b>&#167;25. </b>In general property permissions work just as well whatever subject is getting
the new property, but the following is called to give the subject a chance to
react. It should return a general pointer to any extra data it wants to attach
to the permission, or <code class="display"><span class="extract">NULL_GENERAL_POINTER</span></code> if it has nothing to add.
</p>
<pre class="display">
<span class="identifier">general_pointer</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::new_permission_granted</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"null INFS"</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">FUND_SUB</span><span class="plain">: </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">KIND_SUB</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::Knowledge::new_permission_granted</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INST_SUB</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Instances::SUBJ_new_permission_granted</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">VARI_SUB</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">NonlocalVariables::SUBJ_new_permission_granted</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">RELN_SUB</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">BinaryPredicates::SUBJ_new_permission_granted</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL_GENERAL_POINTER</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::new_permission_granted is used in 16/pp (<a href="16-pp.html#SP9_1">&#167;9.1</a>).</p>
<p class="inwebparagraph"><a id="SP26"></a><b>&#167;26. </b>Suppose there is an instance, such as "green", belonging to a kind of
value which coincides with a property of some subject. Then the following is
called to tell the subject in question that it needs to become the domain
of "green" as an adjective.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::make_adj_const_domain</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">,</span>
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">nc</span><span class="plain">, </span><span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"null INFS"</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">FUND_SUB</span><span class="plain">: </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">KIND_SUB</span><span class="plain">: </span><span class="functiontext">Kinds::Knowledge::make_adj_const_domain</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">nc</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INST_SUB</span><span class="plain">: </span><span class="functiontext">Instances::SUBJ_make_adj_const_domain</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">nc</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">VARI_SUB</span><span class="plain">: </span><span class="functiontext">NonlocalVariables::SUBJ_make_adj_const_domain</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">nc</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">RELN_SUB</span><span class="plain">: </span><span class="functiontext">BinaryPredicates::SUBJ_make_adj_const_domain</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">nc</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::make_adj_const_domain is used in 5/ins (<a href="5-ins.html#SP11">&#167;11</a>).</p>
<p class="inwebparagraph"><a id="SP27"></a><b>&#167;27. </b>Part of the process of "completing" the model &mdash; that is, filling in detail
not spelled out explicitly in assertion sentences &mdash; is to ask each subject
to fill in anything missing about itself:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::complete_model</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"null INFS"</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">FUND_SUB</span><span class="plain">: </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">KIND_SUB</span><span class="plain">: </span><span class="functiontext">Kinds::Knowledge::complete_model</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INST_SUB</span><span class="plain">: </span><span class="functiontext">Instances::SUBJ_complete_model</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">VARI_SUB</span><span class="plain">: </span><span class="functiontext">NonlocalVariables::SUBJ_complete_model</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">RELN_SUB</span><span class="plain">: </span><span class="functiontext">BinaryPredicates::SUBJ_complete_model</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::complete_model is used in 16/cmw (<a href="16-cmw.html#SP1_1">&#167;1.1</a>).</p>
<p class="inwebparagraph"><a id="SP28"></a><b>&#167;28. </b>Each subject also has a chance to check the knowledge about it for
consistency, and to issue problem messages if something is wrong:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::check_model</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"null INFS"</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">FUND_SUB</span><span class="plain">: </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">KIND_SUB</span><span class="plain">: </span><span class="functiontext">Kinds::Knowledge::check_model</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INST_SUB</span><span class="plain">: </span><span class="functiontext">Instances::SUBJ_check_model</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">VARI_SUB</span><span class="plain">: </span><span class="functiontext">NonlocalVariables::SUBJ_check_model</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">RELN_SUB</span><span class="plain">: </span><span class="functiontext">BinaryPredicates::SUBJ_check_model</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::check_model is used in 16/cmw (<a href="16-cmw.html#SP1_2">&#167;1.2</a>).</p>
<p class="inwebparagraph"><a id="SP29"></a><b>&#167;29. </b>Here we must compile run-time code which tests whether the value in <code class="display"><span class="extract">t_0</span></code>
is a constant which the subject gives information about, given that we already
know it has the right atomic kind. (In some cases there will be nothing to
test &mdash; if we know that <code class="display"><span class="extract">t_0</span></code> has kind "number" then it must be what we want.
But in the case of objects, we need to check <code class="display"><span class="extract">t_0</span></code> is not <code class="display"><span class="extract">nothing</span></code> and that
it has the right kind, and so on. If there's nothing to check, we leave the
condition blank.)
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::emit_element_of_condition</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">t0_s</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"null INFS"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">written</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">FUND_SUB</span><span class="plain">: </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">KIND_SUB</span><span class="plain">: </span><span class="identifier">written</span><span class="plain"> = </span><span class="functiontext">Kinds::Knowledge::emit_element_of_condition</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">t0_s</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INST_SUB</span><span class="plain">: </span><span class="identifier">written</span><span class="plain"> = </span><span class="functiontext">Instances::SUBJ_emit_element_of_condition</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">t0_s</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">VARI_SUB</span><span class="plain">: </span><span class="identifier">written</span><span class="plain"> = </span><span class="functiontext">NonlocalVariables::SUBJ_emit_element_of_condition</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">t0_s</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">RELN_SUB</span><span class="plain">: </span><span class="identifier">written</span><span class="plain"> = </span><span class="functiontext">BinaryPredicates::SUBJ_emit_element_of_condition</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">t0_s</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">written</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">Produce::val</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_truth_state</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 1);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::emit_element_of_condition is used in 4/am (<a href="4-am.html#SP35">&#167;35</a>).</p>
<p class="inwebparagraph"><a id="SP30"></a><b>&#167;30. </b>The model world needs to have its complex initial state stored somewhere
at run-time. Each subject may need its own data structure, and we want no
part of thinking about what it looks like.
</p>
<p class="inwebparagraph">Each kind of subject has a chance to compile all its subjects at once,
which enables this to be done in a funny order or in some consolidated
array, or else have its subjects compiled one at a time in order of their
creation. <code class="display"><span class="extract">compile_all</span></code> should return <code class="display"><span class="extract">TRUE</span></code> to indicate the former course.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">InferenceSubjects::compile_all</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain">)</span>
<span class="functiontext">World::Inferences::verify_prop_states</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">koi</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">koi</span><span class="plain">=1; </span><span class="identifier">koi</span><span class="plain">&lt;=</span><span class="constant">MAX_SUB</span><span class="plain">; </span><span class="identifier">koi</span><span class="plain">++) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">done</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">koi</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">FUND_SUB</span><span class="plain">: </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">KIND_SUB</span><span class="plain">: </span><span class="identifier">done</span><span class="plain"> = </span><span class="functiontext">Kinds::Knowledge::emit_all</span><span class="plain">(); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INST_SUB</span><span class="plain">: </span><span class="identifier">done</span><span class="plain"> = </span><span class="functiontext">Instances::SUBJ_compile_all</span><span class="plain">(); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">VARI_SUB</span><span class="plain">: </span><span class="identifier">done</span><span class="plain"> = </span><span class="functiontext">NonlocalVariables::SUBJ_compile_all</span><span class="plain">(); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">RELN_SUB</span><span class="plain">: </span><span class="identifier">done</span><span class="plain"> = </span><span class="functiontext">BinaryPredicates::SUBJ_compile_all</span><span class="plain">(); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">done</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain"> == </span><span class="identifier">koi</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain">-</span><span class="element">&gt;kind_of_infs</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">FUND_SUB</span><span class="plain">: </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">KIND_SUB</span><span class="plain">: </span><span class="functiontext">Kinds::Knowledge::emit</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INST_SUB</span><span class="plain">: </span><span class="functiontext">Instances::SUBJ_compile</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">VARI_SUB</span><span class="plain">: </span><span class="functiontext">NonlocalVariables::SUBJ_compile</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">RELN_SUB</span><span class="plain">: </span><span class="functiontext">BinaryPredicates::SUBJ_compile</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function InferenceSubjects::compile_all is used in 16/cmw2 (<a href="16-cmw2.html#SP2">&#167;2</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><i>(This section begins Chapter 16: Inference and Model.)</i></li><li><a href="16-pp.html">Continue with 'Property Permissions'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>