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/9-ass.html
2019-08-24 11:21:48 +01:00

567 lines
60 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>9/rk</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 '9/ass' 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#9">Chapter 9: The A-Parser</a></li><li><b>Assemblies</b></li></ul><p class="purpose">To build the complex multi-object assemblies which result from allowing the source text to say things like "in every room is a vehicle".</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP6">&#167;6. Initialisation</a></li><li><a href="#SP9">&#167;9. New generalisations</a></li><li><a href="#SP11">&#167;11. The assembly process</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>Assemblies are made when an object of a given kind is created, and when
generalisations about that kind mean that further creations are also
needed. For instance: if a generalisation has said that every container
contains a shoe, then each time a container is created, we also need to
create a shoe, and assert a spatial relationship between them.
</p>
<p class="inwebparagraph">In practice we do this by a simple process which involves cutting and
pasting of subtrees of the parse tree, which motivates the following
data structure.
</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Generalisations are essentially fragments of parse tree stored for later use.
They handle sentences like
</p>
<blockquote>
<p>In every container is a coin.</p>
</blockquote>
<p class="inwebparagraph">which are done by recognising the prototype part ("in every container") in
the parse tree and grafting on a duplicate of the assembly part ("a coin")
in place of the <code class="display"><span class="extract">EVERY_NT</span></code> subtree ("every container"). Sometimes the EVERY
subtree is the whole prototype subtree ("Every coin is on a table"), in
which case <code class="display"><span class="extract">px</span></code> and <code class="display"><span class="extract">substitute_at</span></code> in the following structure coincide.
</p>
<p class="inwebparagraph">Each kind (in this example "container") keeps a linked list of the
generalisations which apply to it.
</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">generalisation</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">look_for</span><span class="plain">; </span> <span class="comment">prototype situation to look for</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">what_to_make</span><span class="plain">; </span> <span class="comment">subtree for what to assemble</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">substitute_at</span><span class="plain">; </span> <span class="comment">position under <code class="display"><span class="extract">look_for</span></code> of the EVERY node</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">generalisation</span><span class="plain"> *</span><span class="identifier">next</span><span class="plain">; </span> <span class="comment">next in list of generalisations about kind</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">generalisation</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure generalisation is accessed in 3/pd, 5/lp, 5/ut, 5/un, 5/ins, 6/rlt, 6/nv, 7/ss, 7/hdn, 7/ns, 7/oaf, 7/rs, 8/ie, 8/ec, 8/ed, 9/tfa, 9/tbath, 9/rpt, 9/tc, 9/ma, 9/rk, 9/imp, 9/pd, 10/teav, 10/cap, 11/ap, 11/pr, 11/bas, 11/tc, 11/sm, 12/dtd, 12/cdp, 14/rv, 14/lv, 14/cn, 14/ds, 14/ds2, 15/cp, 16/is, 16/in, 19/tb, 19/rsft, 19/tod, 20/eq, 21/rl, 21/rl2, 21/fao, 21/rps, 21/sv, 21/ac, 22/ph, 22/tp, 22/tp2, 23/ad, 24/lv, 24/sf, 25/in, 25/pi, 25/cii, 25/cp, 26/uo, 26/tti, 26/pc, 26/ts, 27/cm and here.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>For reasons to do with timing, each object needs to keep track of which
generalisations have and have not yet applied to it. In practice, this is
a list of pairs (K, g) where K is a kind and g is the most recent one
applied from K's list.
</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">application</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="identifier">generalisation_owner</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">generalisation</span><span class="plain"> *</span><span class="identifier">latest_applied</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">application</span><span class="plain"> *</span><span class="identifier">next</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">application</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure application is accessed in 3/pd, 5/lp, 5/ut, 5/un, 5/ins, 6/rlt, 6/nv, 7/ss, 7/hdn, 7/ns, 7/oaf, 7/rs, 8/ie, 8/ec, 8/ed, 9/tfa, 9/tbath, 9/rpt, 9/tc, 9/ma, 9/rk, 9/imp, 9/pd, 10/teav, 10/cap, 11/ap, 11/pr, 11/bas, 11/tc, 11/sm, 12/dtd, 12/cdp, 14/rv, 14/lv, 14/cn, 14/ds, 14/ds2, 15/cp, 16/is, 16/in, 19/tb, 19/rsft, 19/tod, 20/eq, 21/rl, 21/rl2, 21/fao, 21/rps, 21/sv, 21/ac, 22/ph, 22/tp, 22/tp2, 23/ad, 24/lv, 24/sf, 25/in, 25/pi, 25/cii, 25/cp, 26/uo, 26/tti, 26/pc, 26/ts, 27/cm and here.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>These structures are combined in the following packet of data attached to
each inference subject:
</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">assemblies_data</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">generalisation</span><span class="plain"> *</span><span class="identifier">generalisation_list</span><span class="plain">; </span> <span class="comment">kinds only: assembly instructions, if any</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">application</span><span class="plain"> *</span><span class="identifier">applications_so_far</span><span class="plain">; </span> <span class="comment">instances only: progress</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">named_after</span><span class="plain">; </span> <span class="comment">name derived from another: e.g. "Jane's nose"</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">named_after_text</span><span class="plain">; </span> <span class="comment">text of the derived part, e.g. "nose"</span>
<span class="plain">} </span><span class="reserved">assemblies_data</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure assemblies_data is private to this section.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Initialisation. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Assertions::Assemblies::initialise_assemblies_data</span><span class="plain">(</span><span class="reserved">assemblies_data</span><span class="plain"> *</span><span class="identifier">ad</span><span class="plain">) {</span>
<span class="identifier">ad</span><span class="plain">-</span><span class="element">&gt;generalisation_list</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">ad</span><span class="plain">-</span><span class="element">&gt;applications_so_far</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">ad</span><span class="plain">-</span><span class="element">&gt;named_after</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">ad</span><span class="plain">-</span><span class="element">&gt;named_after_text</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Assertions::Assemblies::initialise_assemblies_data is used in 16/is (<a href="16-is.html#SP10">&#167;10</a>).</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>Setting the naming-after information.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Assertions::Assemblies::name_object_after</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">after</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">assemblies_data</span><span class="plain"> *</span><span class="identifier">ad</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::get_assemblies_data</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="identifier">ad</span><span class="plain">-</span><span class="element">&gt;named_after</span><span class="plain"> = </span><span class="identifier">after</span><span class="plain">;</span>
<span class="identifier">ad</span><span class="plain">-</span><span class="element">&gt;named_after_text</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 Assertions::Assemblies::name_object_after is used in 9/tc (<a href="9-tc.html#SP8_4_1">&#167;8.4.1</a>).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>And reading it again.
</p>
<pre class="display">
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="functiontext">Assertions::Assemblies::what_this_is_named_after</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">assemblies_data</span><span class="plain"> *</span><span class="identifier">ad</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::get_assemblies_data</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">ad</span><span class="plain">-</span><span class="element">&gt;named_after</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="functiontext">Assertions::Assemblies::get_named_after_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">assemblies_data</span><span class="plain"> *</span><span class="identifier">ad</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::get_assemblies_data</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">ad</span><span class="plain">-</span><span class="element">&gt;named_after_text</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Assertions::Assemblies::what_this_is_named_after appears nowhere else.</p>
<p class="endnote">The function Assertions::Assemblies::get_named_after_text appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. New generalisations. </b>Here a new generalisation is made. The <code class="display"><span class="extract">look_for</span></code> subtree contains the
<code class="display"><span class="extract">EVERY_NT</span></code> node, but it might be either at the top, as here:
</p>
<blockquote>
<p>Every container is in the Lumber Room.</p>
</blockquote>
<p class="inwebparagraph">or the first child of a <code class="display"><span class="extract">RELATIONSHIP_NT</span></code> node, as here:
</p>
<blockquote>
<p>In every container is a vehicle.</p>
</blockquote>
<p class="inwebparagraph">In the second case the <code class="display"><span class="extract">what_to_make</span></code> subtree is an <code class="display"><span class="extract">COMMON_NOUN_NT</span></code>, and in the
first it's a <code class="display"><span class="extract">RELATIONSHIP_NT</span></code> subtree.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Assertions::Assemblies::make_generalisation</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">look_for</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">what_to_make</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">EVERY_node</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">look_for</span><span class="plain">) == </span><span class="constant">EVERY_NT</span><span class="plain">) </span><span class="identifier">EVERY_node</span><span class="plain"> = </span><span class="identifier">look_for</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">look_for</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) &amp;&amp; (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">look_for</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) == </span><span class="constant">EVERY_NT</span><span class="plain">))</span>
<span class="identifier">EVERY_node</span><span class="plain"> = </span><span class="identifier">look_for</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Generalisation without EVERY node"</span><span class="plain">);</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">k</span><span class="plain"> = </span><span class="identifier">ParseTree::get_subject</span><span class="plain">(</span><span class="identifier">EVERY_node</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Malformed EVERY node"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Assertions::Assemblies::subtree_mentions_kind</span><span class="plain">(</span><span class="identifier">look_for</span><span class="plain">,</span><span class="identifier">k</span><span class="plain">,0)) ||</span>
<span class="plain">(</span><span class="functiontext">Assertions::Assemblies::subtree_mentions_kind</span><span class="plain">(</span><span class="identifier">what_to_make</span><span class="plain">,</span><span class="identifier">k</span><span class="plain">,0)))</span>
&lt;<span class="cwebmacro">Issue an infinite regress of assemblies problem message</span> <span class="cwebmacronumber">9.5</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Forbid generalisation about fixed kinds</span> <span class="cwebmacronumber">9.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Forbid generalisation on both sides</span> <span class="cwebmacronumber">9.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">If we have to make a kind qualified by adjectives, expand that into a suitable subtree</span> <span class="cwebmacronumber">9.3</span>&gt;<span class="plain">;</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">EVERY_node</span><span class="plain">, </span><span class="identifier">EMPTY_WORDING</span><span class="plain">);</span>
<span class="reserved">generalisation</span><span class="plain"> *</span><span class="identifier">g</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">generalisation</span><span class="plain">);</span>
<span class="identifier">g</span><span class="plain">-</span><span class="element">&gt;look_for</span><span class="plain"> = </span><span class="identifier">look_for</span><span class="plain">;</span>
<span class="identifier">g</span><span class="plain">-</span><span class="element">&gt;what_to_make</span><span class="plain"> = </span><span class="identifier">what_to_make</span><span class="plain">;</span>
<span class="identifier">g</span><span class="plain">-</span><span class="element">&gt;substitute_at</span><span class="plain"> = </span><span class="identifier">EVERY_node</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Add this new generalisation to the list for the kind it applies to</span> <span class="cwebmacronumber">9.4</span>&gt;<span class="plain">;</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">, </span><span class="constant">you_can_ignore_ANNOT</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">ASSEMBLIES</span><span class="plain">, </span><span class="string">"New generalisation made concerning $j:\</span><span class="plain">n</span><span class="string">Look for: $T\</span><span class="plain">n</span><span class="string">Make: $T\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">k</span><span class="plain">, </span><span class="identifier">g</span><span class="plain">-</span><span class="element">&gt;look_for</span><span class="plain">, </span><span class="identifier">g</span><span class="plain">-</span><span class="element">&gt;what_to_make</span><span class="plain">);</span>
<span class="functiontext">Assertions::Assemblies::ensure_all_generalisations_made</span><span class="plain">(</span><span class="identifier">k</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Assertions::Assemblies::make_generalisation is used in 9/ma (<a href="9-ma.html#SP3_3_31">&#167;3.3.31</a>, <a href="9-ma.html#SP3_3_34_1">&#167;3.3.34.1</a>, <a href="9-ma.html#SP3_3_35">&#167;3.3.35</a>).</p>
<p class="inwebparagraph"><a id="SP9_1"></a><b>&#167;9.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Forbid generalisation about fixed kinds</span> <span class="cwebmacronumber">9.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">instance_kind</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::as_nonobject_kind</span><span class="plain">(</span><span class="identifier">k</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">instance_kind</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">instance_kind</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Kinds::Behaviour::has_named_constant_values</span><span class="plain">(</span><span class="identifier">instance_kind</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$T"</span><span class="plain">, </span><span class="identifier">look_for</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$T"</span><span class="plain">, </span><span class="identifier">what_to_make</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_AssemblyOnFixedKind</span><span class="plain">),</span>
<span class="string">"this generalisation can't be made"</span><span class="plain">,</span>
<span class="string">"because I only use generalisations to talk about values which can be "</span>
<span class="string">"created as needed, like things or scenes - not about those always "</span>
<span class="string">"existing in fixed ranges, like numbers or times."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP9_2"></a><b>&#167;9.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Forbid generalisation on both sides</span> <span class="cwebmacronumber">9.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">what_to_make</span><span class="plain">) &amp;&amp; (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">what_to_make</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) == </span><span class="constant">EVERY_NT</span><span class="plain">)) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$T"</span><span class="plain">, </span><span class="identifier">look_for</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$T"</span><span class="plain">, </span><span class="identifier">what_to_make</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_AssemblyOnBothSides</span><span class="plain">),</span>
<span class="string">"this generalisation can't be made"</span><span class="plain">,</span>
<span class="string">"because it uses 'every' or some similar generalisation on both sides, "</span>
<span class="string">"which is too rich for my taste."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP9_3"></a><b>&#167;9.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">If we have to make a kind qualified by adjectives, expand that into a suitable subtree</span> <span class="cwebmacronumber">9.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">val</span><span class="plain"> = </span><span class="identifier">ParseTree::get_evaluation</span><span class="plain">(</span><span class="identifier">what_to_make</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">val</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Descriptions::is_adjectives_plus_kind</span><span class="plain">(</span><span class="identifier">val</span><span class="plain">))) {</span>
<span class="functiontext">Assertions::Refiner::refine_from_simple_description</span><span class="plain">(</span><span class="identifier">what_to_make</span><span class="plain">, </span><span class="identifier">ParseTree::duplicate</span><span class="plain">(</span><span class="identifier">val</span><span class="plain">));</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP9_4"></a><b>&#167;9.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Add this new generalisation to the list for the kind it applies to</span> <span class="cwebmacronumber">9.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">assemblies_data</span><span class="plain"> *</span><span class="identifier">ad</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::get_assemblies_data</span><span class="plain">(</span><span class="identifier">k</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ad</span><span class="plain">-</span><span class="element">&gt;generalisation_list</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="identifier">ad</span><span class="plain">-</span><span class="element">&gt;generalisation_list</span><span class="plain"> = </span><span class="identifier">g</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">generalisation</span><span class="plain"> *</span><span class="identifier">g2</span><span class="plain"> = </span><span class="identifier">ad</span><span class="plain">-</span><span class="element">&gt;generalisation_list</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">g2</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) </span><span class="identifier">g2</span><span class="plain"> = </span><span class="identifier">g2</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="identifier">g2</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">g</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">g</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP9_5"></a><b>&#167;9.5. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue an infinite regress of assemblies problem message</span> <span class="cwebmacronumber">9.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Generalisation:\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$T"</span><span class="plain">, </span><span class="identifier">look_for</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$T"</span><span class="plain">, </span><span class="identifier">what_to_make</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_AssemblyRegress</span><span class="plain">),</span>
<span class="string">"this generalisation would be too dangerous"</span><span class="plain">,</span>
<span class="string">"because it would lead to infinite regress in the assembly process. Sometimes "</span>
<span class="string">"this happens if you have set up matters with text like 'A container is in every "</span>
<span class="string">"container.'."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>This is used only in checking for infinite regress:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Assertions::Assemblies::subtree_mentions_kind</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">subtree</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">k</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">level</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">subtree</span><span class="plain">) == </span><span class="constant">COMMON_NOUN_NT</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">ParseTree::get_subject</span><span class="plain">(</span><span class="identifier">subtree</span><span class="plain">) == </span><span class="identifier">k</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">subtree</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Assertions::Assemblies::subtree_mentions_kind</span><span class="plain">(</span><span class="identifier">subtree</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">, </span><span class="identifier">level</span><span class="plain">+1)))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">level</span><span class="plain">&gt;0) &amp;&amp; (</span><span class="identifier">subtree</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Assertions::Assemblies::subtree_mentions_kind</span><span class="plain">(</span><span class="identifier">subtree</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">, </span><span class="identifier">level</span><span class="plain">)))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Assertions::Assemblies::subtree_mentions_kind is used in <a href="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. The assembly process. </b>As noticed above, it's useful to have a routine which brings up to date the
application of generalisations. When this routine completes, every object
of a given kind has undergone every generalisation applicable to it exactly once.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Assertions::Assemblies::ensure_all_generalisations_made</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">k</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="functiontext">InferenceSubjects::is_within</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">)) &amp;&amp; (</span><span class="functiontext">InferenceSubjects::domain</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="functiontext">Assertions::Assemblies::satisfies_generalisations</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 Assertions::Assemblies::ensure_all_generalisations_made is used in <a href="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>Clearly one reason we might need to bring generalisations up to date is if
the kind of an object is determined, because that potentially expands the set of
generalisations applicable to it. But it's needlessly slow to apply a full
refresh when we know the only object which can be affected, so in that
situation we call just <code class="display"><span class="extract">Assertions::Assemblies::satisfies_generalisations</span></code> on the object in question.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Assertions::Assemblies::satisfies_generalisations</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::domain</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="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">k</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::narrowest_broader_subject</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">); </span><span class="identifier">k</span><span class="plain">; </span><span class="identifier">k</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::narrowest_broader_subject</span><span class="plain">(</span><span class="identifier">k</span><span class="plain">)) {</span>
<span class="reserved">application</span><span class="plain"> *</span><span class="identifier">app</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">app</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::get_assemblies_data</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">)-</span><span class="element">&gt;applications_so_far</span><span class="plain">; </span><span class="identifier">app</span><span class="plain">; </span><span class="identifier">app</span><span class="plain"> = </span><span class="identifier">app</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">app</span><span class="plain">-</span><span class="element">&gt;generalisation_owner</span><span class="plain"> == </span><span class="identifier">k</span><span class="plain">)</span>
<span class="reserved">break</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Apply generalisations about K which have not yet been applied</span> <span class="cwebmacronumber">12.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Assertions::Assemblies::satisfies_generalisations is used in <a href="#SP11">&#167;11</a>, 5/ins (<a href="5-ins.html#SP6">&#167;6</a>, <a href="5-ins.html#SP19">&#167;19</a>).</p>
<p class="inwebparagraph"><a id="SP12_1"></a><b>&#167;12.1. </b>At this point <code class="display"><span class="extract">app</span></code> points to the record of which generalisations in K
have been applied to the object so far, or is <code class="display"><span class="extract">NULL</span></code> if none of K's
generalisation has ever been applied to it.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Apply generalisations about K which have not yet been applied</span> <span class="cwebmacronumber">12.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">generalisation</span><span class="plain"> *</span><span class="identifier">ignore_up_to</span><span class="plain"> = (</span><span class="identifier">app</span><span class="plain">)?(</span><span class="identifier">app</span><span class="plain">-</span><span class="element">&gt;latest_applied</span><span class="plain">):</span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">generalisation</span><span class="plain"> *</span><span class="identifier">g</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">g</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::get_assemblies_data</span><span class="plain">(</span><span class="identifier">k</span><span class="plain">)-</span><span class="element">&gt;generalisation_list</span><span class="plain">; </span><span class="identifier">g</span><span class="plain">; </span><span class="identifier">g</span><span class="plain">=</span><span class="identifier">g</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ignore_up_to</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">g</span><span class="plain"> == </span><span class="identifier">ignore_up_to</span><span class="plain">) </span><span class="identifier">ignore_up_to</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">app</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span>&lt;<span class="cwebmacro">Create a new record for this previously unapplied kind</span> <span class="cwebmacronumber">12.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">app</span><span class="plain">-</span><span class="element">&gt;latest_applied</span><span class="plain"> = </span><span class="identifier">g</span><span class="plain">;</span>
<span class="functiontext">Assertions::Assemblies::satisfies_generalisation</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">g</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP12_1_1"></a><b>&#167;12.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Create a new record for this previously unapplied kind</span> <span class="cwebmacronumber">12.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">app</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">application</span><span class="plain">);</span>
<span class="identifier">app</span><span class="plain">-</span><span class="element">&gt;generalisation_owner</span><span class="plain"> = </span><span class="identifier">k</span><span class="plain">;</span>
<span class="identifier">app</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::get_assemblies_data</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">)-</span><span class="element">&gt;applications_so_far</span><span class="plain">;</span>
<span class="functiontext">InferenceSubjects::get_assemblies_data</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">)-</span><span class="element">&gt;applications_so_far</span><span class="plain"> = </span><span class="identifier">app</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12_1">&#167;12.1</a>.</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b>It's worth a brief pause to think about the time and storage needed by the
above. Let N be the number of objects, and H the maximum depth of the kinds
hierarchy; while in theory H might be O(N), it's more likely to be about
log_2 N if the kinds hierarchy is balanced, and in practice even for very
large Inform source texts H is never larger than 7 or 8.
</p>
<p class="inwebparagraph">The storage required to record G generalisations is proportional to G,
since each appears only in a single linked list and is recorded in a single
structure instance. We clearly won't do better than that.
</p>
<p class="inwebparagraph">The storage required to record which generalisations have so far applied to
which objects is O(HN), since each object stores about 12H bytes of data,
which is significantly better than a bitmap recording all pairs of generalisations
and objects (which would be O(GN)). The running time of <code class="display"><span class="extract">Assertions::Assemblies::satisfies_generalisations</span></code>
applied to object X is O(G_X H^2), where G_X is the number of generalisations
which can be applied to X. In the course of compilation this is called once
each time the kind of X is changed &mdash; at most H times &mdash; and once each time
a new generalisation applicable to X is added &mdash; at most G_X times. So we
have a total time consumption of O(G_X^2 H^2 + G_X H^3). In practice the
constants are low, G_X is very small compared to the size of the source
text, and so is H.
</p>
<p class="inwebparagraph">The main point, then, is that the mechanism above is much, much faster than
repeatedly checking each generalisation against each object, for a cost of
O(G^2N).
</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. </b>So here we get on with the actual construction: we apply <code class="display"><span class="extract">g</span></code> to <code class="display"><span class="extract">infs</span></code>. What
we actually do is to insert new sentences after the current one.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">implicit_recursion_exception</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span> <span class="comment">thrown when we've gone into infinite regress</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Assertions::Assemblies::satisfies_generalisation</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">generalisation</span><span class="plain"> *</span><span class="identifier">g</span><span class="plain">) {</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">counterpart</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">snatcher</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Plugins::Call::detect_bodysnatching</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, &amp;</span><span class="identifier">snatcher</span><span class="plain">, &amp;</span><span class="identifier">counterpart</span><span class="plain">)) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">ASSEMBLIES</span><span class="plain">, </span><span class="string">"Body-snatcher found! Subj $j, snatcher %d, counterpart $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">snatcher</span><span class="plain">, </span><span class="identifier">counterpart</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">snatcher</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs_k</span><span class="plain"> = </span><span class="identifier">ParseTree::get_subject</span><span class="plain">(</span><span class="identifier">g</span><span class="plain">-</span><span class="element">&gt;substitute_at</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Throw the infinite regress exception if the current sentence makes too many things</span> <span class="cwebmacronumber">14.1</span>&gt;<span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">new_sentence</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="identifier">SENTENCE_NT</span><span class="plain">);</span>
<span class="comment">mark this sentence as implicit, and increase its generation count:</span>
<span class="identifier">ParseTree::set_implicit_in_creation_of</span><span class="plain">(</span><span class="identifier">new_sentence</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">);</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">new_sentence</span><span class="plain">, </span><span class="constant">implicitness_count_ANNOT</span><span class="plain">,</span>
<span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">, </span><span class="constant">implicitness_count_ANNOT</span><span class="plain">) + 1);</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">new_sentence</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">));</span>
<span class="comment">temporarily make the <code class="display"><span class="extract">EVERY_NT</span></code> node refer to the specific new <code class="display"><span class="extract">infs</span></code>:</span>
<span class="functiontext">Assertions::Refiner::noun_from_infs</span><span class="plain">(</span><span class="identifier">g</span><span class="plain">-</span><span class="element">&gt;substitute_at</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">);</span>
<span class="comment">make the new sentence an assertion:</span>
<span class="identifier">new_sentence</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="identifier">AVERB_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">new_sentence</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, </span><span class="constant">verb_id_ANNOT</span><span class="plain">, </span><span class="constant">ASSERT_VB</span><span class="plain">);</span>
<span class="identifier">new_sentence</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">CREATED_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::copy_subtree</span><span class="plain">(</span><span class="identifier">g</span><span class="plain">-</span><span class="element">&gt;look_for</span><span class="plain">, </span><span class="identifier">new_sentence</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">, 0);</span>
<span class="identifier">new_sentence</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">CREATED_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::copy_subtree</span><span class="plain">(</span><span class="identifier">g</span><span class="plain">-</span><span class="element">&gt;what_to_make</span><span class="plain">, </span><span class="identifier">new_sentence</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">, 0);</span>
<span class="identifier">new_sentence</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="comment">restore the <code class="display"><span class="extract">EVERY_NT</span></code> node, now that the tree containing it has been copied:</span>
<span class="identifier">ParseTree::set_type</span><span class="plain">(</span><span class="identifier">g</span><span class="plain">-</span><span class="element">&gt;substitute_at</span><span class="plain">, </span><span class="constant">EVERY_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_subject</span><span class="plain">(</span><span class="identifier">g</span><span class="plain">-</span><span class="element">&gt;substitute_at</span><span class="plain">, </span><span class="identifier">infs_k</span><span class="plain">);</span>
<span class="comment">insert this sentence after the current assembly position:</span>
<span class="identifier">new_sentence</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">assembly_position</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="identifier">assembly_position</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">new_sentence</span><span class="plain">;</span>
<span class="identifier">assembly_position</span><span class="plain"> = </span><span class="identifier">new_sentence</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">ASSEMBLIES</span><span class="plain">,</span>
<span class="string">"Subject $j satisfies generalisation %d (from $j), making sentence:\</span><span class="plain">n</span><span class="string">$T"</span><span class="plain">,</span>
<span class="identifier">infs</span><span class="plain">, </span><span class="identifier">g</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">infs_k</span><span class="plain">, </span><span class="identifier">new_sentence</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Assertions::Assemblies::satisfies_generalisation is used in <a href="#SP12_1">&#167;12.1</a>.</p>
<p class="inwebparagraph"><a id="SP14_1"></a><b>&#167;14.1. </b>The "implicitness count" is a generation count, where the sentences
from the original source text are generation 0, and any sentences created
from those are generation 1, and so on. This should never be more than a
dozen or so, and if it becomes large than we can be pretty sure that the
machinery is in infinite regress, e.g., because each K must contain an
L but each L must contain a K.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_ASSEMBLY_SIZE</span><span class="plain"> 500</span>
</pre>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Throw the infinite regress exception if the current sentence makes too many things</span> <span class="cwebmacronumber">14.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">implicit_recursion_exception</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">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">, </span><span class="constant">implicitness_count_ANNOT</span><span class="plain">) &gt;= </span><span class="constant">MAX_ASSEMBLY_SIZE</span><span class="plain">) {</span>
<span class="identifier">implicit_recursion_exception</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_subject</span><span class="plain">(2, </span><span class="identifier">infs_k</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">max</span><span class="plain"> = </span><span class="constant">MAX_ASSEMBLY_SIZE</span><span class="plain">;</span>
<span class="identifier">Problems::quote_number</span><span class="plain">(3, &amp;</span><span class="identifier">max</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_AssemblyLoop</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"Making a new %2 seems to result in an assembly which can never end, "</span>
<span class="string">"or which at any rate led to some %3 further constructions "</span>
<span class="string">"before I panicked. This problem tends to occur if instructions "</span>
<span class="string">"are given which cause kinds to create each other forever: "</span>
<span class="string">"for instance, 'Every device is on a supporter. Every supporter "</span>
<span class="string">"is in a container. Every container is part of a device.'"</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP14">&#167;14</a>.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="9-rk.html">Back to 'Relation Knowledge'</a></li><li><a href="9-imp.html">Continue with 'Implications'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>