mirror of
https://github.com/ganelson/inform.git
synced 2024-07-16 22:14:23 +03:00
544 lines
92 KiB
HTML
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">§9. Common code</a></li></ul><hr class="tocbar">
|
||
|
|
||
|
<p class="commentary firstcommentary"><a id="SP1"></a><b>§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>§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>§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>§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>§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 — 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>§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>§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 < S\) but there is no \(S'\) with \(K<S'<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">§8</a>, <a href="2-tlok.html#SP9_5">§9.5</a><br/>Kinds - <a href="2-knd.html#SP18">§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">-></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">-></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">-></span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_enumerated_value</span><span class="plain-syntax">-></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">-></span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_arithmetic_value</span><span class="plain-syntax">-></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">-></span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_pointer_value</span><span class="plain-syntax">-></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">-></span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_sayable_value</span><span class="plain-syntax">-></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">-></span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_stored_value</span><span class="plain-syntax">-></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>§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'<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">-></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">-></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"> > </span><span class="constant-syntax">0</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">a2</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">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">K2</span><span class="plain-syntax">-></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"><</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">-></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">-></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">-></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">-></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">-></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"> > </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"> > </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">) &&</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="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"> > </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">) &&</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="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"> > </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"> > </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"> > </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"> > </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"> > </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>§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">§9.1</a>, <a href="2-tlok.html#SP9_4">§9.4</a>, <a href="2-tlok.html#SP9_6_1">§9.6.1</a>, <a href="2-tlok.html#SP9_6_2">§9.6.2</a><br/>Kinds - <a href="2-knd.html#SP22">§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">) > </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">) > </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>§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">) &&</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">§9</a>.</li></ul>
|
||
|
<p class="commentary firstcommentary"><a id="SP9_2"></a><b>§9.2. </b>"Value" is special because, for every kind \(K\), we have \(K\leq V\) — 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 — 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">§9</a>.</li></ul>
|
||
|
<p class="commentary firstcommentary"><a id="SP9_3"></a><b>§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">) && (</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">§9</a>.</li></ul>
|
||
|
<p class="commentary firstcommentary"><a id="SP9_4"></a><b>§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">-></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">-></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"> < </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">-></span><span class="element-syntax">construct</span><span class="plain-syntax"> != </span><span class="identifier-syntax">to</span><span class="plain-syntax">-></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"><</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">-></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">-></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">-></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">-></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">-></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">) && (</span><span class="identifier-syntax">to</span><span class="plain-syntax">-></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">§9</a>.</li></ul>
|
||
|
<p class="commentary firstcommentary"><a id="SP9_5"></a><b>§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">§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">) && (</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">-></span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">to</span><span class="plain-syntax">-></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>§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" — 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">§9</a> (twice).</li></ul>
|
||
|
<p class="commentary firstcommentary"><a id="SP9_6_1"></a><b>§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">-></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">-></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">-></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">§9.6</a>.</li></ul>
|
||
|
<p class="commentary firstcommentary"><a id="SP9_6_2"></a><b>§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">§9.6</a>.</li></ul>
|
||
|
<p class="commentary firstcommentary"><a id="SP10"></a><b>§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"><=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"><=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">❮</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">❯</a></li></ul></div>
|
||
|
</nav><!--End of weave-->
|
||
|
|
||
|
</main>
|
||
|
</body>
|
||
|
</html>
|
||
|
|