1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-09 02:24:21 +03:00
inform7/docs/kinds-module/2-tlok.html
2020-08-11 23:59:29 +01:00

544 lines
92 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>The Lattice of Kinds</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<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="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
MathJax = {
tex: {
inlineMath: '$', '$'], ['\\(', '\\)'
},
svg: {
fontCache: 'global'
}
};
</script>
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
</script>
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body class="commentary-font">
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-assets/Inform.png" height=72">
</a></h1>
<ul><li><a href="../compiler.html">compiler tools</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="../supervisor-module/index.html">supervisor</a></li>
</ul><h2>Inform7 Modules</h2><ul>
<li><a href="../core-module/index.html">core</a></li>
<li><a href="index.html"><span class="selectedlink">kinds</span></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="../bytecode-module/index.html">bytecode</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../codegen-module/index.html">codegen</a></li>
</ul><h2>Services</h2><ul>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../syntax-module/index.html">syntax</a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../html-module/index.html">html</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="../problems-module/index.html">problems</a></li>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'The Lattice of Kinds' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../compiler.html">Services</a></li><li><a href="index.html">kinds</a></li><li><a href="index.html#2">Chapter 2: Kinds</a></li><li><b>The Lattice of Kinds</b></li></ul></div>
<p class="purpose">Placing a partial order on kinds according to whether one conforms to another.</p>
<ul class="toc"><li><a href="2-tlok.html#SP9">&#167;9. Common code</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1"></a><b>&#167;1. </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 \leq K_R. $$
There are many pairs of kinds where neither is compatible with the other:
for instance, it is true neither that rulebook \(\leq\) text nor that text \(\leq\) rulebook. So
we're using the notation \(\leq\) here by analogy with partially-ordered sets
rather than with numbers. The universe of kinds does indeed form a poset
under this relation:
</p>
<ul class="items"><li>(a) it is reflexive (\(K\leq K\));
</li><li>(b) it is antisymmetric (\(K\leq L\) and \(L\leq K\) imply \(K=L\));
</li><li>(c) it is transitive (\(K\leq L\) and \(L\leq M\) imply \(K\leq M\)).
</li></ul>
<p class="commentary firstcommentary"><a id="SP2"></a><b>&#167;2. </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\leq 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 \(\leq\) text. Compatibility lacks the
elegant formal properties of \(\leq\): for example, "value" is compatible
with "text" which is in turn compatible with "value".
</p>
<p class="commentary">This test is performed by <span class="extract"><span class="extract-syntax">Kinds::compatible</span></span>. As we will see, the two
relations are similarly defined, and they share most of the code.
</p>
<p class="commentary firstcommentary"><a id="SP3"></a><b>&#167;3. </b>A function \(f\) on kinds is covariant if \(K\leq L\) implies \(f(K)\leq f(L)\),
and contravariant if \(K\leq L\) implies \(f(L)\leq 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 code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">COVARIANT</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">CONTRAVARIANT</span><span class="plain-syntax"> -1</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4"></a><b>&#167;4. </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="commentary">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="commentary">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 code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">MAX_KIND_VARIABLES</span><span class="plain-syntax"> </span><span class="constant-syntax">27</span><span class="plain-syntax"> </span><span class="comment-syntax"> we number them from 1 (A) to 26 (Z)</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">values_of_kind_variables</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_KIND_VARIABLES</span><span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5"></a><b>&#167;5. </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 &mdash; that's the <span class="extract"><span class="extract-syntax">MATCH_KIND_VARIABLES_AS_VALUES</span></span> 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
<span class="extract"><span class="extract-syntax">MATCH_KIND_VARIABLES_AS_SYMBOLS</span></span> mode. Or it can match anything
against Q, which is <span class="extract"><span class="extract-syntax">MATCH_KIND_VARIABLES_AS_UNIVERSAL</span></span> mode.
</p>
<p class="commentary">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
<span class="extract"><span class="extract-syntax">MATCH_KIND_VARIABLES_INFERRING_VALUES</span></span> mode.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">MATCH_KIND_VARIABLES_AS_SYMBOLS</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">MATCH_KIND_VARIABLES_INFERRING_VALUES</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">MATCH_KIND_VARIABLES_AS_VALUES</span><span class="plain-syntax"> </span><span class="constant-syntax">2</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">MATCH_KIND_VARIABLES_AS_UNIVERSAL</span><span class="plain-syntax"> </span><span class="constant-syntax">3</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">kind_checker_mode</span><span class="plain-syntax"> = </span><span class="constant-syntax">MATCH_KIND_VARIABLES_AS_SYMBOLS</span><span class="plain-syntax">;</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6"></a><b>&#167;6. </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="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">kind_variable_declaration</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">kv_number</span><span class="plain-syntax">; </span><span class="comment-syntax"> must be from 1 to 26</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">kv_value</span><span class="plain-syntax">; </span><span class="comment-syntax"> must be a definite non-</span><span class="extract"><span class="extract-syntax">NULL</span></span><span class="comment-syntax"> kind</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">kind_variable_declaration</span><span class="plain-syntax"> *</span><span class="identifier-syntax">next</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">kind_variable_declaration</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure kind_variable_declaration is accessed in 3/dmn and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP7"></a><b>&#167;7. </b>It turns out to be useful to be able to "increment" a kind \(K\), by trying to
find the \(S\) such that \(K &lt; S\) but there is no \(S'\) with \(K&lt;S'&lt;S\). This is only
well-defined for kinds of object, and otherwise returns <span class="extract"><span class="extract-syntax">NULL</span></span>.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="function-syntax">Latticework::super</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Latticework::super</span></span>:<br/><a href="2-tlok.html#SP8">&#167;8</a>, <a href="2-tlok.html#SP9_5">&#167;9.5</a><br/>Kinds - <a href="2-knd.html#SP18">&#167;18</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_real_arithmetic_value</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_arithmetic_value</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_enumerated_value</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_sayable_value</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_arithmetic_value</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_sayable_value</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_pointer_value</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_sayable_value</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_sayable_value</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_stored_value</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_stored_value</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_value</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_value</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_nil</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_void</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">HIERARCHY_GET_SUPER_KINDS_CALLBACK</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S</span><span class="plain-syntax"> = </span><span class="identifier-syntax">HIERARCHY_GET_SUPER_KINDS_CALLBACK</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">S</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">S</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-kc.html#SP17" class="function-link"><span class="function-syntax">Kinds::Constructors::compatible</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_real_arithmetic_value</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_real_arithmetic_value</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-kc.html#SP17" class="function-link"><span class="function-syntax">Kinds::Constructors::compatible</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_enumerated_value</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_enumerated_value</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-kc.html#SP17" class="function-link"><span class="function-syntax">Kinds::Constructors::compatible</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_arithmetic_value</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_arithmetic_value</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-kc.html#SP17" class="function-link"><span class="function-syntax">Kinds::Constructors::compatible</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_pointer_value</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_pointer_value</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-kc.html#SP17" class="function-link"><span class="function-syntax">Kinds::Constructors::compatible</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_sayable_value</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_sayable_value</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-kc.html#SP17" class="function-link"><span class="function-syntax">Kinds::Constructors::compatible</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_stored_value</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_stored_value</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_value</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP8"></a><b>&#167;8. </b>The join of \(K_1\lor K_2\) is by definition the kind \(M\) such that
\(K_1\leq M\) and \(K_2\leq M\), and there is no \(M'&lt;M\) with the same property.
Note however:
</p>
<ul class="items"><li>(a) If one of \(K_1\), \(K_2\) uses floating-point and the other doesn't, then
we promote the one which doesn't before taking the join. This is useful
when inferring the kind of a constant list or column which mixes floating-point
and integer literals; recall that <span class="extract"><span class="extract-syntax">number</span></span> \(\not\leq\) <span class="extract"><span class="extract-syntax">real number</span></span>, so
without this promotion there would be no way to join such kinds.
</li><li>(b) The set of kinds is not entirely a semilattice and therefore some joins
can't be performed: in such cases we give up and return <span class="extract"><span class="extract-syntax">value</span></span>, which at
least is \(\geq K_1, K_2\).
</li></ul>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="function-syntax">Latticework::join</span><span class="plain-syntax">(</span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K1</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K2</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="2-tlok.html#SP8" class="function-link"><span class="function-syntax">Latticework::j_or_m</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K1</span><span class="plain-syntax">, </span><span class="identifier-syntax">K2</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="function-syntax">Latticework::meet</span><span class="plain-syntax">(</span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K1</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K2</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="2-tlok.html#SP8" class="function-link"><span class="function-syntax">Latticework::j_or_m</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K1</span><span class="plain-syntax">, </span><span class="identifier-syntax">K2</span><span class="plain-syntax">, -1);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="function-syntax">Latticework::j_or_m</span><span class="plain-syntax">(</span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K1</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K2</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">direction</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">K1</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K2</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">K2</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">kind_constructor</span><span class="plain-syntax"> *</span><span class="identifier-syntax">con</span><span class="plain-syntax"> = </span><span class="identifier-syntax">K1</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">a1</span><span class="plain-syntax"> = </span><a href="2-kc.html#SP13" class="function-link"><span class="function-syntax">Kinds::Constructors::arity</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">con</span><span class="plain-syntax">), </span><span class="identifier-syntax">a2</span><span class="plain-syntax"> = </span><a href="2-kc.html#SP13" class="function-link"><span class="function-syntax">Kinds::Constructors::arity</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K2</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">a1</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">a2</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">K2</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax"> != </span><span class="identifier-syntax">con</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_value</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ka</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_KIND_CONSTRUCTION_ARITY</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">a1</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">con</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">variance</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] == </span><span class="constant-syntax">COVARIANT</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ka</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><a href="2-tlok.html#SP8" class="function-link"><span class="function-syntax">Latticework::j_or_m</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K1</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">K2</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">direction</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ka</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><a href="2-tlok.html#SP8" class="function-link"><span class="function-syntax">Latticework::j_or_m</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K1</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">K2</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], -</span><span class="identifier-syntax">direction</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">a1</span><span class="plain-syntax"> == </span><span class="constant-syntax">1</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="2-knd.html#SP3_3" class="function-link"><span class="function-syntax">Kinds::unary_construction</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">con</span><span class="plain-syntax">, </span><span class="identifier-syntax">ka</span><span class="plain-syntax">[0]);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="2-knd.html#SP3_3" class="function-link"><span class="function-syntax">Kinds::binary_construction</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">con</span><span class="plain-syntax">, </span><span class="identifier-syntax">ka</span><span class="plain-syntax">[0], </span><span class="identifier-syntax">ka</span><span class="plain-syntax">[1]);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K1</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_nil</span><span class="plain-syntax">))) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">direction</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)?</span><span class="identifier-syntax">K2:K1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K2</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_nil</span><span class="plain-syntax">))) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">direction</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)?</span><span class="identifier-syntax">K1:K2</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><a href="3-fv.html#SP3" class="function-link"><span class="function-syntax">Kinds::FloatingPoint::uses_floating_point</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K1</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax"> (</span><a href="3-fv.html#SP3" class="function-link"><span class="function-syntax">Kinds::FloatingPoint::uses_floating_point</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K2</span><span class="plain-syntax">)) &amp;&amp;</span>
<span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><a href="3-fv.html#SP3" class="function-link"><span class="function-syntax">Kinds::FloatingPoint::real_equivalent</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K1</span><span class="plain-syntax">), </span><span class="identifier-syntax">K2</span><span class="plain-syntax">)))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">direction</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)?</span><span class="identifier-syntax">K2:K1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><a href="3-fv.html#SP3" class="function-link"><span class="function-syntax">Kinds::FloatingPoint::uses_floating_point</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K2</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax"> (</span><a href="3-fv.html#SP3" class="function-link"><span class="function-syntax">Kinds::FloatingPoint::uses_floating_point</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K1</span><span class="plain-syntax">)) &amp;&amp;</span>
<span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><a href="3-fv.html#SP3" class="function-link"><span class="function-syntax">Kinds::FloatingPoint::real_equivalent</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K2</span><span class="plain-syntax">), </span><span class="identifier-syntax">K1</span><span class="plain-syntax">)))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">direction</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)?</span><span class="identifier-syntax">K1:K2</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP22" class="function-link"><span class="function-syntax">Kinds::conforms_to</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K1</span><span class="plain-syntax">, </span><span class="identifier-syntax">K2</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">direction</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)?</span><span class="identifier-syntax">K2:K1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP22" class="function-link"><span class="function-syntax">Kinds::conforms_to</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K2</span><span class="plain-syntax">, </span><span class="identifier-syntax">K1</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">direction</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)?</span><span class="identifier-syntax">K1:K2</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">direction</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><span class="identifier-syntax">K1</span><span class="plain-syntax">; </span><span class="identifier-syntax">K</span><span class="plain-syntax">; </span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><a href="2-tlok.html#SP7" class="function-link"><span class="function-syntax">Latticework::super</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP22" class="function-link"><span class="function-syntax">Kinds::conforms_to</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K2</span><span class="plain-syntax">, </span><span class="identifier-syntax">K</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">direction</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)?</span><span class="identifier-syntax">K_value:K_nil</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9"></a><b>&#167;9. Common code. </b>So the following routine tests \(\leq\) if <span class="extract"><span class="extract-syntax">comp</span></span> is <span class="extract"><span class="extract-syntax">FALSE</span></span>, returning
<span class="extract"><span class="extract-syntax">ALWAYS_MATCH</span></span> if and only if \(\leq\) holds; and otherwise it tests compatibility.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Latticework::order_relation</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">Latticework::order_relation</span></span>:<br/><a href="2-tlok.html#SP9_1">&#167;9.1</a>, <a href="2-tlok.html#SP9_4">&#167;9.4</a>, <a href="2-tlok.html#SP9_6_1">&#167;9.6.1</a>, <a href="2-tlok.html#SP9_6_2">&#167;9.6.2</a><br/>Kinds - <a href="2-knd.html#SP22">&#167;22</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">allow_casts</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP9" class="function-link"><span class="function-syntax">Kinds::get_variable_number</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">to</span><span class="plain-syntax">) &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">var_k</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to</span><span class="plain-syntax">, *</span><span class="identifier-syntax">other_k</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tlok.html#SP9_6" class="named-paragraph-link"><span class="named-paragraph">Deal separately with matches against kind variables</span><span class="named-paragraph-number">9.6</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP9" class="function-link"><span class="function-syntax">Kinds::get_variable_number</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">) &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">var_k</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from</span><span class="plain-syntax">, *</span><span class="identifier-syntax">other_k</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tlok.html#SP9_6" class="named-paragraph-link"><span class="named-paragraph">Deal separately with matches against kind variables</span><span class="named-paragraph-number">9.6</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tlok.html#SP9_1" class="named-paragraph-link"><span class="named-paragraph">Deal separately with the sayability of lists</span><span class="named-paragraph-number">9.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tlok.html#SP9_2" class="named-paragraph-link"><span class="named-paragraph">Deal separately with the special role of value</span><span class="named-paragraph-number">9.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tlok.html#SP9_3" class="named-paragraph-link"><span class="named-paragraph">Deal separately with the special role of the unknown kind</span><span class="named-paragraph-number">9.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tlok.html#SP9_4" class="named-paragraph-link"><span class="named-paragraph">The general case of compatibility</span><span class="named-paragraph-number">9.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9_1"></a><b>&#167;9.1. </b>A list is sayable if and only if it is empty, or its contents are sayable.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Deal separately with the sayability of lists</span><span class="named-paragraph-number">9.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><a href="2-knd.html#SP8" class="function-link"><span class="function-syntax">Kinds::get_construct</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">) == </span><span class="identifier-syntax">CON_list_of</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_sayable_value</span><span class="plain-syntax">))) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">CK</span><span class="plain-syntax"> = </span><a href="2-knd.html#SP11" class="function-link"><span class="function-syntax">Kinds::unary_construction_material</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">CK</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_nil</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">CK</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax">; </span><span class="comment-syntax"> for an internal test case making dodgy lists</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="2-tlok.html#SP9" class="function-link"><span class="function-syntax">Latticework::order_relation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">CK</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_sayable_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">allow_casts</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-tlok.html#SP9">&#167;9</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP9_2"></a><b>&#167;9.2. </b>"Value" is special because, for every kind \(K\), we have \(K\leq V\) &mdash; it
represents a supremum in our partially ordered set of kinds.
</p>
<p class="commentary">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 &mdash; 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="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Deal separately with the special role of value</span><span class="named-paragraph-number">9.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_value</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_nil</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-tlok.html#SP9">&#167;9</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP9_3"></a><b>&#167;9.3. </b><span class="extract"><span class="extract-syntax">NULL</span></span> as a kind means "unknown". It's compatible only with itself
and, of course, "value".
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Deal separately with the special role of the unknown kind</span><span class="named-paragraph-number">9.3</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">to</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">to</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">NEVER_MATCH</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-tlok.html#SP9">&#167;9</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP9_4"></a><b>&#167;9.4. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">The general case of compatibility</span><span class="named-paragraph-number">9.4</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">f_a</span><span class="plain-syntax"> = </span><a href="2-kc.html#SP13" class="function-link"><span class="function-syntax">Kinds::Constructors::arity</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">t_a</span><span class="plain-syntax"> = </span><a href="2-kc.html#SP13" class="function-link"><span class="function-syntax">Kinds::Constructors::arity</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">arity</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">f_a</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">t_a</span><span class="plain-syntax">)?</span><span class="identifier-syntax">f_a:t_a</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">o</span><span class="plain-syntax"> = </span><span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax"> != </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">o</span><span class="plain-syntax"> = </span><a href="2-tlok.html#SP9_5" class="function-link"><span class="function-syntax">Latticework::construct_viable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">allow_casts</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">, </span><span class="identifier-syntax">this_o</span><span class="plain-syntax"> = </span><span class="constant-syntax">NEVER_MATCH</span><span class="plain-syntax">, </span><span class="identifier-syntax">fallen</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">arity</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-kc.html#SP13" class="function-link"><span class="function-syntax">Kinds::Constructors::variance</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">) == </span><span class="constant-syntax">COVARIANT</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">this_o</span><span class="plain-syntax"> = </span><a href="2-tlok.html#SP9" class="function-link"><span class="function-syntax">Latticework::order_relation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">allow_casts</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">this_o</span><span class="plain-syntax"> = </span><a href="2-tlok.html#SP9" class="function-link"><span class="function-syntax">Latticework::order_relation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">allow_casts</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">this_o</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">NEVER_MATCH:</span><span class="plain-syntax"> </span><span class="identifier-syntax">o</span><span class="plain-syntax"> = </span><span class="identifier-syntax">this_o</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">SOMETIMES_MATCH:</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">o</span><span class="plain-syntax"> != </span><span class="constant-syntax">NEVER_MATCH</span><span class="plain-syntax">) { </span><span class="identifier-syntax">o</span><span class="plain-syntax"> = </span><span class="identifier-syntax">this_o</span><span class="plain-syntax">; </span><span class="identifier-syntax">fallen</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; } </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">o</span><span class="plain-syntax"> == </span><span class="identifier-syntax">fallen</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax"> != </span><span class="identifier-syntax">CON_list_of</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">NEVER_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">o</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-tlok.html#SP9">&#167;9</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP9_5"></a><b>&#167;9.5. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Latticework::construct_viable</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">Latticework::construct_viable</span></span>:<br/><a href="2-tlok.html#SP9_4">&#167;9.4</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">allow_casts</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">K</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">to</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><a href="2-tlok.html#SP7" class="function-link"><span class="function-syntax">Latticework::super</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">allow_casts</span><span class="plain-syntax">) &amp;&amp; (</span><a href="2-kc.html#SP15" class="function-link"><span class="function-syntax">Kinds::Constructors::find_cast</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">)))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">K</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">HIERARCHY_ALLOWS_SOMETIMES_MATCH_KINDS_CALLBACK</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">HIERARCHY_ALLOWS_SOMETIMES_MATCH_KINDS_CALLBACK</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">SOMETIMES_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifndef</span><span class="plain-syntax"> </span><span class="identifier-syntax">HIERARCHY_ALLOWS_SOMETIMES_MATCH_KINDS_CALLBACK</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">SOMETIMES_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><a href="2-tlok.html#SP7" class="function-link"><span class="function-syntax">Latticework::super</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">NEVER_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9_6"></a><b>&#167;9.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="commentary">the first appearance of "K" will be an ordinary use of a kind variable,
whereas the second has the declaration "value" &mdash; meaning that it can
become any kind matching "value". (It could alternatively have had a
more restrictive declaration like "arithmetic value".)
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Deal separately with matches against kind variables</span><span class="named-paragraph-number">9.6</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><span class="identifier-syntax">kind_checker_mode</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">MATCH_KIND_VARIABLES_AS_SYMBOLS:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP9" class="function-link"><span class="function-syntax">Kinds::get_variable_number</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">other_k</span><span class="plain-syntax">) ==</span>
<span class="plain-syntax"> </span><a href="2-knd.html#SP9" class="function-link"><span class="function-syntax">Kinds::get_variable_number</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">var_k</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">NEVER_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">MATCH_KIND_VARIABLES_AS_UNIVERSAL:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">vn</span><span class="plain-syntax"> = </span><a href="2-knd.html#SP9" class="function-link"><span class="function-syntax">Kinds::get_variable_number</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">var_k</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP9" class="function-link"><span class="function-syntax">Kinds::get_variable_stipulation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">var_k</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tlok.html#SP9_6_1" class="named-paragraph-link"><span class="named-paragraph">Act on a declaration usage, where inference is allowed</span><span class="named-paragraph-number">9.6.1</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tlok.html#SP9_6_2" class="named-paragraph-link"><span class="named-paragraph">Act on an ordinary usage, where inference is not allowed</span><span class="named-paragraph-number">9.6.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-tlok.html#SP9">&#167;9</a> (twice).</li></ul>
<p class="commentary firstcommentary"><a id="SP9_6_1"></a><b>&#167;9.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="commentary">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="commentary">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 <span class="extract"><span class="extract-syntax">MATCH_KIND_VARIABLES_INFERRING_VALUES</span></span> mode; on the second pass, it
does the same in <span class="extract"><span class="extract-syntax">MATCH_KIND_VARIABLES_AS_VALUES</span></span> 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="commentary">The following shows what happens matching "values of kind K", which is
a declaration usage of the variable K.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Act on a declaration usage, where inference is allowed</span><span class="named-paragraph-number">9.6.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><span class="identifier-syntax">kind_checker_mode</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">MATCH_KIND_VARIABLES_INFERRING_VALUES:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-tlok.html#SP9" class="function-link"><span class="function-syntax">Latticework::order_relation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">other_k</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><a href="2-knd.html#SP9" class="function-link"><span class="function-syntax">Kinds::get_variable_stipulation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">var_k</span><span class="plain-syntax">), </span><span class="identifier-syntax">allow_casts</span><span class="plain-syntax">) != </span><span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">NEVER_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">KIND_CHECKING</span><span class="plain-syntax">, </span><span class="string-syntax">"Inferring kind variable %d from %u (declaration %u)\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">vn</span><span class="plain-syntax">, </span><span class="identifier-syntax">other_k</span><span class="plain-syntax">, </span><a href="2-knd.html#SP9" class="function-link"><span class="function-syntax">Kinds::get_variable_stipulation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">var_k</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">values_of_kind_variables</span><span class="plain-syntax">[</span><span class="identifier-syntax">vn</span><span class="plain-syntax">] = </span><span class="identifier-syntax">other_k</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">kind_variable_declaration</span><span class="plain-syntax"> *</span><span class="identifier-syntax">kvd</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">kind_variable_declaration</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">kvd</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kv_number</span><span class="plain-syntax"> = </span><span class="identifier-syntax">vn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">kvd</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kv_value</span><span class="plain-syntax"> = </span><span class="identifier-syntax">other_k</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">kvd</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">MATCH_KIND_VARIABLES_AS_VALUES:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-tlok.html#SP9_6">&#167;9.6</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP9_6_2"></a><b>&#167;9.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="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Act on an ordinary usage, where inference is not allowed</span><span class="named-paragraph-number">9.6.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><span class="identifier-syntax">kind_checker_mode</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">MATCH_KIND_VARIABLES_INFERRING_VALUES:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">MATCH_KIND_VARIABLES_AS_VALUES:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">KIND_CHECKING</span><span class="plain-syntax">, </span><span class="string-syntax">"Checking %u against kind variable %d (=%u)\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">other_k</span><span class="plain-syntax">, </span><span class="identifier-syntax">vn</span><span class="plain-syntax">, </span><span class="identifier-syntax">values_of_kind_variables</span><span class="plain-syntax">[</span><span class="identifier-syntax">vn</span><span class="plain-syntax">]);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-tlok.html#SP9" class="function-link"><span class="function-syntax">Latticework::order_relation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">other_k</span><span class="plain-syntax">, </span><span class="identifier-syntax">values_of_kind_variables</span><span class="plain-syntax">[</span><span class="identifier-syntax">vn</span><span class="plain-syntax">], </span><span class="identifier-syntax">allow_casts</span><span class="plain-syntax">) == </span><span class="constant-syntax">NEVER_MATCH</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">NEVER_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-tlok.html#SP9_6">&#167;9.6</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP10"></a><b>&#167;10. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Latticework::show_variables</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Variables: "</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax">=1; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;=26; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><span class="identifier-syntax">values_of_kind_variables</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">K</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">continue</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"%c=%u "</span><span class="plain-syntax">, </span><span class="character-syntax">'A'</span><span class="plain-syntax">+</span><span class="identifier-syntax">i</span><span class="plain-syntax">-1, </span><span class="identifier-syntax">K</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"\n"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Latticework::show_frame_variables</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">shown</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=1; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;=26; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><a href="2-knd.html#SP20" class="function-link"><span class="function-syntax">Kinds::variable_from_context</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">K</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">shown</span><span class="plain-syntax">++ == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">MATCHING</span><span class="plain-syntax">, </span><span class="string-syntax">"Stack frame uses kind variables: "</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">MATCHING</span><span class="plain-syntax">, </span><span class="string-syntax">"%c=%u "</span><span class="plain-syntax">, </span><span class="character-syntax">'A'</span><span class="plain-syntax">+</span><span class="identifier-syntax">i</span><span class="plain-syntax">-1, </span><span class="identifier-syntax">K</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">shown</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">MATCHING</span><span class="plain-syntax">, </span><span class="string-syntax">"Stack frame sets no kind variables"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">MATCHING</span><span class="plain-syntax">, </span><span class="string-syntax">"\n"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="2-fk.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-km.html">1</a></li><li class="progresscurrentchapter">2</li><li class="progresssection"><a href="2-knd.html">knd</a></li><li class="progresssection"><a href="2-fk.html">fk</a></li><li class="progresscurrent">tlok</li><li class="progresssection"><a href="2-kc.html">kc</a></li><li class="progresssection"><a href="2-uk.html">uk</a></li><li class="progresssection"><a href="2-dk.html">dk</a></li><li class="progresschapter"><a href="3-dmn.html">3</a></li><li class="progresschapter"><a href="4-kf.html">4</a></li><li class="progressnext"><a href="2-kc.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>