mirror of
https://github.com/ganelson/inform.git
synced 2024-07-09 02:24:21 +03:00
964 lines
113 KiB
HTML
964 lines
113 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>2/knd</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</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 '2/kc' 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">kinds</a></li><li><a href="index.html#2">Chapter 2: Kinds</a></li><li><b>Kind Checking</b></li></ul><p class="purpose">To test whether two kinds are equivalent to each other, or failing that, whether they are compatible with each other.</p>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. Definitions</a></li><li><a href="#SP9">§9. Subkinds</a></li><li><a href="#SP14">§14. Kind compatibility</a></li><li><a href="#SP15">§15. Common code</a></li><li><a href="#SP18">§18. Unit tests</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. Definitions. </b></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§2. </b>We say that a kind K_L is a subkind of K_R if its values can
|
|
be used without modification at run-time in code which expects a value of
|
|
K_R, and write
|
|
K_L <= K_R.
|
|
There are many pairs of kinds where neither is compatible with the other:
|
|
for instance, it is true neither that rulebook <= text nor that text <= rulebook. So
|
|
we're using the notation <= here by analogy with partially-ordered sets
|
|
rather than with numbers. The universe of kinds does indeed form a poset
|
|
under this relation:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(a) it is reflexive (K<= K);
|
|
</li><li>(b) it is antisymmetric (K<= L and L<= K imply K=L);
|
|
</li><li>(c) it is transitive (K<= L and L<= M imply K<= M).
|
|
</li></ul>
|
|
<p class="inwebparagraph">We test compatibility with the routine <code class="display"><span class="extract">Kinds::Compare::le</span></code>, and for convenience
|
|
we also have <code class="display"><span class="extract">Kinds::Compare::eq</span></code> to test equality and <code class="display"><span class="extract">Kinds::Compare::lt</span></code> for the case
|
|
when K<= L but K!= L, that is, for K<L. The main aim of this
|
|
section is to define those routines.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. </b>To say that K_L is compatible with K_R is a weaker statement.
|
|
This is the test Inform uses to see whether it will allow K_L values to
|
|
be used where K_R values are expected. Clearly if K_L<= K_R then
|
|
they must be compatible, but there are other possibilities. For example,
|
|
snippets can be used as texts if suitably modified ("cast")
|
|
at run-time, but snippet is not <= text. Compatibility lacks the
|
|
elegant formal properties of <=: for example, "value" is compatible
|
|
with "text" which is in turn compatible with "value".
|
|
</p>
|
|
|
|
<p class="inwebparagraph">This test is performed by <code class="display"><span class="extract">Kinds::Compare::compatible</span></code>. As we will see, the two
|
|
relations are similarly defined, and they share most of the code.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. </b>A function f on kinds is covariant if K<= L implies f(K)<= f(L),
|
|
and contravariant if K<= L implies f(L)<= f(K). Of course there's
|
|
no reason a function needs to be either, but the ones provided by our
|
|
kind constructors (such "list of", which maps K to list of K) always are.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">COVARIANT</span><span class="plain"> 1</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">CONTRAVARIANT</span><span class="plain"> -1</span>
|
|
</pre>
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§5. </b>Kind checking can happen for many reasons, but the most difficult case
|
|
occurs when matching phrase prototypes (a task carried out by the main
|
|
specification matcher in the next chapter). This is difficult because
|
|
it involves kind variables:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>To add (new entry - K) to (L - list of values of kind K) ...</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">This matches "add 23 to L" if "L" is a list of numbers, but not if it
|
|
is a list of times.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Since kind variables can be changed only when matching phrase prototypes,
|
|
and this is not a recursive process, we can store the current definitions
|
|
of A to Z in a single array.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">MAX_KIND_VARIABLES</span><span class="plain"> 27 </span> <span class="comment">we number them from 1 (A) to 26 (Z)</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">values_of_kind_variables</span><span class="plain">[</span><span class="constant">MAX_KIND_VARIABLES</span><span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§6. </b>In theory the kind-checker only needs to read the values of A to Z, not
|
|
to write them. If Q is currently equal to "number", then it should check
|
|
kinds against Q exactly as if it were checking against "number". It can
|
|
indeed do this — that's the <code class="display"><span class="extract">MATCH_KIND_VARIABLES_AS_VALUES</span></code> mode. It can
|
|
also ignore the values of kind variables and treat them as names, so that
|
|
Q matches only against Q, regardless of its current value; that's the
|
|
<code class="display"><span class="extract">MATCH_KIND_VARIABLES_AS_SYMBOLS</span></code> mode. Or it can match anything
|
|
against Q, which is <code class="display"><span class="extract">MATCH_KIND_VARIABLES_AS_UNIVERSAL</span></code> mode.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">More interestingly, the kind-checker can also set the values of A to Z.
|
|
This is convenient since checking their correctness is more or less the same
|
|
thing as inferring what they seem to be in a given situation. So this is
|
|
<code class="display"><span class="extract">MATCH_KIND_VARIABLES_INFERRING_VALUES</span></code> mode.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">MATCH_KIND_VARIABLES_AS_SYMBOLS</span><span class="plain"> 0</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">MATCH_KIND_VARIABLES_INFERRING_VALUES</span><span class="plain"> 1</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">MATCH_KIND_VARIABLES_AS_VALUES</span><span class="plain"> 2</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">MATCH_KIND_VARIABLES_AS_UNIVERSAL</span><span class="plain"> 3</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">kind_checker_mode</span><span class="plain"> = </span><span class="constant">MATCH_KIND_VARIABLES_AS_SYMBOLS</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§7. </b>When the kind-checker does choose a value for a variable, it not only
|
|
sets the relevant entry in the above array but also creates a note that
|
|
this has been done. (If a phrase is correctly matched by the specification
|
|
matcher, a linked list of these notes is attached to the results: thus
|
|
a match of "add 23 to L" in the example above would produce a successful
|
|
result plus a note that K has to be "list of numbers".)
|
|
</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">kind_variable_declaration</span><span class="plain"> {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">kv_number</span><span class="plain">; </span> <span class="comment">must be from 1 to 26</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kv_value</span><span class="plain">; </span> <span class="comment">must be a definite non-<code class="display"><span class="extract">NULL</span></code> kind</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_variable_declaration</span><span class="plain"> *</span><span class="identifier">next</span><span class="plain">;</span>
|
|
<span class="identifier">MEMORY_MANAGEMENT</span>
|
|
<span class="plain">} </span><span class="reserved">kind_variable_declaration</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure kind_variable_declaration is accessed in 2/dmn and here.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8"></a><b>§8. </b>The following constants will be used to represent the results of kind
|
|
checking:
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">ALWAYS_MATCH</span><span class="plain"> 2 </span> <span class="comment">provably correct at compile time</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">SOMETIMES_MATCH</span><span class="plain"> 1 </span> <span class="comment">provably reduced to a check feasible at run-time</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">NEVER_MATCH</span><span class="plain"> 0 </span> <span class="comment">provably incorrect at compile time</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">NO_DECISION_ON_MATCH</span><span class="plain"> -1 </span> <span class="comment">none of the above</span>
|
|
</pre>
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§9. Subkinds. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::test_kind_relation</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">) == </span><span class="constant">ALWAYS_MATCH</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Compare::lt</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Compare::le is used in <a href="#SP12">§12</a>, <a href="#SP18_1">§18.1</a>, <a href="#SP18_2">§18.2</a>, <a href="#SP18_4">§18.4</a>, <a href="#SP18_5">§18.5</a>, <a href="#SP18_6">§18.6</a>, 2/knd (<a href="2-knd.html#SP33">§33</a>, <a href="2-knd.html#SP33_2">§33.2</a>), 2/uk (<a href="2-uk.html#SP17">§17</a>, <a href="2-uk.html#SP29">§29</a>, <a href="2-uk.html#SP30">§30</a>, <a href="2-uk.html#SP33">§33</a>, <a href="2-uk.html#SP35">§35</a>).</p>
|
|
|
|
<p class="endnote">The function Kinds::Compare::lt is used in <a href="#SP17">§17</a>, 2/knd (<a href="2-knd.html#SP30">§30</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§10. </b>The following determines whether or not two kinds are the same. Clearly
|
|
all base kinds are different from each other, but in some programming
|
|
languages it's an interesting question whether different sequences of
|
|
constructors applied to these bases can ever produce an equivalent kind.
|
|
Most of the interesting cases are to do with unions (which Inform
|
|
disallows as type unsafe) and records (which Inform supports by its
|
|
"combination" operator). For example, is "combination (number, text)"
|
|
the same as "combination (text, number)"? One might also consider
|
|
whether <code class="display"><span class="extract">-></span></code> (function mapping) ought to be an associative operation, as
|
|
it would be in a language like Haskell which curried all functions.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">At any rate, for Inform the answer is no: every different sequence of kind
|
|
constructors produces a different kind.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">With kind variables, we take the "name" approach rather than the
|
|
"structural" approach: that is, the kind "X" (a variable) is not equivalent
|
|
to the kind "number" even if that's the current value of X.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K1</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K2</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K1</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">K2</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">TRUE</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">; }</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K2</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K1</span><span class="plain">-</span><span class="element">>construct</span><span class="plain"> != </span><span class="identifier">K2</span><span class="plain">-</span><span class="element">>construct</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">if</span><span class="plain"> ((</span><span class="identifier">K1</span><span class="plain">-</span><span class="element">>intermediate_result</span><span class="plain">) && (</span><span class="identifier">K2</span><span class="plain">-</span><span class="element">>intermediate_result</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K1</span><span class="plain">-</span><span class="element">>intermediate_result</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) && (</span><span class="identifier">K2</span><span class="plain">-</span><span class="element">>intermediate_result</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">if</span><span class="plain"> ((</span><span class="identifier">K1</span><span class="plain">-</span><span class="element">>intermediate_result</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::Dimensions::compare_unit_sequences</span><span class="plain">(</span>
|
|
<span class="identifier">K1</span><span class="plain">-</span><span class="element">>intermediate_result</span><span class="plain">, </span><span class="identifier">K2</span><span class="plain">-</span><span class="element">>intermediate_result</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">if</span><span class="plain"> (</span><span class="functiontext">Kinds::get_variable_number</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">) != </span><span class="functiontext">Kinds::get_variable_number</span><span class="plain">(</span><span class="identifier">K2</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">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="constant">MAX_KIND_CONSTRUCTION_ARITY</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="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">-</span><span class="element">>kc_args</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">K2</span><span class="plain">-</span><span class="element">>kc_args</span><span class="plain">[</span><span class="identifier">i</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">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 Kinds::Compare::eq is used in <a href="#SP9">§9</a>, <a href="#SP12">§12</a>, <a href="#SP14">§14</a>, <a href="#SP15_1">§15.1</a>, <a href="#SP15_2">§15.2</a>, <a href="#SP18_1">§18.1</a>, <a href="#SP18_2">§18.2</a>, <a href="#SP18_4">§18.4</a>, <a href="#SP18_5">§18.5</a>, <a href="#SP18_6">§18.6</a>, 2/knd (<a href="2-knd.html#SP33">§33</a>), 2/uk (<a href="2-uk.html#SP26">§26</a>, <a href="2-uk.html#SP27">§27</a>, <a href="2-uk.html#SP32">§32</a>), 2/dk (<a href="2-dk.html#SP24_1_2">§24.1.2</a>, <a href="2-dk.html#SP24_3_1">§24.3.1</a>, <a href="2-dk.html#SP24_3_2">§24.3.2</a>), 2/dmn (<a href="2-dmn.html#SP18">§18</a>, <a href="2-dmn.html#SP23">§23</a>, <a href="2-dmn.html#SP24">§24</a>, <a href="2-dmn.html#SP26">§26</a>, <a href="2-dmn.html#SP31">§31</a>, <a href="2-dmn.html#SP32_2_1">§32.2.1</a>, <a href="2-dmn.html#SP32_2_2">§32.2.2</a>, <a href="2-dmn.html#SP40_1">§40.1</a>), 2/fv (<a href="2-fv.html#SP4">§4</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§11. </b>It turns out to be useful to be able to "increment" a kind K, by trying to
|
|
find the S such that K < S but there is no S' with K<S'<S. This is only
|
|
well-defined for kinds of object, and otherwise returns <code class="display"><span class="extract">NULL</span></code>.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::Compare::super</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">KINDS_SUPER</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">KINDS_SUPER</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="reserved">else</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Compare::super is used in <a href="#SP12">§12</a>, <a href="#SP17">§17</a>, <a href="#SP18_3">§18.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12"></a><b>§12. </b>The maximum of K_1 and K_2 is by definition the kind M such that
|
|
K_1<= M and K_2<= M, and there is no M'<M with the same property.
|
|
This is similarly not well-defined in some cases, in which case we simply
|
|
return "value" as a safe answer.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::Compare::max</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K1</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K2</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::FloatingPoint::uses_floating_point</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::FloatingPoint::uses_floating_point</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="functiontext">Kinds::FloatingPoint::real_equivalent</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">), </span><span class="identifier">K2</span><span class="plain">)))</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K2</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::FloatingPoint::uses_floating_point</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::FloatingPoint::uses_floating_point</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="functiontext">Kinds::FloatingPoint::real_equivalent</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">), </span><span class="identifier">K1</span><span class="plain">)))</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K1</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::Compare::traverse_kind_poset</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">, </span><span class="identifier">K2</span><span class="plain">, 1);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::Compare::traverse_kind_poset</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K1</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K2</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">direction</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K1</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">K2</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">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K1</span><span class="plain">;</span>
|
|
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">con</span><span class="plain"> = </span><span class="identifier">K1</span><span class="plain">-</span><span class="element">>construct</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">a1</span><span class="plain"> = </span><span class="functiontext">Kinds::Constructors::arity</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">), </span><span class="identifier">a2</span><span class="plain"> = </span><span class="functiontext">Kinds::Constructors::arity</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">-</span><span class="element">>construct</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">a1</span><span class="plain"> > 0) || (</span><span class="identifier">a2</span><span class="plain"> > 0)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K2</span><span class="plain">-</span><span class="element">>construct</span><span class="plain"> != </span><span class="identifier">con</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K_value</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">ka</span><span class="plain">[</span><span class="constant">MAX_KIND_CONSTRUCTION_ARITY</span><span class="plain">];</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">a1</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">con</span><span class="plain">-</span><span class="element">>variance</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == </span><span class="constant">COVARIANT</span><span class="plain">)</span>
|
|
<span class="identifier">ka</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="functiontext">Kinds::Compare::traverse_kind_poset</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">-</span><span class="element">>kc_args</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">K2</span><span class="plain">-</span><span class="element">>kc_args</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">direction</span><span class="plain">);</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">ka</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="functiontext">Kinds::Compare::traverse_kind_poset</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">-</span><span class="element">>kc_args</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">K2</span><span class="plain">-</span><span class="element">>kc_args</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], -</span><span class="identifier">direction</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">a1</span><span class="plain"> == 1) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::unary_construction</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">, </span><span class="identifier">ka</span><span class="plain">[0]);</span>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">, </span><span class="identifier">ka</span><span class="plain">[0], </span><span class="identifier">ka</span><span class="plain">[1]);</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">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">, </span><span class="identifier">K2</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> (</span><span class="identifier">direction</span><span class="plain"> > 0)?</span><span class="identifier">K2</span><span class="plain">:</span><span class="identifier">K1</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">, </span><span class="identifier">K1</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> (</span><span class="identifier">direction</span><span class="plain"> > 0)?</span><span class="identifier">K1</span><span class="plain">:</span><span class="identifier">K2</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">direction</span><span class="plain"> > 0) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">)) && (</span><span class="functiontext">Kinds::Compare::le</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="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">K1</span><span class="plain">; </span><span class="identifier">K</span><span class="plain">; </span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Kinds::Compare::super</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">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">K2</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">K</span><span class="plain">;</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">K_value</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Compare::max is used in <a href="#SP13">§13</a>, <a href="#SP18_5">§18.5</a>, <a href="#SP18_6">§18.6</a>.</p>
|
|
|
|
<p class="endnote">The function Kinds::Compare::traverse_kind_poset appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13"></a><b>§13. </b>A variation on this is the accumulated maximum, used for example when
|
|
inferring the kinds of table columns by looking through entries one by one.
|
|
This is needed because the empty list has kind "list of values", and yet
|
|
should be considered for these purposes as a subkind of "list of texts".
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::Compare::accumulative_max</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K1</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K2</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Behaviour::definite</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">) == </span><span class="identifier">TRUE</span><span class="plain">) && (</span><span class="functiontext">Kinds::Behaviour::definite</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">, </span><span class="identifier">K1</span><span class="plain">) == </span><span class="constant">ALWAYS_MATCH</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K1</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">Kinds::Behaviour::definite</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">) == </span><span class="identifier">TRUE</span><span class="plain">) && (</span><span class="functiontext">Kinds::Behaviour::definite</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">, </span><span class="identifier">K2</span><span class="plain">) == </span><span class="constant">ALWAYS_MATCH</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K2</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::Compare::max</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">, </span><span class="identifier">K2</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Compare::accumulative_max appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14"></a><b>§14. Kind compatibility. </b>Now for a more interesting question. If K_F and K_T are kinds, what
|
|
values do they have in common? <code class="display"><span class="extract">Kinds::Compare::compatible</span></code> returns
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(a) <code class="display"><span class="extract">ALWAYS_MATCH</span></code> if a value of kind K_F can always be used when a value
|
|
of kind K_T is expected,
|
|
</li><li>(b) <code class="display"><span class="extract">SOMETIMES_MATCH</span></code> if it sometimes can, but this needs to be protected
|
|
by run-time checking in individual cases, or
|
|
</li><li>(c) <code class="display"><span class="extract">NEVER_MATCH</span></code> if it never can.
|
|
</li></ul>
|
|
<p class="inwebparagraph">For example, a value of kind "vehicle" can always be used when a value of
|
|
kind "object" is expected; a value of kind "object" can only sometimes
|
|
be used when a "vehicle" is expected, and any attempt to use it should
|
|
be guarded by run-time checking that is indeed a vehicle; a value of kind
|
|
"number" can never be used when a "scene" is expected.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The outer routine is just a logging mechanism for the real routine. Cases
|
|
where K_F = K_T are frequent and not interesting enough to be logged.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Compare::compatible</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">ALWAYS_MATCH</span><span class="plain">;</span>
|
|
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CHECKING</span><span class="plain">, </span><span class="string">"(Is the kind $u compatible with $u?"</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">switch</span><span class="plain">(</span><span class="functiontext">Kinds::Compare::test_kind_relation</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">)) {</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">NEVER_MATCH</span><span class="plain">: </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CHECKING</span><span class="plain">, </span><span class="string">" No)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">NEVER_MATCH</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">ALWAYS_MATCH</span><span class="plain">: </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CHECKING</span><span class="plain">, </span><span class="string">" Yes)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">ALWAYS_MATCH</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">SOMETIMES_MATCH</span><span class="plain">: </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CHECKING</span><span class="plain">, </span><span class="string">" Sometimes)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">SOMETIMES_MATCH</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad return value from Kinds::Compare::compatible"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">NEVER_MATCH</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Compare::compatible is used in <a href="#SP13">§13</a>, <a href="#SP17">§17</a>, <a href="#SP18_2">§18.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15"></a><b>§15. Common code. </b>So the following routine tests <= if <code class="display"><span class="extract">comp</span></code> is <code class="display"><span class="extract">FALSE</span></code>, returning
|
|
<code class="display"><span class="extract">ALWAYS_MATCH</span></code> if and only if <= holds; and otherwise it tests compatibility.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Compare::test_kind_relation</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">comp</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::get_variable_number</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">) > 0) {</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">var_k</span><span class="plain"> = </span><span class="identifier">to</span><span class="plain">, *</span><span class="identifier">other_k</span><span class="plain"> = </span><span class="identifier">from</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Deal separately with matches against kind variables</span> <span class="cwebmacronumber">15.6</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::get_variable_number</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">) > 0) {</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">var_k</span><span class="plain"> = </span><span class="identifier">from</span><span class="plain">, *</span><span class="identifier">other_k</span><span class="plain"> = </span><span class="identifier">to</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Deal separately with matches against kind variables</span> <span class="cwebmacronumber">15.6</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<<span class="cwebmacro">Deal separately with the sayability of lists</span> <span class="cwebmacronumber">15.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Deal separately with the special role of value</span> <span class="cwebmacronumber">15.2</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Deal separately with the special role of the unknown kind</span> <span class="cwebmacronumber">15.3</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Deal separately with compatibility within the objects hierarchy</span> <span class="cwebmacronumber">15.4</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">The general case of compatibility</span> <span class="cwebmacronumber">15.5</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Compare::test_kind_relation is used in <a href="#SP9">§9</a>, <a href="#SP14">§14</a>, <a href="#SP15_1">§15.1</a>, <a href="#SP15_5">§15.5</a>, <a href="#SP15_6_1">§15.6.1</a>, <a href="#SP15_6_2">§15.6.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_1"></a><b>§15.1. </b>A list is sayable if and only if its contents are.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Deal separately with the sayability of lists</span> <span class="cwebmacronumber">15.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">) == </span><span class="identifier">CON_list_of</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">, </span><span class="identifier">K_sayable_value</span><span class="plain">)))</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::Compare::test_kind_relation</span><span class="plain">(</span>
|
|
<span class="functiontext">Kinds::unary_construction_material</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">), </span><span class="identifier">K_sayable_value</span><span class="plain">, </span><span class="identifier">comp</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP15">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_2"></a><b>§15.2. </b>"Value" is special because, for every kind K, we have K<= V — it
|
|
represents a supremum in our partially ordered set of kinds.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">But it is also used in Inform to mark places where type safety has
|
|
deliberately been put aside. For compatibility purposes, then, giving
|
|
something the kind "value" is a way of saying that we don't care what its
|
|
kind is, and we always allow the usage. So "value" is compatible with
|
|
everything — which is one reason compatibility isn't a partial ordering:
|
|
"value" is compatible with "number" and vice versa, yet they are
|
|
different kinds.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Deal separately with the special role of value</span> <span class="cwebmacronumber">15.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">ALWAYS_MATCH</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">comp</span><span class="plain">) && (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">))) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">ALWAYS_MATCH</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP15">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_3"></a><b>§15.3. </b><code class="display"><span class="extract">NULL</span></code> as a kind means "unknown". It's compatible only with itself
|
|
and, of course, "value".
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Deal separately with the special role of the unknown kind</span> <span class="cwebmacronumber">15.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">to</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) && (</span><span class="identifier">from</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">ALWAYS_MATCH</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">to</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">from</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">NEVER_MATCH</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP15">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_4"></a><b>§15.4. </b>Here both our kinds are <= "object".
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Deal separately with compatibility within the objects hierarchy</span> <span class="cwebmacronumber">15.4</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">KINDS_COMPATIBLE</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">m</span><span class="plain"> = </span><span class="identifier">KINDS_COMPATIBLE</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">m</span><span class="plain"> != </span><span class="constant">NO_DECISION_ON_MATCH</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">m</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="#SP15">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_5"></a><b>§15.5. </b><code class="display">
|
|
<<span class="cwebmacrodefn">The general case of compatibility</span> <span class="cwebmacronumber">15.5</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Constructors::compatible</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">-</span><span class="element">>construct</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">-</span><span class="element">>construct</span><span class="plain">, </span><span class="identifier">comp</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="constant">NEVER_MATCH</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">f_a</span><span class="plain"> = </span><span class="functiontext">Kinds::Constructors::arity</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">-</span><span class="element">>construct</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">t_a</span><span class="plain"> = </span><span class="functiontext">Kinds::Constructors::arity</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">-</span><span class="element">>construct</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">arity</span><span class="plain"> = (</span><span class="identifier">f_a</span><span class="plain"> < </span><span class="identifier">t_a</span><span class="plain">)?</span><span class="identifier">f_a</span><span class="plain">:</span><span class="identifier">t_a</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">o</span><span class="plain"> = </span><span class="constant">ALWAYS_MATCH</span><span class="plain">, </span><span class="identifier">this_o</span><span class="plain"> = </span><span class="constant">NEVER_MATCH</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">arity</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="functiontext">Kinds::Constructors::variance</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">-</span><span class="element">>construct</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == </span><span class="constant">COVARIANT</span><span class="plain">)</span>
|
|
<span class="identifier">this_o</span><span class="plain"> = </span><span class="functiontext">Kinds::Compare::test_kind_relation</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">-</span><span class="element">>kc_args</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">to</span><span class="plain">-</span><span class="element">>kc_args</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">comp</span><span class="plain">);</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">this_o</span><span class="plain"> = </span><span class="functiontext">Kinds::Compare::test_kind_relation</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">-</span><span class="element">>kc_args</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">from</span><span class="plain">-</span><span class="element">>kc_args</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">comp</span><span class="plain">);</span>
|
|
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">this_o</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">NEVER_MATCH</span><span class="plain">: </span><span class="identifier">o</span><span class="plain"> = </span><span class="identifier">this_o</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">SOMETIMES_MATCH</span><span class="plain">: </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">o</span><span class="plain"> != </span><span class="constant">NEVER_MATCH</span><span class="plain">) </span><span class="identifier">o</span><span class="plain"> = </span><span class="identifier">this_o</span><span class="plain">; </span><span class="reserved">break</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">o</span><span class="plain"> == </span><span class="constant">SOMETIMES_MATCH</span><span class="plain">) && (</span><span class="identifier">to</span><span class="plain">-</span><span class="element">>construct</span><span class="plain"> != </span><span class="identifier">CON_list_of</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">NEVER_MATCH</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">o</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP15">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_6"></a><b>§15.6. </b>Recall that kind variables are identified by a number in the range 1 ("A")
|
|
to 26 ("Z"), and that it is also possible to assign them a domain, or a
|
|
"declaration". This marks that they are free to take on a value, within
|
|
that domain. For example, in
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>To add (new entry - K) to (L - list of values of kind K) ...</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">the first appearance of "K" will be an ordinary use of a kind variable,
|
|
whereas the second has the declaration "value" — meaning that it can
|
|
become any kind matching "value". (It could alternatively have had a
|
|
more restrictive declaration like "arithmetic value".)
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Deal separately with matches against kind variables</span> <span class="cwebmacronumber">15.6</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">kind_checker_mode</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">MATCH_KIND_VARIABLES_AS_SYMBOLS</span><span class="plain">:</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::get_variable_number</span><span class="plain">(</span><span class="identifier">other_k</span><span class="plain">) ==</span>
|
|
<span class="functiontext">Kinds::get_variable_number</span><span class="plain">(</span><span class="identifier">var_k</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">ALWAYS_MATCH</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">NEVER_MATCH</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">MATCH_KIND_VARIABLES_AS_UNIVERSAL</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">ALWAYS_MATCH</span><span class="plain">;</span>
|
|
<span class="reserved">default</span><span class="plain">: {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">vn</span><span class="plain"> = </span><span class="functiontext">Kinds::get_variable_number</span><span class="plain">(</span><span class="identifier">var_k</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::get_variable_stipulation</span><span class="plain">(</span><span class="identifier">var_k</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">Act on a declaration usage, where inference is allowed</span> <span class="cwebmacronumber">15.6.1</span>>
|
|
<span class="reserved">else</span>
|
|
<<span class="cwebmacro">Act on an ordinary usage, where inference is not allowed</span> <span class="cwebmacronumber">15.6.2</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="#SP15">§15</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_6_1"></a><b>§15.6.1. </b>When the specification matcher works on matching text such as
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>add 23 to the scores list;</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">it works through the prototype:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>To add (new entry - K) to (L - list of values of kind K) ...</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">in two passes. On the first pass, it tries to match the tokens "23" and
|
|
"scores list" against "K" and "list of values of kind K" respectively
|
|
in <code class="display"><span class="extract">MATCH_KIND_VARIABLES_INFERRING_VALUES</span></code> mode; on the second pass, it
|
|
does the same in <code class="display"><span class="extract">MATCH_KIND_VARIABLES_AS_VALUES</span></code> mode. In this example,
|
|
on the first pass we infer (from the kind of "scores list", which is
|
|
indeed a list of numbers) that K must be "number"; on the second pass
|
|
we verify that "23" is a K.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The following shows what happens matching "values of kind K", which is
|
|
a declaration usage of the variable K.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Act on a declaration usage, where inference is allowed</span> <span class="cwebmacronumber">15.6.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">kind_checker_mode</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">MATCH_KIND_VARIABLES_INFERRING_VALUES</span><span class="plain">:</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::test_kind_relation</span><span class="plain">(</span><span class="identifier">other_k</span><span class="plain">,</span>
|
|
<span class="functiontext">Kinds::get_variable_stipulation</span><span class="plain">(</span><span class="identifier">var_k</span><span class="plain">), </span><span class="identifier">comp</span><span class="plain">) != </span><span class="constant">ALWAYS_MATCH</span><span class="plain">)</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">NEVER_MATCH</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CHECKING</span><span class="plain">, </span><span class="string">"Inferring kind variable %d from $u (declaration $u)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">vn</span><span class="plain">, </span><span class="identifier">other_k</span><span class="plain">, </span><span class="functiontext">Kinds::get_variable_stipulation</span><span class="plain">(</span><span class="identifier">var_k</span><span class="plain">));</span>
|
|
<span class="identifier">values_of_kind_variables</span><span class="plain">[</span><span class="identifier">vn</span><span class="plain">] = </span><span class="identifier">other_k</span><span class="plain">;</span>
|
|
<span class="reserved">kind_variable_declaration</span><span class="plain"> *</span><span class="identifier">kvd</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">kind_variable_declaration</span><span class="plain">);</span>
|
|
<span class="identifier">kvd</span><span class="plain">-</span><span class="element">>kv_number</span><span class="plain"> = </span><span class="identifier">vn</span><span class="plain">;</span>
|
|
<span class="identifier">kvd</span><span class="plain">-</span><span class="element">>kv_value</span><span class="plain"> = </span><span class="identifier">other_k</span><span class="plain">;</span>
|
|
<span class="identifier">kvd</span><span class="plain">-</span><span class="element">>next</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">ALWAYS_MATCH</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">MATCH_KIND_VARIABLES_AS_VALUES</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">ALWAYS_MATCH</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP15_6">§15.6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_6_2"></a><b>§15.6.2. </b>Whereas this is what happens when matching just "K". On the inference pass,
|
|
we always make a match, which is legitimate because we know we are going to
|
|
make a value-checking pass later.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Act on an ordinary usage, where inference is not allowed</span> <span class="cwebmacronumber">15.6.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">kind_checker_mode</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">MATCH_KIND_VARIABLES_INFERRING_VALUES</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">ALWAYS_MATCH</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">MATCH_KIND_VARIABLES_AS_VALUES</span><span class="plain">:</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CHECKING</span><span class="plain">, </span><span class="string">"Checking $u against kind variable %d (=$u)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">other_k</span><span class="plain">, </span><span class="identifier">vn</span><span class="plain">, </span><span class="identifier">values_of_kind_variables</span><span class="plain">[</span><span class="identifier">vn</span><span class="plain">]);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::test_kind_relation</span><span class="plain">(</span><span class="identifier">other_k</span><span class="plain">, </span><span class="identifier">values_of_kind_variables</span><span class="plain">[</span><span class="identifier">vn</span><span class="plain">], </span><span class="identifier">comp</span><span class="plain">) == </span><span class="constant">NEVER_MATCH</span><span class="plain">)</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">NEVER_MATCH</span><span class="plain">;</span>
|
|
<span class="reserved">else</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">ALWAYS_MATCH</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP15_6">§15.6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16"></a><b>§16. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Compare::show_variables</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Variables: "</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=1; </span><span class="identifier">i</span><span class="plain"><=26; </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">values_of_kind_variables</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">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%c=$u "</span><span class="plain">, </span><span class="character">'A'</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">-1, </span><span class="identifier">K</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Compare::show_frame_variables</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">shown</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=1; </span><span class="identifier">i</span><span class="plain"><=26; </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">KIND_VARIABLE_FROM_CONTEXT</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">K</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">shown</span><span class="plain">++ == 0) </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Stack frame uses kind variables: "</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"%c=$u "</span><span class="plain">, </span><span class="character">'A'</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">-1, </span><span class="identifier">K</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">shown</span><span class="plain"> == 0) </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"Stack frame sets no kind variables"</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">MATCHING</span><span class="plain">, </span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Compare::show_variables appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Kinds::Compare::show_frame_variables appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP17"></a><b>§17. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Compare::make_subkind</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">super</span><span class="plain">) {</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">PROTECTED_MODEL_PROCEDURE</span>
|
|
<span class="identifier">PROTECTED_MODEL_PROCEDURE</span><span class="plain">;</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sub</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Tried to set kind to $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">super</span><span class="plain">);</span>
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Tried to set the kind of a null kind"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::lt</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">K_object</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="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">NEW_SUBKIND_NOTIFY</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">NEW_SUBKIND_NOTIFY</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">super</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">existing</span><span class="plain"> = </span><span class="functiontext">Kinds::Compare::super</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="reserved">switch</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">existing</span><span class="plain">, </span><span class="identifier">super</span><span class="plain">)) {</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">NEVER_MATCH</span><span class="plain">:</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Tried to make $u a kind of $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">super</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> == 0)</span>
|
|
<span class="identifier">KINDS_PROBLEM_HANDLER</span><span class="plain">(</span><span class="constant">KindUnalterable_KINDERROR</span><span class="plain">,</span>
|
|
<span class="functiontext">Kinds::Behaviour::get_superkind_set_at</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">), </span><span class="identifier">super</span><span class="plain">, </span><span class="identifier">existing</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">SOMETIMES_MATCH</span><span class="plain">:</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KINDS_TEST_WITHIN</span><span class="plain">(</span><span class="identifier">super</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> == 0)</span>
|
|
<span class="identifier">KINDS_PROBLEM_HANDLER</span><span class="plain">(</span><span class="constant">KindsCircular_KINDERROR</span><span class="plain">,</span>
|
|
<span class="functiontext">Kinds::Behaviour::get_superkind_set_at</span><span class="plain">(</span><span class="identifier">super</span><span class="plain">), </span><span class="identifier">super</span><span class="plain">, </span><span class="identifier">existing</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">KINDS_MOVE_WITHIN</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">super</span><span class="plain">);</span>
|
|
<span class="functiontext">Kinds::Behaviour::set_superkind_set_at</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CHANGES</span><span class="plain">, </span><span class="string">"Making $u a subkind of $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">super</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Compare::make_subkind appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18"></a><b>§18. Unit tests. </b>Some internal test cases check that the hierarchy of kinds is behaving as we expect:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Compare::log_poset</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="reserved">switch</span><span class="plain"> (</span><span class="identifier">n</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> 1: </span><<span class="cwebmacro">Display the subkind relation of base kinds</span> <span class="cwebmacronumber">18.1</span>><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 2: </span><<span class="cwebmacro">Display the compatibility relation of base kinds</span> <span class="cwebmacronumber">18.2</span>><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 3: </span><<span class="cwebmacro">Display the results of the superkind function</span> <span class="cwebmacronumber">18.3</span>><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 4: </span><<span class="cwebmacro">Check for poset violations</span> <span class="cwebmacronumber">18.4</span>><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 5: </span><<span class="cwebmacro">Check the maximum function</span> <span class="cwebmacronumber">18.5</span>><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 6: </span><<span class="cwebmacro">Some miscellaneous tests with a grab bag of kinds</span> <span class="cwebmacronumber">18.6</span>><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Compare::log_poset appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18_1"></a><b>§18.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Display the subkind relation of base kinds</span> <span class="cwebmacronumber">18.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"The subkind relation on (base) kinds:\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">A</span><span class="plain">, *</span><span class="identifier">B</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">B</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">)) && (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain">++ == 0) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$u <= "</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">); </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">", "</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$u"</span><span class="plain">, </span><span class="identifier">B</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">c</span><span class="plain"> > 0) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP18">§18</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18_2"></a><b>§18.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Display the compatibility relation of base kinds</span> <span class="cwebmacronumber">18.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"The (always) compatibility relation on (base) kinds, where it differs from <=:\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">A</span><span class="plain">, *</span><span class="identifier">B</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">B</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">) == </span><span class="constant">ALWAYS_MATCH</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain">++ == 0) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$u --> "</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">); </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">", "</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$u"</span><span class="plain">, </span><span class="identifier">B</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">c</span><span class="plain"> > 0) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP18">§18</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18_3"></a><b>§18.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Display the results of the superkind function</span> <span class="cwebmacronumber">18.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"The superkind function applied to base kinds:\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">A</span><span class="plain">, *</span><span class="identifier">B</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">) {</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">B</span><span class="plain"> = </span><span class="identifier">A</span><span class="plain">; </span><span class="identifier">B</span><span class="plain">; </span><span class="identifier">B</span><span class="plain"> = </span><span class="functiontext">Kinds::Compare::super</span><span class="plain">(</span><span class="identifier">B</span><span class="plain">))</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$u -> "</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP18">§18</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18_4"></a><b>§18.4. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Check for poset violations</span> <span class="cwebmacronumber">18.4</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Looking for partially ordered set violations.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">A</span><span class="plain">, *</span><span class="identifier">B</span><span class="plain">, *</span><span class="identifier">C</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Reflexivity violated: $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">)</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">B</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">)) && (</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">B</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">)) && (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">))</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Antisymmetry violated: $u, $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">)</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">B</span><span class="plain">)</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</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="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">)) && (</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">B</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">)) && (</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">))</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Transitivity violated: $u, $u, $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP18">§18</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18_5"></a><b>§18.5. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Check the maximum function</span> <span class="cwebmacronumber">18.5</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Looking for maximum violations.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">A</span><span class="plain">, *</span><span class="identifier">B</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">)</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">B</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="functiontext">Kinds::Compare::max</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">), </span><span class="functiontext">Kinds::Compare::max</span><span class="plain">(</span><span class="identifier">B</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">)) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Fail symmetry: max($u, $u) = $u, but max($u, $u) = $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">, </span><span class="functiontext">Kinds::Compare::max</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">), </span><span class="identifier">B</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">, </span><span class="functiontext">Kinds::Compare::max</span><span class="plain">(</span><span class="identifier">B</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">));</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">)</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">B</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="functiontext">Kinds::Compare::max</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">)) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Fail maximality(A): max($u, $u) = $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">, </span><span class="functiontext">Kinds::Compare::max</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">));</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">)</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">B</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">B</span><span class="plain">, </span><span class="functiontext">Kinds::Compare::max</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">)) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Fail maximality(B): max($u, $u) = $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">, </span><span class="functiontext">Kinds::Compare::max</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">));</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="functiontext">Kinds::Compare::max</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">), </span><span class="identifier">A</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Fail: max($u, $u) = $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">A</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">, </span><span class="functiontext">Kinds::Compare::max</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">));</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP18">§18</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18_6"></a><b>§18.6. </b></p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">SIZE_OF_GRAB_BAG</span><span class="plain"> 11</span>
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Some miscellaneous tests with a grab bag of kinds</span> <span class="cwebmacronumber">18.6</span>> =
|
|
</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">kind</span><span class="plain"> *</span><span class="identifier">tests</span><span class="plain">[</span><span class="constant">SIZE_OF_GRAB_BAG</span><span class="plain">];</span>
|
|
<span class="identifier">tests</span><span class="plain">[0] = </span><span class="identifier">K_number</span><span class="plain">;</span>
|
|
<span class="identifier">tests</span><span class="plain">[1] = </span><span class="identifier">K_container</span><span class="plain">;</span>
|
|
<span class="identifier">tests</span><span class="plain">[2] = </span><span class="identifier">K_door</span><span class="plain">;</span>
|
|
<span class="identifier">tests</span><span class="plain">[3] = </span><span class="identifier">K_thing</span><span class="plain">;</span>
|
|
<span class="identifier">tests</span><span class="plain">[4] = </span><span class="functiontext">Kinds::unary_construction</span><span class="plain">(</span><span class="identifier">CON_list_of</span><span class="plain">, </span><span class="identifier">K_container</span><span class="plain">);</span>
|
|
<span class="identifier">tests</span><span class="plain">[5] = </span><span class="functiontext">Kinds::unary_construction</span><span class="plain">(</span><span class="identifier">CON_list_of</span><span class="plain">, </span><span class="identifier">K_door</span><span class="plain">);</span>
|
|
<span class="identifier">tests</span><span class="plain">[6] = </span><span class="functiontext">Kinds::unary_construction</span><span class="plain">(</span><span class="identifier">CON_list_of</span><span class="plain">, </span><span class="identifier">K_person</span><span class="plain">);</span>
|
|
<span class="identifier">tests</span><span class="plain">[7] = </span><span class="functiontext">Kinds::unary_construction</span><span class="plain">(</span><span class="identifier">CON_list_of</span><span class="plain">, </span><span class="identifier">K_thing</span><span class="plain">);</span>
|
|
<span class="identifier">tests</span><span class="plain">[8] = </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_phrase</span><span class="plain">,</span>
|
|
<span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_TUPLE_ENTRY</span><span class="plain">, </span><span class="identifier">K_door</span><span class="plain">, </span><span class="identifier">K_nil</span><span class="plain">), </span><span class="identifier">K_object</span><span class="plain">);</span>
|
|
<span class="identifier">tests</span><span class="plain">[9] = </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_phrase</span><span class="plain">,</span>
|
|
<span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_TUPLE_ENTRY</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">K_nil</span><span class="plain">), </span><span class="identifier">K_door</span><span class="plain">);</span>
|
|
<span class="identifier">tests</span><span class="plain">[10] = </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_phrase</span><span class="plain">,</span>
|
|
<span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_TUPLE_ENTRY</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">K_nil</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">i</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="constant">SIZE_OF_GRAB_BAG</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=</span><span class="identifier">i</span><span class="plain">+1; </span><span class="identifier">j</span><span class="plain"><</span><span class="constant">SIZE_OF_GRAB_BAG</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">tests</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">tests</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">])) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$u <= $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">tests</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">tests</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">tests</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">], </span><span class="identifier">tests</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$u <= $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">tests</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">], </span><span class="identifier">tests</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">M</span><span class="plain"> = </span><span class="functiontext">Kinds::Compare::max</span><span class="plain">(</span><span class="identifier">tests</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">tests</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">M</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"max($u, $u) = $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">tests</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">tests</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">], </span><span class="identifier">M</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="#SP18">§18</a>.</p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="2-knd.html">Back to 'Kinds'</a></li><li><a href="2-kc2.html">Continue with 'Kind Constructors'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
</main>
|
|
</body>
|
|
</html>
|
|
|