1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-03 07:24:58 +03:00
inform7/docs/core-module/16-cmw.html

315 lines
26 KiB
HTML
Raw Normal View History

2019-03-17 14:40:57 +02:00
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>16/in</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/cmw' 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>Complete Model World</b></li></ul><p class="purpose">Once the assertions have all been read and reduced to inferences, and all the creations have been made, we take stock; sometimes we spot inconsistencies, sometimes we make deductions, and we try to complete our picture of the model world.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Stages II to IV</a></li><li><a href="#SP2">&#167;2. Stage V</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Stages II to IV. </b>The process of using existing facts to infer new ones is vulnerable
to timing bugs, so we organise the "making" process into five numbered
stages, given the Roman numerals I to V. Much of the work is done by plugins,
which can take a hand at any or all of the stages, using their contextual
knowledge to fill in missing properties.
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(I) Deducing the kind of any object whose kind is not known. Because this
can result in a change of kind, which can result in further creations by
assembly sentences like "A handle is part of every door", Stage I takes
place at the end of traverse 2 of the source text and, uniquely, gets the
opportunity to add fresh sentences to the source &mdash; thus extending the
traverse. By the end of Stage I, all kinds are fixed.
</li></ul>
<ul class="items"><li>(II) Stages II and III are for adding further properties or relationships,
which aren't explicit in the source text but which plugins can add on the
basis of contextual understanding. (Two stages are provided here to avoid
timing issues where one plugin has to act earlier than another.)
</li></ul>
<ul class="items"><li>(III) See (II). If a plugin is going to change the compilation order of
the objects (as the spatial-model plugin does), it must do so during
Stage III.
</li></ul>
<ul class="items"><li>(IV) A stage for consistency checks or to store away useful data, but where
nothing in the model may be changed &mdash; no properties or relationships
may be added. (Except that the instance-counting plugin is allowed to
add the linked-lists-of-instances properties, used to optimise loops
at run-time; they aren't visible at the I7 level so aren't properly
part of the model world.)
</li></ul>
<ul class="items"><li>(V) A final chance to add properties which will assist the run-time
implementation of, for instance, the command grammar, but again aren't
really part of the model world. (This can't be done earlier since the
command grammar isn't parsed until after <code class="display"><span class="extract">World::complete</span></code>; and we
aren't allowed to add I7-accessible properties.)
</li></ul>
<p class="inwebparagraph">The following routine, then, carries out stages II, III and IV.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::complete</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Stages II and III of the completion process</span> <span class="cwebmacronumber">1.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Stage IV of the completion process</span> <span class="cwebmacronumber">1.2</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
2020-03-11 02:21:09 +02:00
<p class="endnote">The function World::complete is used in 1/htc (<a href="1-htc.html#SP2_5">&#167;2.5</a>).</p>
2019-03-17 14:40:57 +02:00
<p class="inwebparagraph"><a id="SP1_1"></a><b>&#167;1.1. </b>The model world is a broth with many cooks. On the one hand, we have the
various different INFSs, with their different needs &mdash; a various-to-various
relation, a global variable, and so on &mdash; and on the other hand we also
have the plugins, each of which takes its own global view of the situation.
We give everyone a turn.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Stages II and III of the completion process</span> <span class="cwebmacronumber">1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<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">InferenceSubjects::complete_model</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="functiontext">Properties::Appearance::reallocate</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</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">Assertions::Implications::consider_all</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="functiontext">Plugins::Call::complete_model</span><span class="plain">(2);</span>
<span class="functiontext">Plugins::Call::complete_model</span><span class="plain">(3);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP1_2"></a><b>&#167;1.2. </b>Checking what we have, then. Once again each INFS is given an opportunity
to check itself, and then the plugins have a turn.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Stage IV of the completion process</span> <span class="cwebmacronumber">1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<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">InferenceSubjects::check_model</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Check that properties are permitted</span> <span class="cwebmacronumber">1.2.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Check that properties are not contradictory</span> <span class="cwebmacronumber">1.2.2</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="functiontext">Plugins::Call::complete_model</span><span class="plain">(4);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP1_2_1"></a><b>&#167;1.2.1. </b>These two checks may seem a little odd. After all, we've been throwing out
impossible inferences with problem messages all along, while reading the
source text. Why not perform these checks then, too?
</p>
<p class="inwebparagraph">The answer is that both depend not only on the subject of the inferences
made, but also on what that subject inherits from. Suppose we are told:
</p>
<blockquote>
<p>The cup is in the Yellow Cupboard. The Cupboard is lighted.</p>
</blockquote>
<p class="inwebparagraph">When we make the "lighted" inference, we know for certain what subject
it's about &mdash; the Yellow Cupboard &mdash; but not where this lives in the
inference-subject hierarchy, because that depends on the kind of the
Cupboard. Is it a room, or a container? We don't yet know (and won't until
Stage I of model-completion), so we aren't in a position to judge whether
or not it's permitted to have the property "lighted". This is why the
check is postponed until after Stage I, and it seems natural to perform
it here in Stage IV, so that we also catch any accidents due to bugs
in plugins which add inconsistent properties.
</p>
<p class="inwebparagraph">A nameless property added in Stages II and III does not need permission.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Check that properties are permitted</span> <span class="cwebmacronumber">1.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">inf</span><span class="plain">;</span>
<span class="identifier">KNOWLEDGE_LOOP</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="constant">PROPERTY_INF</span><span class="plain">) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_property</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">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">-</span><span class="element">&gt;name</span><span class="plain">))</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">World::Permissions::find</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="functiontext">Problems::Issue::inference_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_PropertyNotPermitted</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="string">"is not allowed to exist"</span><span class="plain">,</span>
<span class="string">"because you haven't said it is. What properties something can "</span>
<span class="string">"have depends on what kind of thing it is: see the Index for "</span>
<span class="string">"details."</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_2">&#167;1.2</a>.</p>
<p class="inwebparagraph"><a id="SP1_2_2"></a><b>&#167;1.2.2. </b>The following contradiction checks do not apply to properties added
in Stages II and III, since those are often I6 hacks added for run-time
convenience, and don't have to follow the I7 rules.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Check that properties are not contradictory</span> <span class="cwebmacronumber">1.2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">narrow</span><span class="plain">;</span>
<span class="identifier">KNOWLEDGE_LOOP</span><span class="plain">(</span><span class="identifier">narrow</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="constant">PROPERTY_INF</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">World::Inferences::added_in_construction</span><span class="plain">(</span><span class="identifier">narrow</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_property</span><span class="plain">(</span><span class="identifier">narrow</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">sign</span><span class="plain"> = 1;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">World::Inferences::get_certainty</span><span class="plain">(</span><span class="identifier">narrow</span><span class="plain">) &lt; 0) </span><span class="identifier">sign</span><span class="plain"> = -1;</span>
&lt;<span class="cwebmacro">Look for clashes concerning this property from wider inferences</span> <span class="cwebmacronumber">1.2.2.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Properties::is_either_or</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">)) &amp;&amp; (</span><span class="functiontext">Properties::EitherOr::get_negation</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">))) {</span>
<span class="identifier">prn</span><span class="plain"> = </span><span class="functiontext">Properties::EitherOr::get_negation</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">);</span>
<span class="identifier">sign</span><span class="plain"> = -</span><span class="identifier">sign</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Look for clashes concerning this property from wider inferences</span> <span class="cwebmacronumber">1.2.2.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_2">&#167;1.2</a>.</p>
<p class="inwebparagraph"><a id="SP1_2_2_1"></a><b>&#167;1.2.2.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Look for clashes concerning this property from wider inferences</span> <span class="cwebmacronumber">1.2.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">boss</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="reserved">while</span><span class="plain"> (</span><span class="identifier">boss</span><span class="plain">) {</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">wide</span><span class="plain">;</span>
<span class="identifier">KNOWLEDGE_LOOP</span><span class="plain">(</span><span class="identifier">wide</span><span class="plain">, </span><span class="identifier">boss</span><span class="plain">, </span><span class="constant">PROPERTY_INF</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">World::Inferences::added_in_construction</span><span class="plain">(</span><span class="identifier">wide</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prn</span><span class="plain"> == </span><span class="functiontext">World::Inferences::get_property</span><span class="plain">(</span><span class="identifier">wide</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Check that these differently scoped inferences do not clash</span> <span class="cwebmacronumber">1.2.2.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">boss</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::narrowest_broader_subject</span><span class="plain">(</span><span class="identifier">boss</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_2_2">&#167;1.2.2</a> (twice).</p>
<p class="inwebparagraph"><a id="SP1_2_2_1_1"></a><b>&#167;1.2.2.1.1. </b>It's never a problem when a vague fact about something general is contradicted
by a fact about something specific; the problem comes with something like this:
</p>
<blockquote>
<p>A door is always open. The Marble Portal is a closed door.</p>
</blockquote>
<p class="inwebparagraph">Here the "wide" property inference, for the "door" kind, is <code class="display"><span class="extract">CERTAIN_CE</span></code>
rather than <code class="display"><span class="extract">LIKELY_CE</span></code>, and so we can't allow the "narrow" inference,
about the Portal, to stand.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Check that these differently scoped inferences do not clash</span> <span class="cwebmacronumber">1.2.2.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">abcw</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_certainty</span><span class="plain">(</span><span class="identifier">wide</span><span class="plain">); </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">abcw</span><span class="plain"> &lt; 0) </span><span class="identifier">abcw</span><span class="plain"> = -</span><span class="identifier">abcw</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">abcw</span><span class="plain"> == </span><span class="identifier">CERTAIN_CE</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">clash</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">wide_sign</span><span class="plain"> = 1; </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">World::Inferences::get_certainty</span><span class="plain">(</span><span class="identifier">wide</span><span class="plain">) &lt; 0) </span><span class="identifier">wide_sign</span><span class="plain"> = -1;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::is_either_or</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">narrow_val</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_property_value</span><span class="plain">(</span><span class="identifier">narrow</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">wide_val</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_property_value</span><span class="plain">(</span><span class="identifier">wide</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Rvalues::compare_CONSTANT</span><span class="plain">(</span><span class="identifier">narrow_val</span><span class="plain">, </span><span class="identifier">wide_val</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">"Clash of $P and $P\</span><span class="plain">n</span><span class="string"> $I\</span><span class="plain">n</span><span class="string"> $I\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">narrow_val</span><span class="plain">, </span><span class="identifier">wide_val</span><span class="plain">, </span><span class="identifier">narrow</span><span class="plain">, </span><span class="identifier">wide</span><span class="plain">);</span>
<span class="identifier">clash</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sign</span><span class="plain"> != </span><span class="identifier">wide_sign</span><span class="plain">) </span><span class="identifier">clash</span><span class="plain"> = (</span><span class="identifier">clash</span><span class="plain">)?</span><span class="identifier">FALSE</span><span class="plain">:</span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">clash</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">abcn</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_certainty</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">abcn</span><span class="plain"> &lt; 0) </span><span class="identifier">abcn</span><span class="plain"> = -</span><span class="identifier">abcn</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">abcn</span><span class="plain"> == </span><span class="identifier">CERTAIN_CE</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Issue a problem message for clash with wider inference</span> <span class="cwebmacronumber">1.2.2.1.1.1</span>&gt;
<span class="reserved">else</span>
<span class="functiontext">World::Inferences::set_certainty</span><span class="plain">(</span><span class="identifier">narrow</span><span class="plain">, </span><span class="identifier">IMPOSSIBLE_CE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_2_2_1">&#167;1.2.2.1</a>.</p>
<p class="inwebparagraph"><a id="SP1_2_2_1_1_1"></a><b>&#167;1.2.2.1.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem message for clash with wider inference</span> <span class="cwebmacronumber">1.2.2.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Checking infs $j compatible with infs $j for property $Y:\</span><span class="plain">n</span><span class="string"> $I\</span><span class="plain">n</span><span class="string"> $I\</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">boss</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">, </span><span class="identifier">narrow</span><span class="plain">, </span><span class="identifier">wide</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::infs_contradiction_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_InstanceContradiction</span><span class="plain">),</span>
<span class="functiontext">World::Inferences::where_inferred</span><span class="plain">(</span><span class="identifier">narrow</span><span class="plain">), </span><span class="functiontext">World::Inferences::where_inferred</span><span class="plain">(</span><span class="identifier">wide</span><span class="plain">), </span><span class="identifier">infs</span><span class="plain">,</span>
<span class="string">"therefore has to have two contradictory states of the same property at once"</span><span class="plain">,</span>
<span class="string">"which is impossible. When a kind's definition says that something is 'always' "</span>
<span class="string">"true, there is no way to override that for particular things of the kind."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_2_2_1_1">&#167;1.2.2.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. Stage V. </b>See above. This is for the use of plugins only.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::complete_additions</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Plugins::Call::complete_model</span><span class="plain">(5);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
2020-03-11 02:21:09 +02:00
<p class="endnote">The function World::complete_additions is used in 1/htc (<a href="1-htc.html#SP2_6">&#167;2.6</a>).</p>
2019-03-17 14:40:57 +02:00
<hr class="tocbar">
<ul class="toc"><li><a href="16-in.html">Back to 'Inferences'</a></li><li><a href="16-cmw2.html">Continue with 'Compile Model World'</a></li></ul><hr class="tocbar">
2019-04-22 17:42:10 +03:00
<!--End of weave-->
2019-03-17 14:40:57 +02:00
</body>
</html>