1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 16:44:21 +03:00
inform7/docs/core-module/16-ic.html
2020-04-07 01:06:09 +01:00

626 lines
67 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>16/cmw2</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../compiler.html"><b>compiler tools</b></a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul>
<h2>Compiler Webs</h2>
<ul>
<li><a href="../inbuild/index.html">inbuild</a></li>
<li><a href="../inform7/index.html">inform7</a></li>
<li><a href="../inter/index.html">inter</a></li>
</ul>
<h2>Inbuild Modules</h2>
<ul>
<li><a href="../inbuild-module/index.html">inbuild</a></li>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../syntax-module/index.html">syntax</a></li>
<li><a href="../html-module/index.html">html</a></li>
</ul>
<h2>Inform7 Modules</h2>
<ul>
<li><a href="../core-module/index.html">core</a></li>
<li><a href="../problems-module/index.html">problems</a></li>
<li><a href="../inflections-module/index.html">inflections</a></li>
<li><a href="../linguistics-module/index.html">linguistics</a></li>
<li><a href="../kinds-module/index.html">kinds</a></li>
<li><a href="../if-module/index.html">if</a></li>
<li><a href="../multimedia-module/index.html">multimedia</a></li>
<li><a href="../index-module/index.html">index</a></li>
</ul>
<h2>Inter Modules</h2>
<ul>
<li><a href="../inter-module/index.html">inter</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../codegen-module/index.html">codegen</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '16/ic' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="../compiler.html">Compiler Modules</a></li><li><a href="index.html">core</a></li><li><a href="index.html#16">Chapter 16: Inference and Model</a></li><li><b>Instance Counting</b></li></ul><p class="purpose">A plugin which maintains run-time-accessible linked lists of instances of kinds, in order to speed up loops; and instance counts within kinds, in order to speed up relation storage; and the object-kind hierarchy, in order to speed up run-time checking of the type safety of property usage.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP4">&#167;4. Plugin startup</a></li><li><a href="#SP5">&#167;5. Initialising</a></li><li><a href="#SP6">&#167;6. Computing instance counts</a></li><li><a href="#SP8">&#167;8. Instance sequences</a></li><li><a href="#SP10">&#167;10. Inform 6 representation</a></li><li><a href="#SP14">&#167;14. Memory estimation</a></li><li><a href="#SP15">&#167;15. Loop optimisation</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>Every subject contains a pointer to its own unique copy of the following
structure, but it only has relevance if the subject represents an object:
</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">counting_data</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">property</span><span class="plain"> *</span><span class="identifier">instance_count_prop</span><span class="plain">; </span><span class="comment">the (<code class="display"><span class="extract">I6</span></code> only) IK-Count property for this kind</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">property</span><span class="plain"> *</span><span class="identifier">instance_link_prop</span><span class="plain">; </span><span class="comment">the (<code class="display"><span class="extract">I6</span></code> only) IK-Link property for this kind</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">has_instances</span><span class="plain">; </span><span class="comment">are there any instances of this kind?</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">counting_data</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure counting_data is private to this section.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>In addition to these I6 properties, two for each kind, there's a single
additional property called <code class="display"><span class="extract">vector</span></code> which is needed as run-time storage for
route-finding through relations on objects.
</p>
<pre class="display">
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">P_vector</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">P_KD_Count</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="comment">see below</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Plugin startup. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Counting::start</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">PLUGIN_REGISTER</span><span class="plain">(</span><span class="constant">PLUGIN_NEW_SUBJECT_NOTIFY</span><span class="plain">, </span><span class="functiontext">PL::Counting::counting_new_subject_notify</span><span class="plain">);</span>
<span class="identifier">PLUGIN_REGISTER</span><span class="plain">(</span><span class="constant">PLUGIN_COMPLETE_MODEL</span><span class="plain">, </span><span class="functiontext">PL::Counting::counting_complete_model</span><span class="plain">);</span>
<span class="identifier">PLUGIN_REGISTER</span><span class="plain">(</span><span class="constant">PLUGIN_COMPILE_MODEL_TABLES</span><span class="plain">, </span><span class="functiontext">PL::Counting::counting_compile_model_tables</span><span class="plain">);</span>
<span class="identifier">PLUGIN_REGISTER</span><span class="plain">(</span><span class="constant">PLUGIN_ESTIMATE_PROPERTY_USAGE</span><span class="plain">, </span><span class="functiontext">PL::Counting::counting_estimate_property_usage</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Counting::start is used in 26/pl (<a href="26-pl.html#SP8">&#167;8</a>).</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Initialising. </b>Counting data is actually relevant only for kinds, and remains blank for instances.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Counting::counting_new_subject_notify</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="identifier">CREATE_PF_DATA</span><span class="plain">(</span><span class="identifier">counting</span><span class="plain">, </span><span class="identifier">subj</span><span class="plain">, </span><span class="functiontext">PL::Counting::new_data</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">counting_data</span><span class="plain"> *</span><span class="functiontext">PL::Counting::new_data</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">counting_data</span><span class="plain"> *</span><span class="identifier">cd</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">counting_data</span><span class="plain">);</span>
<span class="identifier">cd</span><span class="plain">-&gt;</span><span class="element">instance_count_prop</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">cd</span><span class="plain">-&gt;</span><span class="element">instance_link_prop</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">cd</span><span class="plain">-&gt;</span><span class="element">has_instances</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">cd</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Counting::counting_new_subject_notify is used in <a href="#SP4">&#167;4</a>.</p>
<p class="endnote">The function PL::Counting::new_data appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Computing instance counts. </b>We're going to store these temporarily in an array which must be allocated
dynamically in memory, and this will make lookups quite fiddly, so we
use the following macro to specify the integer lvalue for the instance
count of instance <code class="display"><span class="extract">I</span></code> within kind <code class="display"><span class="extract">k</span></code>. This depends on both: for example,
the red car might be thing number 17 but vehicle number 2, and will be
door number -1, since it isn't a door. The first instance in a kind is
numbered 0.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">INSTANCE_COUNT</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">)</span>
<span class="identifier">kind_instance_counts</span><span class="plain">[(</span><span class="identifier">I</span><span class="plain">)-&gt;</span><span class="identifier">allocation_id</span><span class="plain">*</span><span class="identifier">max_kind_instance_count</span><span class="plain"> +</span>
<span class="functiontext">Kinds::RunTime::I6_classnumber</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)]</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> *</span><span class="identifier">kind_instance_counts</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">max_kind_instance_count</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Counting::make_instance_counts</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Allocate the instance count array in memory</span> <span class="cwebmacronumber">6.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compute the instance count array</span> <span class="cwebmacronumber">6.2</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Counting::make_instance_counts is used in <a href="#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP6_1"></a><b>&#167;6.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Allocate the instance count array in memory</span> <span class="cwebmacronumber">6.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">max_kind_instance_count</span><span class="plain"> = </span><span class="identifier">NUMBER_CREATED</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain">);</span>
<span class="identifier">kind_instance_counts</span><span class="plain"> =</span>
<span class="identifier">Memory::I7_calloc</span><span class="plain">(</span><span class="identifier">max_kind_instance_count</span><span class="plain">*</span><span class="identifier">max_kind_instance_count</span><span class="plain">, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">int</span><span class="plain">),</span>
<span class="constant">INSTANCE_COUNTING_MREASON</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_2"></a><b>&#167;6.2. </b>The following is quadratic in the number of objects, but this has never been
a problem in practice; the number seldom exceeds a few hundred.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compute the instance count array</span> <span class="cwebmacronumber">6.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::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="identifier">LOOP_OVER_OBJECT_INSTANCES</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">)</span>
<span class="identifier">INSTANCE_COUNT</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">) = -1;</span>
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::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">int</span><span class="plain"> </span><span class="identifier">ix_count</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_INSTANCES</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">)</span>
<span class="identifier">INSTANCE_COUNT</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">) = </span><span class="identifier">ix_count</span><span class="plain">++;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>Instance counts are actually useful to several other plugins, so we provide:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Counting::instance_count</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="identifier">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">kind_instance_counts</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">"instance counts not available"</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">"instance counts available only for objects"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">INSTANCE_COUNT</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Counting::instance_count appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. Instance sequences. </b>At run-time we're going to want to loop through objects in order of their
definition in the I6 code, which is not the same as their creation order in I7.
(This is so that an optimised and an unoptimised loop to perform the same
search will not only iterate through the same set of objects, but in the
same order.)
</p>
<p class="inwebparagraph">The following abstracts the linked list in compilation sequence. Note that
it excludes instances which have been "diverted", which is mainly used
to get rid of the <code class="display"><span class="extract">selfobj</span></code> object in cases where the source text creates
an explicit player.
</p>
<pre class="display">
<span class="reserved">instance</span><span class="plain"> *</span><span class="functiontext">PL::Counting::next_instance_of</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="identifier">kind</span><span class="plain"> *</span><span class="identifier">k</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</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">resuming</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">I</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">I</span><span class="plain"> = </span><span class="constant">FIRST_IN_COMPILATION_SEQUENCE</span><span class="plain">; </span><span class="identifier">resuming</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; }</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">I</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">resuming</span><span class="plain">) </span><span class="identifier">I</span><span class="plain"> = </span><span class="identifier">NEXT_IN_COMPILATION_SEQUENCE</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">);</span>
<span class="identifier">resuming</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">I</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">InferenceSubjects::aliased_but_diverted</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">continue</span><span class="plain">; </span><span class="comment"><code class="display"><span class="extract">selfobj</span></code> may not count</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Instances::of_kind</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">I</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Counting::next_instance_of is used in <a href="#SP9">&#167;9</a>, <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>For compilation purposes, it's useful to express this as a specification:
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">PL::Counting::next_instance_of_as_value</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="identifier">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">next</span><span class="plain"> = </span><span class="functiontext">PL::Counting::next_instance_of</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">next</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">next</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Rvalues::new_nothing_object_constant</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Counting::next_instance_of_as_value is used in <a href="#SP12_3_3">&#167;12.3.3</a>.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. Inform 6 representation. </b>The main purpose of this plugin is to trade memory for speed at run-time.
Inform source text is rich in implied searches through kinds ("if a red
door is open, ...") and we need these to be as fast as possible; iterating
through all objects would be dangerously slow, so we need a way at run-time
to iterate through the instances of a single kind (in this example, doors).
</p>
<p class="inwebparagraph">For each kind we will store a linked list of instances. The first instance
need only be defined as a constant, and need not be stored in a memory word,
since Inform always compiles code which knows which kind it's looping over.
</p>
<pre class="display">
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="functiontext">PL::Counting::first_instance</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">kind_constructor</span><span class="plain"> *</span><span class="identifier">con</span><span class="plain"> = </span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">iname</span><span class="plain"> = </span><span class="identifier">Kinds::Constructors::first_instance_iname</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">iname</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">iname</span><span class="plain"> = </span><span class="functiontext">Hierarchy::derive_iname_in</span><span class="plain">(</span><span class="constant">FIRST_INSTANCE_HL</span><span class="plain">, </span><span class="functiontext">Kinds::RunTime::iname</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">), </span><span class="identifier">Kinds::Behaviour::package</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">));</span>
<span class="identifier">Kinds::Constructors::set_first_instance_iname</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">, </span><span class="identifier">iname</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">iname</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="functiontext">PL::Counting::next_instance</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">kind_constructor</span><span class="plain"> *</span><span class="identifier">con</span><span class="plain"> = </span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">iname</span><span class="plain"> = </span><span class="identifier">Kinds::Constructors::next_instance_iname</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">iname</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">iname</span><span class="plain"> = </span><span class="functiontext">Hierarchy::derive_iname_in</span><span class="plain">(</span><span class="constant">NEXT_INSTANCE_HL</span><span class="plain">, </span><span class="functiontext">Kinds::RunTime::iname</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">), </span><span class="identifier">Kinds::Behaviour::package</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">));</span>
<span class="identifier">Kinds::Constructors::set_next_instance_iname</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">, </span><span class="identifier">iname</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">iname</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="functiontext">PL::Counting::instance_count_iname</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="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="functiontext">Kinds::RunTime::I6_classnumber</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">N</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="constant">COUNT_INSTANCE_1_HL</span><span class="plain">, </span><span class="identifier">Kinds::Behaviour::package</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">N</span><span class="plain"> == </span><span class="constant">2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="constant">COUNT_INSTANCE_2_HL</span><span class="plain">, </span><span class="identifier">Kinds::Behaviour::package</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">N</span><span class="plain"> == </span><span class="constant">3</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="constant">COUNT_INSTANCE_3_HL</span><span class="plain">, </span><span class="identifier">Kinds::Behaviour::package</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">N</span><span class="plain"> == </span><span class="constant">4</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="constant">COUNT_INSTANCE_4_HL</span><span class="plain">, </span><span class="identifier">Kinds::Behaviour::package</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">N</span><span class="plain"> == </span><span class="constant">5</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="constant">COUNT_INSTANCE_5_HL</span><span class="plain">, </span><span class="identifier">Kinds::Behaviour::package</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">N</span><span class="plain"> == </span><span class="constant">6</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="constant">COUNT_INSTANCE_6_HL</span><span class="plain">, </span><span class="identifier">Kinds::Behaviour::package</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">N</span><span class="plain"> == </span><span class="constant">7</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="constant">COUNT_INSTANCE_7_HL</span><span class="plain">, </span><span class="identifier">Kinds::Behaviour::package</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">N</span><span class="plain"> == </span><span class="constant">8</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="constant">COUNT_INSTANCE_8_HL</span><span class="plain">, </span><span class="identifier">Kinds::Behaviour::package</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">N</span><span class="plain"> == </span><span class="constant">9</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="constant">COUNT_INSTANCE_9_HL</span><span class="plain">, </span><span class="identifier">Kinds::Behaviour::package</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">N</span><span class="plain"> == </span><span class="constant">10</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="constant">COUNT_INSTANCE_10_HL</span><span class="plain">, </span><span class="identifier">Kinds::Behaviour::package</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">Hierarchy::derive_iname_in</span><span class="plain">(</span><span class="constant">COUNT_INSTANCE_HL</span><span class="plain">, </span><span class="functiontext">Kinds::RunTime::iname</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">), </span><span class="identifier">Kinds::Behaviour::package</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Counting::counting_compile_model_tables</span><span class="plain">(</span><span class="reserved">void</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">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::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="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">iname</span><span class="plain"> = </span><span class="functiontext">PL::Counting::first_instance</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">next</span><span class="plain"> = </span><span class="functiontext">PL::Counting::next_instance_of</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">next</span><span class="plain">) {</span>
<span class="functiontext">Emit::named_iname_constant</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">, </span><span class="functiontext">Instances::emitted_iname</span><span class="plain">(</span><span class="identifier">next</span><span class="plain">));</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="functiontext">Emit::named_iname_constant</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">NULL</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">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Counting::first_instance is used in <a href="#SP15">&#167;15</a>.</p>
<p class="endnote">The function PL::Counting::next_instance is used in <a href="#SP12_2">&#167;12.2</a>, <a href="#SP15">&#167;15</a>.</p>
<p class="endnote">The function PL::Counting::instance_count_iname is used in <a href="#SP12_2">&#167;12.2</a>.</p>
<p class="endnote">The function PL::Counting::counting_compile_model_tables is used in <a href="#SP4">&#167;4</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>Counting kinds of object, not very quickly:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Counting::kind_of_object_count</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="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">IK</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">IK</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">IK</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">)) {</span>
<span class="identifier">c</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">IK</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">c</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Counting::kind_of_object_count is used in <a href="#SP12_3_1">&#167;12.3.1</a>.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>So now the compiler can define the start of a linked list of instances
for a given kind, but how can it define the inductive step? The answer is
that every instance of kind number 4 (say) provides an I6 property <code class="display"><span class="extract">IK4_Link</span></code>
whose value is the next instance, or else <code class="display"><span class="extract">nothing</span></code> if it's the last.
</p>
<p class="inwebparagraph">A further property, <code class="display"><span class="extract">IK4_Count</span></code>, holds the instance count; this is used for
efficient access to various-to-various relation storage at run-time. If we
have a relation of various doors to various rooms, say, we want to store a
bitmap only D* R in size, but then to access this quickly given a
specific door and room, we need to convert these quickly to their indices;
this is what <code class="display"><span class="extract">IK4_Count</span></code> does.
</p>
<p class="inwebparagraph">We create these properties, and assert these property values, during stage IV
of model completion:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Counting::counting_complete_model</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">stage</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stage</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Create and assert zero values of the vector property</span> <span class="cwebmacronumber">12.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stage</span><span class="plain"> == </span><span class="constant">4</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Create the two instance properties for each kind of object</span> <span class="cwebmacronumber">12.2</span>&gt;<span class="plain">;</span>
<span class="functiontext">PL::Counting::make_instance_counts</span><span class="plain">();</span>
&lt;<span class="cwebmacro">Assert values of the two instance properties for each instance</span> <span class="cwebmacronumber">12.3</span>&gt;<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 PL::Counting::counting_complete_model is used in <a href="#SP4">&#167;4</a>.</p>
<p class="inwebparagraph"><a id="SP12_1"></a><b>&#167;12.1. </b>The <code class="display"><span class="extract">vector</span></code> property exists only at the I6 level, and provides workspace
for the relation-route-finding code at run time.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Create and assert zero values of the vector property</span> <span class="cwebmacronumber">12.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">P_vector</span><span class="plain"> = </span><span class="functiontext">Properties::Valued::new_nameless</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"vector"</span><span class="plain">, </span><span class="identifier">K_number</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">zero</span><span class="plain"> = </span><span class="functiontext">Rvalues::from_int</span><span class="plain">(0, </span><span class="identifier">EMPTY_WORDING</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="identifier">LOOP_OVER_OBJECT_INSTANCES</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">)</span>
<span class="functiontext">Properties::Valued::assert</span><span class="plain">(</span><span class="identifier">P_vector</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="identifier">zero</span><span class="plain">, </span><span class="identifier">CERTAIN_CE</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_2"></a><b>&#167;12.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Create the two instance properties for each kind of object</span> <span class="cwebmacronumber">12.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::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">inference_subject</span><span class="plain"> *</span><span class="identifier">subj</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="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">count_iname</span><span class="plain"> = </span><span class="functiontext">PL::Counting::instance_count_iname</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="identifier">PF_S</span><span class="plain">(</span><span class="identifier">counting</span><span class="plain">, </span><span class="identifier">subj</span><span class="plain">)-&gt;</span><span class="element">instance_count_prop</span><span class="plain"> =</span>
<span class="functiontext">Properties::Valued::new_nameless_using</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">Kinds::Behaviour::package</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">), </span><span class="identifier">count_iname</span><span class="plain">);</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">next_iname</span><span class="plain"> = </span><span class="functiontext">PL::Counting::next_instance</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="identifier">PF_S</span><span class="plain">(</span><span class="identifier">counting</span><span class="plain">, </span><span class="identifier">subj</span><span class="plain">)-&gt;</span><span class="element">instance_link_prop</span><span class="plain"> =</span>
<span class="functiontext">Properties::Valued::new_nameless_using</span><span class="plain">(</span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">Kinds::Behaviour::package</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">), </span><span class="identifier">next_iname</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">P_KD_Count</span><span class="plain"> = </span><span class="functiontext">Properties::Valued::new_nameless</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"KD_Count"</span><span class="plain">, </span><span class="identifier">K_number</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_3"></a><b>&#167;12.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Assert values of the two instance properties for each instance</span> <span class="cwebmacronumber">12.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_OBJECT_INSTANCES</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Fill in the special IK0-Count property</span> <span class="cwebmacronumber">12.3.1</span>&gt;<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">for</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="functiontext">Instances::to_kind</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="identifier">infs</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">kind</span><span class="plain"> *</span><span class="identifier">K</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="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">inference_subject</span><span class="plain"> *</span><span class="identifier">subj</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="identifier">PF_S</span><span class="plain">(</span><span class="identifier">counting</span><span class="plain">, </span><span class="identifier">subj</span><span class="plain">)-&gt;</span><span class="element">has_instances</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Fill in this IK-Count property</span> <span class="cwebmacronumber">12.3.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Fill in this IK-Link property</span> <span class="cwebmacronumber">12.3.3</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="#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP12_3_1"></a><b>&#167;12.3.1. </b>As noted above, <code class="display"><span class="extract">KD_Count</span></code> is a special case. This looks as if it should be
the instance count of "kind" itself, but that would be useless, since no
instance object can ever have kind "kind" &mdash; instances aren't kinds.
</p>
<p class="inwebparagraph">Instead it holds the kind number of its own (direct) kind. For example, if the
instance object is the red door, its <code class="display"><span class="extract">KD_Count</span></code> value will be 4, meaning that
its kind is kind number 4, which according to the <code class="display"><span class="extract">KindHierarchy</span></code> array is
<code class="display"><span class="extract">K4_door</span></code>. Again, this is needed for rapid checking at run-time that property
usage is legal.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Fill in the special IK0-Count property</span> <span class="cwebmacronumber">12.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ic</span><span class="plain"> = </span><span class="functiontext">PL::Counting::kind_of_object_count</span><span class="plain">(</span><span class="functiontext">Instances::to_kind</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">));</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">the_count</span><span class="plain"> = </span><span class="functiontext">Rvalues::from_int</span><span class="plain">(</span><span class="identifier">ic</span><span class="plain">, </span><span class="identifier">EMPTY_WORDING</span><span class="plain">);</span>
<span class="functiontext">Properties::Valued::assert</span><span class="plain">(</span>
<span class="identifier">P_KD_Count</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="identifier">the_count</span><span class="plain">, </span><span class="identifier">CERTAIN_CE</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12_3">&#167;12.3</a>.</p>
<p class="inwebparagraph"><a id="SP12_3_2"></a><b>&#167;12.3.2. </b>And otherwise, for every kind that the instance belongs to (directly or
indirectly) it gets the relevant instance count as a property value. For
example, the red door might have <code class="display"><span class="extract">IK4_Count</span></code> set to 3 &mdash; it's door number 3,
let's suppose &mdash; and <code class="display"><span class="extract">IK2_Count</span></code> set to 19 &mdash; it's thing number 19. It doesn't
have an <code class="display"><span class="extract">IK7_Count</span></code> property at all, since it isn't a backdrop (kind number 7),
and so on for all other kinds.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Fill in this IK-Count property</span> <span class="cwebmacronumber">12.3.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ic</span><span class="plain"> = </span><span class="identifier">INSTANCE_COUNT</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">the_count</span><span class="plain"> = </span><span class="functiontext">Rvalues::from_int</span><span class="plain">(</span><span class="identifier">ic</span><span class="plain">, </span><span class="identifier">EMPTY_WORDING</span><span class="plain">);</span>
<span class="functiontext">Properties::Valued::assert</span><span class="plain">(</span>
<span class="identifier">PF_S</span><span class="plain">(</span><span class="identifier">counting</span><span class="plain">, </span><span class="identifier">subj</span><span class="plain">)-&gt;</span><span class="element">instance_count_prop</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="identifier">the_count</span><span class="plain">, </span><span class="identifier">CERTAIN_CE</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12_3">&#167;12.3</a>.</p>
<p class="inwebparagraph"><a id="SP12_3_3"></a><b>&#167;12.3.3. </b>The IK-Link property is never set for kind 0, so there's no special case. It
records the next instance in compilation order:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Fill in this IK-Link property</span> <span class="cwebmacronumber">12.3.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Properties::Valued::assert</span><span class="plain">(</span>
<span class="identifier">PF_S</span><span class="plain">(</span><span class="identifier">counting</span><span class="plain">, </span><span class="identifier">subj</span><span class="plain">)-&gt;</span><span class="element">instance_link_prop</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="functiontext">PL::Counting::next_instance_of_as_value</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">), </span><span class="identifier">CERTAIN_CE</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12_3">&#167;12.3</a>.</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b></p>
<pre class="display">
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="functiontext">PL::Counting::instance_count_property_symbol</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="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">inference_subject</span><span class="plain"> *</span><span class="identifier">subj</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="reserved">property</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain"> = </span><span class="identifier">PF_S</span><span class="plain">(</span><span class="identifier">counting</span><span class="plain">, </span><span class="identifier">subj</span><span class="plain">)-&gt;</span><span class="element">instance_count_prop</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">P</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Properties::iname</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Counting::instance_count_property_symbol is used in 6/rlt (<a href="6-rlt.html#SP20_2">&#167;20.2</a>).</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. Memory estimation. </b>We're going to need about 4 words of extra memory to store the two properties
per instance per kind, so:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Counting::counting_estimate_property_usage</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="reserved">int</span><span class="plain"> *</span><span class="identifier">words_used</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">for</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::narrowest_broader_subject</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="identifier">infs</span><span class="plain">; </span><span class="identifier">infs</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">kind</span><span class="plain"> *</span><span class="identifier">k2</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="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::lt</span><span class="plain">(</span><span class="identifier">k2</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">))</span>
<span class="plain">*</span><span class="identifier">words_used</span><span class="plain"> += </span><span class="constant">4</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 PL::Counting::counting_estimate_property_usage is used in <a href="#SP4">&#167;4</a>.</p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. Loop optimisation. </b>Lastly, then, the coup de gr\^ace: here's where we define loop schemas to
perform loops through kinds quickly at run-time. We start from the First
constants, and use the Link constants to progress; we stop at <code class="display"><span class="extract">nothing</span></code>.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Counting::optimise_loop</span><span class="plain">(</span><span class="reserved">i6_schema</span><span class="plain"> *</span><span class="identifier">sch</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="reserved">if</span><span class="plain"> (</span><span class="functiontext">Plugins::Manage::plugged_in</span><span class="plain">(</span><span class="identifier">counting_plugin</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</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="functiontext">Kinds::Knowledge::as_subject</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">PF_S</span><span class="plain">(</span><span class="identifier">counting</span><span class="plain">, </span><span class="identifier">subj</span><span class="plain">)-&gt;</span><span class="element">has_instances</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="comment">(to avoid writing misleading code)</span>
<span class="functiontext">Calculus::Schemas::modify</span><span class="plain">(</span><span class="identifier">sch</span><span class="plain">,</span>
<span class="string">"for (*1=nothing: false: )"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">first_iname</span><span class="plain"> = </span><span class="functiontext">PL::Counting::first_instance</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">next_iname</span><span class="plain"> = </span><span class="functiontext">PL::Counting::next_instance</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="functiontext">Calculus::Schemas::modify</span><span class="plain">(</span><span class="identifier">sch</span><span class="plain">, </span><span class="string">"for (*1=%n: *1: *1=*1.%n)"</span><span class="plain">, </span><span class="identifier">first_iname</span><span class="plain">, </span><span class="identifier">next_iname</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Counting::optimise_loop is used in 12/dtd (<a href="12-dtd.html#SP24">&#167;24</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="16-cmw2.html">Back to 'Compile Model World'</a></li><li><i>(This section ends Chapter 16: Inference and Model.)</i></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>