1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/core-module/15-epv.html
2019-08-31 13:56:36 +01:00

417 lines
46 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>15/pov</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 '15/epv' 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#15">Chapter 15: Properties</a></li><li><b>Emit Property Values</b></li></ul><p class="purpose">To feed the hierarchy of instances and their property values into Inter.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Emitting the property values</a></li><li><a href="#SP3">&#167;3. Attribute allocation</a></li><li><a href="#SP4">&#167;4. Rapid run-time testing</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Emitting the property values. </b>The following routine is called on every kind which can have properties,
and also on every individual instance of those kinds. Superkinds are called
before subkinds, and kinds are called before their instances, but we don't
manage that here.
</p>
<pre class="display">
<span class="identifier">inter_t</span><span class="plain"> </span><span class="identifier">cs_sequence_counter</span><span class="plain"> = 0;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Properties::Emit::emit_subject</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">LOGIF</span><span class="plain">(</span><span class="identifier">OBJECT_COMPILATION</span><span class="plain">, </span><span class="string">"Compiling object definition for $j\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">subj</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">subj</span><span class="plain">);</span>
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::as_instance</span><span class="plain">(</span><span class="identifier">subj</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">words_used</span><span class="plain"> = 0;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">) </span><span class="functiontext">Plugins::Call::estimate_property_usage</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, &amp;</span><span class="identifier">words_used</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">NULL</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">iname</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="reserved">else</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">iname</span><span class="plain"> = </span><span class="functiontext">Instances::emitted_iname</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad subject for emission"</span><span class="plain">);</span>
<span class="identifier">Produce::annotate_i</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">, </span><span class="identifier">DECLARATION_ORDER_IANN</span><span class="plain">, </span><span class="identifier">cs_sequence_counter</span><span class="plain">++);</span>
&lt;<span class="cwebmacro">Compile the actual object</span> <span class="cwebmacronumber">1.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="functiontext">World::Compile::set_rough_memory_usage</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">words_used</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">nw</span><span class="plain"> = 0;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain"> = </span><span class="identifier">subj</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">K2</span><span class="plain">) </span><span class="identifier">nw</span><span class="plain"> += </span><span class="functiontext">World::Compile::get_rough_memory_usage</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">nw</span><span class="plain"> += 16;</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">KW</span><span class="plain"> = </span><span class="identifier">Kinds::Behaviour::get_name</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="functiontext">VirtualMachines::note_usage</span><span class="plain">(</span><span class="string">"object"</span><span class="plain">, </span><span class="identifier">KW</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">nw</span><span class="plain">, 0, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">OBJECT_COMPILATION</span><span class="plain">, </span><span class="string">"Rough size estimate: %d words\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">nw</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">OBJECT_COMPILATION</span><span class="plain">, </span><span class="string">"Compilation of $j complete\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">subj</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Properties::Emit::emit_subject is used in 5/ins (<a href="5-ins.html#SP34">&#167;34</a>), 13/kak (<a href="13-kak.html#SP5">&#167;5</a>).</p>
<p class="inwebparagraph"><a id="SP1_1"></a><b>&#167;1.1. </b>We need to compile <code class="display"><span class="extract">with</span></code> or <code class="display"><span class="extract">has</span></code> clauses for all the properties our
object will have, and we need to be careful not to compile them more than
once, even if there's more than one permission recorded for a given
property; so we do this with a "traverse" of the properties, in which
each one is marked when visited.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile the actual object</span> <span class="cwebmacronumber">1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
&lt;<span class="cwebmacro">Annotate with the spatial depth</span> <span class="cwebmacronumber">1.1.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">I</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::le</span><span class="plain">(</span><span class="functiontext">Instances::to_kind</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">), </span><span class="identifier">K_object</span><span class="plain">))) </span><span class="identifier">words_used</span><span class="plain">++;</span>
&lt;<span class="cwebmacro">Append any inclusions the source text requested</span> <span class="cwebmacronumber">1.1.2</span>&gt;<span class="plain">;</span>
<span class="functiontext">Properties::begin_traverse</span><span class="plain">();</span>
&lt;<span class="cwebmacro">Emit inferred object properties</span> <span class="cwebmacronumber">1.1.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Emit permitted but unspecified object properties</span> <span class="cwebmacronumber">1.1.4</span>&gt;<span class="plain">;</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_1_1"></a><b>&#167;1.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Annotate with the spatial depth</span> <span class="cwebmacronumber">1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">I</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::le</span><span class="plain">(</span><span class="functiontext">Instances::to_kind</span><span class="plain">(</span><span class="identifier">I</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">AC</span><span class="plain"> = </span><span class="identifier">PL::Spatial::get_definition_depth</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">AC</span><span class="plain"> &gt; 0) </span><span class="identifier">Produce::annotate_i</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">, </span><span class="identifier">ARROW_COUNT_IANN</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">AC</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_1">&#167;1.1</a>.</p>
<p class="inwebparagraph"><a id="SP1_1_2"></a><b>&#167;1.1.2. </b>This is an ugly business, but the I7 language supports the injection of raw
I6 code into object bodies, and the I6 template does make use of this a little.
In an ideal world we would revoke this ability.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Append any inclusions the source text requested</span> <span class="cwebmacronumber">1.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">incl</span><span class="plain">);</span>
<span class="functiontext">Config::Inclusions::compile_inclusions_for_subject</span><span class="plain">(</span><span class="identifier">incl</span><span class="plain">, </span><span class="identifier">subj</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">incl</span><span class="plain">) &gt; 0) </span><span class="functiontext">Emit::append</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">, </span><span class="identifier">incl</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">incl</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_1">&#167;1.1</a>.</p>
<p class="inwebparagraph"><a id="SP1_1_3"></a><b>&#167;1.1.3. </b>Now, here goes with the properties. We first compile clauses for those we
know about, then for any other properties which are permitted but apparently
not set. Note that we only look through knowledge and permissions associated
with <code class="display"><span class="extract">subj</span></code> itself; we've no need to look at those for its kind (and its kind's
kind, and so on) because the Inform 6 compiler automatically inherits those
through the <code class="display"><span class="extract">Class</span></code> hierarchy of I6 objects &mdash; this is why we have made
the class hierarchy at I6 level exactly match the kind hierarchy at I7 level.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Emit inferred object properties</span> <span class="cwebmacronumber">1.1.3</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">subj</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="identifier">current_sentence</span><span class="plain"> = </span><span class="functiontext">World::Inferences::where_inferred</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">OBJECT_COMPILATION</span><span class="plain">, </span><span class="string">"Compiling property $Y\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">);</span>
<span class="identifier">words_used</span><span class="plain"> += </span><span class="functiontext">Properties::Emit::emit_propertyvalue</span><span class="plain">(</span><span class="identifier">subj</span><span class="plain">, </span><span class="identifier">prn</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_1">&#167;1.1</a>.</p>
<p class="inwebparagraph"><a id="SP1_1_4"></a><b>&#167;1.1.4. </b>We now wander through the permitted properties, even those which we have
no actual knowledge about.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Emit permitted but unspecified object properties</span> <span class="cwebmacronumber">1.1.4</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="reserved">for</span><span class="plain"> (</span><span class="identifier">infs</span><span class="plain"> = </span><span class="identifier">subj</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="reserved">property_permission</span><span class="plain"> *</span><span class="identifier">pp</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_PERMISSIONS_FOR_INFS</span><span class="plain">(</span><span class="identifier">pp</span><span class="plain">, </span><span class="identifier">infs</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::Permissions::get_property</span><span class="plain">(</span><span class="identifier">pp</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">infs</span><span class="plain"> == </span><span class="identifier">subj</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">Kinds::Behaviour::uses_pointer_values</span><span class="plain">(</span><span class="functiontext">Properties::Valued::kind</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">))))</span>
<span class="identifier">words_used</span><span class="plain"> += </span><span class="functiontext">Properties::Emit::emit_propertyvalue</span><span class="plain">(</span><span class="identifier">subj</span><span class="plain">, </span><span class="identifier">prn</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_1">&#167;1.1</a>.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>Either way, then, we end up here. The following works out what initial
value the property will have, and compiles a clause as appropriate.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Properties::Emit::emit_propertyvalue</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">know</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="identifier">package_request</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::as_instance</span><span class="plain">(</span><span class="identifier">know</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">R</span><span class="plain"> = </span><span class="functiontext">Instances::package</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::as_kind</span><span class="plain">(</span><span class="identifier">know</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">R</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">int</span><span class="plain"> </span><span class="identifier">storage_cost</span><span class="plain"> = 0;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Properties::visited_in_traverse</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Properties::can_be_compiled</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">))) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Properties::is_either_or</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Properties::EitherOr::stored_in_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">value_holster</span><span class="plain"> </span><span class="identifier">VH</span><span class="plain"> = </span><span class="identifier">Holsters::new</span><span class="plain">(</span><span class="identifier">INTER_DATA_VHMODE</span><span class="plain">);</span>
<span class="functiontext">Properties::compile_inferred_value</span><span class="plain">(&amp;</span><span class="identifier">VH</span><span class="plain">, </span><span class="identifier">know</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Now emit a propertyvalue</span> <span class="cwebmacronumber">2.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">storage_cost</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Properties::Emit::emit_propertyvalue is used in <a href="#SP1_1_3">&#167;1.1.3</a>, <a href="#SP1_1_4">&#167;1.1.4</a>.</p>
<p class="inwebparagraph"><a id="SP2_1"></a><b>&#167;2.1. </b>Inform 6 notation is to use a clause like
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">with capacity 20</span>
</pre>
<p class="inwebparagraph">for I6 properties, and
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">has open ~lockable</span>
</pre>
<p class="inwebparagraph">for "attributes", where the tilde <code class="display"><span class="extract">~</span></code> denotes negation. As noted above, some
of our either/or properties are going to be stored as attributes, in which case
the value 1 (run-time <code class="display"><span class="extract">true</span></code>) corresponds to <code class="display"><span class="extract">has</span></code> and 0 to <code class="display"><span class="extract">has ~</span></code>.
</p>
<p class="inwebparagraph">For purposes of our size calculation, each property costs 2 words, but attributes
are free.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Now emit a propertyvalue</span> <span class="cwebmacronumber">2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">as_I</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::as_instance</span><span class="plain">(</span><span class="identifier">know</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">as_K</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::as_kind</span><span class="plain">(</span><span class="identifier">know</span><span class="plain">);</span>
<span class="identifier">inter_t</span><span class="plain"> </span><span class="identifier">v1</span><span class="plain"> = </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, </span><span class="identifier">v2</span><span class="plain"> = (</span><span class="identifier">inter_t</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">in</span><span class="plain"> = </span><span class="identifier">prn</span><span class="plain">;</span>
<span class="identifier">Holsters::unholster_pair</span><span class="plain">(&amp;</span><span class="identifier">VH</span><span class="plain">, &amp;</span><span class="identifier">v1</span><span class="plain">, &amp;</span><span class="identifier">v2</span><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::implemented_as_attribute</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">))) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::EitherOr::stored_in_negation</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">)) {</span>
<span class="identifier">in</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">v2</span><span class="plain"> = (</span><span class="identifier">inter_t</span><span class="plain">) (</span><span class="identifier">v2</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="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">as_I</span><span class="plain">) </span><span class="functiontext">Emit::instance_propertyvalue</span><span class="plain">(</span><span class="identifier">in</span><span class="plain">, </span><span class="identifier">as_I</span><span class="plain">, </span><span class="identifier">v1</span><span class="plain">, </span><span class="identifier">v2</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Emit::propertyvalue</span><span class="plain">(</span><span class="identifier">in</span><span class="plain">, </span><span class="identifier">as_K</span><span class="plain">, </span><span class="identifier">v1</span><span class="plain">, </span><span class="identifier">v2</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2">&#167;2</a>.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. Attribute allocation. </b>At some later stage the business of deciding which properties are stored
at I6 run-time as attributes will be solely up to the code generator.
For now, though, we make a parallel decision here.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Properties::Emit::allocate_attributes</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">slots_given_away</span><span class="plain"> = 0;</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">, </span><span class="reserved">property</span><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="plain">(</span><span class="functiontext">Properties::EitherOr::stored_in_negation</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="reserved">int</span><span class="plain"> </span><span class="identifier">make_attribute</span><span class="plain"> = </span><span class="identifier">NOT_APPLICABLE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Any either/or property which some value can hold is ineligible</span> <span class="cwebmacronumber">3.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">An either/or property translated to an existing attribute must be chosen</span> <span class="cwebmacronumber">3.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Otherwise give away attribute slots on a first-come-first-served basis</span> <span class="cwebmacronumber">3.3</span>&gt;<span class="plain">;</span>
<span class="functiontext">Properties::EitherOr::implement_as_attribute</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">, </span><span class="identifier">make_attribute</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Properties::Emit::allocate_attributes is used in 1/mr (<a href="1-mr.html#SP4_11">&#167;4.11</a>).</p>
<p class="inwebparagraph"><a id="SP3_1"></a><b>&#167;3.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Any either/or property which some value can hold is ineligible</span> <span class="cwebmacronumber">3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">property_permission</span><span class="plain"> *</span><span class="identifier">pp</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_PERMISSIONS_FOR_PROPERTY</span><span class="plain">(</span><span class="identifier">pp</span><span class="plain">, </span><span class="identifier">prn</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="functiontext">World::Permissions::get_subject</span><span class="plain">(</span><span class="identifier">pp</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">InferenceSubjects::is_an_object</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">InferenceSubjects::is_a_kind_of_object</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">))</span>
<span class="identifier">make_attribute</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">This code is used in <a href="#SP3">&#167;3</a>.</p>
<p class="inwebparagraph"><a id="SP3_2"></a><b>&#167;3.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">An either/or property translated to an existing attribute must be chosen</span> <span class="cwebmacronumber">3.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::has_been_translated</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">)) </span><span class="identifier">make_attribute</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP3">&#167;3</a>.</p>
<p class="inwebparagraph"><a id="SP3_3"></a><b>&#167;3.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Otherwise give away attribute slots on a first-come-first-served basis</span> <span class="cwebmacronumber">3.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">make_attribute</span><span class="plain"> == </span><span class="identifier">NOT_APPLICABLE</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">slots_given_away</span><span class="plain">++ &lt; </span><span class="identifier">ATTRIBUTE_SLOTS_TO_GIVE_AWAY</span><span class="plain">)</span>
<span class="identifier">make_attribute</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">else</span>
<span class="identifier">make_attribute</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">This code is used in <a href="#SP3">&#167;3</a>.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Rapid run-time testing. </b>The preferred way to access either/or properties of an object at run-time
is to use the pair of routines <code class="display"><span class="extract">GetEitherOrProperty</span></code> or
<code class="display"><span class="extract">SetEitherOrProperty</span></code>, defined in the I6 template, because that way
suitable run-time problems are generated for mistaken accesses. But if we
want the fastest possible access and know that it will be valid, we can use
the following.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Properties::Emit::emit_iname_has_property</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">inter_name</span><span class="plain"> *</span><span class="identifier">N</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">Properties::Emit::emit_has_property</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">InterNames::to_symbol</span><span class="plain">(</span><span class="identifier">N</span><span class="plain">), </span><span class="identifier">prn</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Properties::Emit::emit_has_property</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">inter_symbol</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::EitherOr::implemented_as_attribute</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::EitherOr::stored_in_negation</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">)) {</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">NOT_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">HAS_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">);</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="functiontext">Properties::iname</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">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">HAS_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">);</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="functiontext">Properties::iname</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::EitherOr::stored_in_negation</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">)) {</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">EQ_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">PROPERTYVALUE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">);</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="functiontext">Properties::iname</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">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_truth_state</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 0);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">EQ_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">PROPERTYVALUE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">);</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="functiontext">Properties::iname</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_truth_state</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 1);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Properties::Emit::emit_iname_has_property appears nowhere else.</p>
<p class="endnote">The function Properties::Emit::emit_has_property appears nowhere else.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="15-pov.html">Back to 'Properties of Values'</a></li><li><i>(This section ends Chapter 15: Properties.)</i></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>