1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 00:24:22 +03:00
inform7/docs/kinds-module/2-knd.html

767 lines
147 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>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>
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">
<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>
<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="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../indocn.html">indoc</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
<li><a href="../inrtpsn.html">inrtps</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=18> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="../../../inweb/index.html">inweb</a></li>
<li><a href="../../../intest/index.html">intest</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Kinds' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../services.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>Kinds</b></li></ul></div>
<p class="purpose">To build tree structures which represent Inform's universe of kinds.</p>
<ul class="toc"><li><a href="2-knd.html#SP1">&#167;1. Construction</a></li><li><a href="2-knd.html#SP7">&#167;7. Constructing kinds for functions</a></li><li><a href="2-knd.html#SP8">&#167;8. Constructing kinds for pairs</a></li><li><a href="2-knd.html#SP9">&#167;9. Iterating through kinds</a></li><li><a href="2-knd.html#SP11">&#167;11. Annotations of kinds</a></li><li><a href="2-knd.html#SP16">&#167;16. Traversing the tree</a></li><li><a href="2-knd.html#SP17">&#167;17. Kind variable substitution</a></li><li><a href="2-knd.html#SP18">&#167;18. Weakening</a></li><li><a href="2-knd.html#SP19">&#167;19. Property dereferencing</a></li><li><a href="2-knd.html#SP20">&#167;20. Creating new base kind constructors</a></li><li><a href="2-knd.html#SP21">&#167;21. Making subkinds</a></li><li><a href="2-knd.html#SP22">&#167;22. Annotating vocabulary</a></li><li><a href="2-knd.html#SP23">&#167;23. From context</a></li><li><a href="2-knd.html#SP24">&#167;24. Equality</a></li><li><a href="2-knd.html#SP25">&#167;25. Conformance and compatibility</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Construction. </b>Kinds are represented by pointers to trees made up of <a href="2-knd.html#SP1" class="internal">kind</a> objects, like so:
</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</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">kind_constructor</span><span class="plain-syntax"> *</span><span class="identifier-syntax">construct</span><span class="plain-syntax">; </span><span class="comment-syntax"> which can never be </span><span class="extract"><span class="extract-syntax">NULL</span></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">kind_variable_number</span><span class="plain-syntax">; </span><span class="comment-syntax"> only used if construct is </span><span class="extract"><span class="extract-syntax">CON_KIND_VARIABLE</span></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">unit_sequence</span><span class="plain-syntax"> *</span><span class="identifier-syntax">intermediate_result</span><span class="plain-syntax">; </span><span class="comment-syntax"> only used if construct is </span><span class="extract"><span class="extract-syntax">CON_INTERMEDIATE</span></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">kc_args</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_KIND_CONSTRUCTION_ARITY</span><span class="plain-syntax">]; </span><span class="comment-syntax"> used if arity positive, or for </span><span class="extract"><span class="extract-syntax">CON_KIND_VARIABLE</span></span>
<span class="plain-syntax">} </span><span class="reserved-syntax">kind</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure kind is accessed in 2/fk, 2/tlok, 2/uk, 3/fv, 4/st, 4/kc2 and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>Some kinds, like <span class="extract"><span class="extract-syntax">number</span></span>, are atomic while others, like <span class="extract"><span class="extract-syntax">relation of numbers to texts</span></span>,
are composite. Each <a href="2-knd.html#SP1" class="internal">kind</a> object is formally a "construction" resulting from
applying a <a href="4-kc2.html#SP2" class="internal">kind_constructor</a> to other kinds. Each different possible constructor
has a fixed "arity", the number of other kinds it builds on. For example, to make
the kind <span class="extract"><span class="extract-syntax">relation of texts to lists of times</span></span>, we need four constructions in
a row:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> (nothing) --&gt; text</span>
<span class="plain-syntax"> (nothing) --&gt; time</span>
<span class="plain-syntax"> time --&gt; list of times</span>
<span class="plain-syntax"> text, list of times --&gt; relation of texts to lists of times</span>
</pre>
<p class="commentary">At each step there is only a finite choice of possible "kind constructions"
which can be made, but since there can in principle be an unlimited number
of steps, the set of all possible kinds is infinite. At each step we make
use of 0, 1 or 2 existing kinds to make a new one: this number (0, 1 or 2)
is the "arity" of the construction. These four steps have arities 0, 0, 1, 2,
and use the constructors "text", "time", "list of ..." and "relation of ... to ...".
</p>
<p class="commentary">We will often use the word "base" to refer to arity-0 constructors
(or to the kinds which use them): thus, "text" and "time" are bases,
but "list of ..." is not. We call constructors of higher arity "proper".
</p>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b>Here is <a href="../kinds-test/index.html" class="internal">kinds-test</a> exercising the construction system. Note that
it has "functions" to extract the first and second term of a construction.
(The REPL language of <a href="../kinds-test/index.html" class="internal">kinds-test</a> has quite a number of functions like
this, for testing different features of <a href="index.html" class="internal">kinds</a>.)
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">'</span><span class="element-syntax">X = object</span><span class="plain-syntax">':</span><span class="string-syntax"> object</span>
<span class="plain-syntax">'</span><span class="element-syntax">first term of X</span><span class="plain-syntax">':</span><span class="string-syntax"> nothing</span>
<span class="plain-syntax">'</span><span class="element-syntax">second term of X</span><span class="plain-syntax">':</span><span class="string-syntax"> nothing</span>
<span class="plain-syntax">'</span><span class="element-syntax">Y = list of numbers</span><span class="plain-syntax">':</span><span class="string-syntax"> list of numbers</span>
<span class="plain-syntax">'</span><span class="element-syntax">first term of Y</span><span class="plain-syntax">':</span><span class="string-syntax"> number</span>
<span class="plain-syntax">'</span><span class="element-syntax">second term of Y</span><span class="plain-syntax">':</span><span class="string-syntax"> nothing</span>
<span class="plain-syntax">'</span><span class="element-syntax">Z = relation of texts to numbers</span><span class="plain-syntax">':</span><span class="string-syntax"> relation of texts to numbers</span>
<span class="plain-syntax">'</span><span class="element-syntax">first term of Z</span><span class="plain-syntax">':</span><span class="string-syntax"> text</span>
<span class="plain-syntax">'</span><span class="element-syntax">second term of Z</span><span class="plain-syntax">':</span><span class="string-syntax"> number</span>
<span class="plain-syntax">'</span><span class="element-syntax">W = phrase (relation of texts to numbers, text) -&gt; truth state</span><span class="plain-syntax">':</span><span class="string-syntax"> phrase (relation of texts to numbers, text) -&gt; truth state</span>
<span class="plain-syntax">'</span><span class="element-syntax">first term of W</span><span class="plain-syntax">':</span><span class="string-syntax"> relation of texts to numbers, text</span>
<span class="plain-syntax">'</span><span class="element-syntax">first term of first term of W</span><span class="plain-syntax">':</span><span class="string-syntax"> relation of texts to numbers</span>
<span class="plain-syntax">'</span><span class="element-syntax">first term of first term of first term of W</span><span class="plain-syntax">':</span><span class="string-syntax"> text</span>
<span class="plain-syntax">'</span><span class="element-syntax">second term of first term of first term of W</span><span class="plain-syntax">':</span><span class="string-syntax"> number</span>
<span class="plain-syntax">'</span><span class="element-syntax">second term of first term of W</span><span class="plain-syntax">':</span><span class="string-syntax"> text</span>
<span class="plain-syntax">'</span><span class="element-syntax">second term of W</span><span class="plain-syntax">':</span><span class="string-syntax"> truth state</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>In principle we could imagine constructors needing arbitrarily large
arity, or needing different arity in different usages, so the scheme of
having fixed arities in the range 0 to 2 looks limited. In practice we get
around that by using "punctuation nodes" in a kind tree. For example,
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> function ... -&gt; ...</span>
<span class="plain-syntax"> CON_TUPLE_ENTRY</span>
<span class="plain-syntax"> text</span>
<span class="plain-syntax"> CON_TUPLE_ENTRY</span>
<span class="plain-syntax"> text</span>
<span class="plain-syntax"> CON_VOID</span>
<span class="plain-syntax"> number</span>
</pre>
<p class="commentary">represents <span class="extract"><span class="extract-syntax">function (text, text) -&gt; number</span></span>. Note two special constructors
used here: <span class="extract"><span class="extract-syntax">CON_TUPLE_ENTRY</span></span> and <span class="extract"><span class="extract-syntax">CON_NIL</span></span>. These cannot occur in isolation.
No Inform variable can have kind <span class="extract"><span class="extract-syntax">CON_TUPLE_ENTRY</span></span>, for example.
</p>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. </b>We keep some statistics for tracking memory usage:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_base_kinds_created</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_intermediate_kinds_created</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_constructed_kinds_created</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. </b>All kind structures are obtained by one of the following. First, a base
construction, one with arity 0. This makes a kind tree with a single leaf
node, of course, and that's something we need very often. So we create it
only on the first request, and cache the pointer to it with the constructor;
we can then use that same pointer on all subsequent requests.
</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">Kinds::base_construction</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">Kinds::base_construction</span></span>:<br/><a href="2-knd.html#SP10">&#167;10</a>, <a href="2-knd.html#SP20">&#167;20</a><br/>Describing Kinds - <a href="2-dk.html#SP10">&#167;10</a><br/>Neptune Syntax - <a href="4-ns.html#SP5_2">&#167;5.2</a><br/>Star Templates - <a href="4-st.html#SP4">&#167;4</a><br/>Kind Commands - <a href="4-kc.html#SP1_4">&#167;1.4</a><br/>Kind Constructors - <a href="4-kc2.html#SP2">&#167;2</a>, <a href="4-kc2.html#SP9">&#167;9</a>, <a href="4-kc2.html#SP9_1">&#167;9.1</a></span></button><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="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="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"impossible construction"</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="identifier-syntax">CON_KIND_VARIABLE</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">con</span><span class="plain-syntax"> == </span><span class="identifier-syntax">CON_INTERMEDIATE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"forbidden construction"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><a href="4-kc2.html#SP15" class="function-link"><span class="function-syntax">KindConstructors::arity</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">con</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</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">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">con</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><a href="2-knd.html#SP6_3" class="function-link"><span class="function-syntax">Kinds::unary_con</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">con</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><a href="2-knd.html#SP6_3" class="function-link"><span class="function-syntax">Kinds::unary_con</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">con</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">case</span><span class="plain-syntax"> </span><span class="constant-syntax">2</span><span class="plain-syntax">: </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="2-knd.html#SP6_3" class="function-link"><span class="function-syntax">Kinds::binary_con</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">con</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_value</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="plain-syntax"> </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> **</span><span class="identifier-syntax">cache</span><span class="plain-syntax"> = </span><a href="4-kc2.html#SP15" class="function-link"><span class="function-syntax">KindConstructors::cache_location</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">con</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">cache</span><span class="plain-syntax">) { </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">cache</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> *</span><span class="identifier-syntax">cache</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="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-knd.html#SP6_4" class="named-paragraph-link"><span class="named-paragraph">Create a raw kind structure</span><span class="named-paragraph-number">6.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax"> = </span><span class="identifier-syntax">con</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">cache</span><span class="plain-syntax">) *</span><span class="identifier-syntax">cache</span><span class="plain-syntax"> = </span><span class="identifier-syntax">K</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">no_base_kinds_created</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>
</pre>
<p class="commentary firstcommentary"><a id="SP6_1" class="paragraph-anchor"></a><b>&#167;6.1. </b>As noted above, <span class="extract"><span class="extract-syntax">CON_INTERMEDIATE</span></span> is used to store intermediate results
of calculations that are never accessible to outside source text, and have
kinds which couldn't be represented there. For example, if we evaluate
$$ E = mc^2 $$
then we may have perfectly good kinds of value to store energy, mass and
velocity, but have no kind of value for \(c^2\), a velocity squared. Such
evanescent kinds are given the special constructor <span class="extract"><span class="extract-syntax">CON_INTERMEDIATE</span></span>.
These are needed relatively seldom and are not cached.
</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">Kinds::intermediate_construction</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">Kinds::intermediate_construction</span></span>:<br/>Dimensions - <a href="3-dmn.html#SP31_4">&#167;31.4</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">unit_sequence</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ik</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">ik</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"made unknown as Kinds::intermediate_construction"</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="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-knd.html#SP6_4" class="named-paragraph-link"><span class="named-paragraph">Create a raw kind structure</span><span class="named-paragraph-number">6.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CON_INTERMEDIATE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">intermediate_result</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">unit_sequence</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> *(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">intermediate_result</span><span class="plain-syntax">) = *</span><span class="identifier-syntax">ik</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">no_intermediate_kinds_created</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>
</pre>
<p class="commentary firstcommentary"><a id="SP6_2" class="paragraph-anchor"></a><b>&#167;6.2. </b>The following constructs "formal variables", that is, placeholders for the
kinds whose values will be stored in the kind variables <span class="extract"><span class="extract-syntax">A</span></span> to <span class="extract"><span class="extract-syntax">Z</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">Kinds::var_construction</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">Kinds::var_construction</span></span>:<br/>Describing Kinds - <a href="2-dk.html#SP6">&#167;6</a>, <a href="2-dk.html#SP9">&#167;9</a>, <a href="2-dk.html#SP18">&#167;18</a>, <a href="2-dk.html#SP19">&#167;19</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">N</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">declaration</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">N</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">N</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">MAX_KIND_VARIABLES</span><span class="plain-syntax">)) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"bad kind variable"</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="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-knd.html#SP6_4" class="named-paragraph-link"><span class="named-paragraph">Create a raw kind structure</span><span class="named-paragraph-number">6.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CON_KIND_VARIABLE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_variable_number</span><span class="plain-syntax"> = </span><span class="identifier-syntax">N</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">declaration</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>
</pre>
<p class="commentary firstcommentary"><a id="SP6_3" class="paragraph-anchor"></a><b>&#167;6.3. </b>That completes the possible base constructions. Proper constructions are made
using the following. For example,
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> Kinds::unary_con(CON_list_of, K_number)</span>
</pre>
<p class="commentary">produces a kind structure meaning "list of numbers". This is not cached
anywhere, so a second request for the same thing will produce a different copy
in memory of the same structure. Profiling shows that little memory is in
practice wasted.
</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">Kinds::unary_con</span><button class="popup" onclick="togglePopup('usagePopup4')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup4">Usage of <span class="code-font"><span class="function-syntax">Kinds::unary_con</span></span>:<br/><a href="2-knd.html#SP6">&#167;6</a>, <a href="2-knd.html#SP17">&#167;17</a>, <a href="2-knd.html#SP18">&#167;18</a>, <a href="2-knd.html#SP19">&#167;19</a><br/>The Lattice of Kinds - <a href="2-tlok.html#SP7">&#167;7</a><br/>Describing Kinds - <a href="2-dk.html#SP11_10">&#167;11.10</a>, <a href="2-dk.html#SP12_1">&#167;12.1</a></span></button><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="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">X</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="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-kc2.html#SP15" class="function-link"><span class="function-syntax">KindConstructors::arity</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">con</span><span class="plain-syntax">) != </span><span class="constant-syntax">1</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"bad unary construction"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-knd.html#SP6_4" class="named-paragraph-link"><span class="named-paragraph">Create a raw kind structure</span><span class="named-paragraph-number">6.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax"> = </span><span class="identifier-syntax">con</span><span class="plain-syntax">; </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">X</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">no_constructed_kinds_created</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="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="function-syntax">Kinds::binary_con</span><button class="popup" onclick="togglePopup('usagePopup5')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup5">Usage of <span class="code-font"><span class="function-syntax">Kinds::binary_con</span></span>:<br/><a href="2-knd.html#SP6">&#167;6</a>, <a href="2-knd.html#SP7">&#167;7</a>, <a href="2-knd.html#SP8">&#167;8</a>, <a href="2-knd.html#SP17">&#167;17</a>, <a href="2-knd.html#SP18">&#167;18</a>, <a href="2-knd.html#SP19">&#167;19</a><br/>The Lattice of Kinds - <a href="2-tlok.html#SP7">&#167;7</a><br/>Describing Kinds - <a href="2-dk.html#SP11_2">&#167;11.2</a>, <a href="2-dk.html#SP11_3">&#167;11.3</a>, <a href="2-dk.html#SP11_4">&#167;11.4</a>, <a href="2-dk.html#SP11_5">&#167;11.5</a>, <a href="2-dk.html#SP11_6">&#167;11.6</a>, <a href="2-dk.html#SP11_7">&#167;11.7</a>, <a href="2-dk.html#SP11_8">&#167;11.8</a>, <a href="2-dk.html#SP11_9">&#167;11.9</a>, <a href="2-dk.html#SP12_1">&#167;12.1</a>, <a href="2-dk.html#SP13">&#167;13</a></span></button><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="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">Y</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="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-kc2.html#SP15" class="function-link"><span class="function-syntax">KindConstructors::arity</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">con</span><span class="plain-syntax">) != </span><span class="constant-syntax">2</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"bad binary construction"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-knd.html#SP6_4" class="named-paragraph-link"><span class="named-paragraph">Create a raw kind structure</span><span class="named-paragraph-number">6.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax"> = </span><span class="identifier-syntax">con</span><span class="plain-syntax">; </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">X</span><span class="plain-syntax">; </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">Y</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">no_constructed_kinds_created</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="identifier-syntax">CON_phrase</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">X</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">Y</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">)) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"bad function kind"</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">Y</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax"> == </span><span class="identifier-syntax">CON_TUPLE_ENTRY</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"bizarre"</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">K</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6_4" class="paragraph-anchor"></a><b>&#167;6.4. </b>We've now seen the only ways to create a kind structure, and they share the
following initialisation:
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Create a raw kind structure</span><span class="named-paragraph-number">6.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="identifier-syntax">K</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">kind</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">intermediate_result</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">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_variable_number</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">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">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="constant-syntax">MAX_KIND_CONSTRUCTION_ARITY</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-knd.html#SP6">&#167;6</a>, <a href="2-knd.html#SP6_1">&#167;6.1</a>, <a href="2-knd.html#SP6_2">&#167;6.2</a>, <a href="2-knd.html#SP6_3">&#167;6.3</a> (twice).</li></ul>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. Constructing kinds for functions. </b>The following uses the above methods to put together the kind of a function,
making use of the punctuation nodes <span class="extract"><span class="extract-syntax">CON_TUPLE_ENTRY</span></span> and <span class="extract"><span class="extract-syntax">CON_NIL</span></span>. Note
that we use <span class="extract"><span class="extract-syntax">K_nil</span></span> to represent the absence of a return kind (the "nothing"
in a function to nothing). Note also that a function from X to Y, with just
one argument, comes out as:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> CON_phrase</span>
<span class="plain-syntax"> CON_TUPLE_ENTRY</span>
<span class="plain-syntax"> X</span>
<span class="plain-syntax"> CON_VOID</span>
<span class="plain-syntax"> Y</span>
</pre>
<p class="commentary">rather than as:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> CON_phrase</span>
<span class="plain-syntax"> X</span>
<span class="plain-syntax"> Y</span>
</pre>
<p class="commentary">(It's more convenient to have a predictable form than to save on kind nodes.)
</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">Kinds::function_kind</span><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_args</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> **</span><span class="identifier-syntax">args</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">return_K</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">arguments_K</span><span class="plain-syntax"> = </span><span class="identifier-syntax">K_void</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">=</span><span class="identifier-syntax">no_args</span><span class="plain-syntax">-1; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&gt;=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">--)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">arguments_K</span><span class="plain-syntax"> = </span><a href="2-knd.html#SP6_3" class="function-link"><span class="function-syntax">Kinds::binary_con</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">CON_TUPLE_ENTRY</span><span class="plain-syntax">, </span><span class="identifier-syntax">args</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">arguments_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">return_K</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">return_K</span><span class="plain-syntax"> = </span><span class="identifier-syntax">K_nil</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-knd.html#SP6_3" class="function-link"><span class="function-syntax">Kinds::binary_con</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">CON_phrase</span><span class="plain-syntax">, </span><span class="identifier-syntax">arguments_K</span><span class="plain-syntax">, </span><span class="identifier-syntax">return_K</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>&#167;8. Constructing kinds for pairs. </b>Similarly, but more simply, here is the kind for an ordered pair of values:
</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">Kinds::pair_kind</span><span class="plain-syntax">(</span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">Y</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-knd.html#SP6_3" class="function-link"><span class="function-syntax">Kinds::binary_con</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">CON_combination</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="identifier-syntax">Y</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>&#167;9. Iterating through kinds. </b>It's clearly not literally possible to iterate through kinds (there are
infinitely many) or even through base kinds (since intermediate and variable
constructions confuse the picture), but it does turn out to be convenient
to iterate through all possible constructions, wrapped up into base kind
format. Thus:
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="identifier-syntax">LOOP_OVER_BASE_KINDS</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">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">K</span><span class="plain-syntax">=</span><a href="2-knd.html#SP10" class="function-link"><span class="function-syntax">Kinds::first_base_k</span></a><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-knd.html#SP10" class="function-link"><span class="function-syntax">Kinds::next_base_k</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">))</span>
</pre>
<p class="commentary firstcommentary"><a id="SP10" class="paragraph-anchor"></a><b>&#167;10. </b>This requires the following iterator routines. Note that these will
produce base constructions using constructors of higher arity than that
(for example, it will make "list of K" as a base kind, with no arguments);
this would be unsuitable as the kind of any data, but is convenient for
drawing up the index, and so on.
</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">Kinds::first_base_k</span><button class="popup" onclick="togglePopup('usagePopup6')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup6">Usage of <span class="code-font"><span class="function-syntax">Kinds::first_base_k</span></span>:<br/><a href="2-knd.html#SP9">&#167;9</a></span></button><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">kind_constructor</span><span class="plain-syntax"> *</span><span class="identifier-syntax">con</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">con</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind_constructor</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="identifier-syntax">CON_KIND_VARIABLE</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">con</span><span class="plain-syntax"> != </span><span class="identifier-syntax">CON_INTERMEDIATE</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-knd.html#SP6" class="function-link"><span class="function-syntax">Kinds::base_construction</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">con</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">NULL</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">Kinds::next_base_k</span><button class="popup" onclick="togglePopup('usagePopup7')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup7">Usage of <span class="code-font"><span class="function-syntax">Kinds::next_base_k</span></span>:<br/><a href="2-knd.html#SP9">&#167;9</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><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">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">kind_constructor</span><span class="plain-syntax"> *</span><span class="identifier-syntax">con</span><span class="plain-syntax"> = </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">do</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">con</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NEXT_OBJECT</span><span class="plain-syntax">(</span><span class="identifier-syntax">con</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind_constructor</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">con</span><span class="plain-syntax"> == </span><span class="identifier-syntax">CON_KIND_VARIABLE</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">con</span><span class="plain-syntax"> == </span><span class="identifier-syntax">CON_INTERMEDIATE</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="identifier-syntax">NULL</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">return</span><span class="plain-syntax"> </span><a href="2-knd.html#SP6" class="function-link"><span class="function-syntax">Kinds::base_construction</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">con</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP11" class="paragraph-anchor"></a><b>&#167;11. Annotations of kinds. </b>Most of the time, the only annotation of a kind node is the constructor used:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">kind_constructor</span><span class="plain-syntax"> *</span><span class="function-syntax">Kinds::get_construct</span><button class="popup" onclick="togglePopup('usagePopup8')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup8">Usage of <span class="code-font"><span class="function-syntax">Kinds::get_construct</span></span>:<br/><a href="2-knd.html#SP17">&#167;17</a>, <a href="2-knd.html#SP20">&#167;20</a><br/>The Lattice of Kinds - <a href="2-tlok.html#SP13_1">&#167;13.1</a><br/>Describing Kinds - <a href="2-dk.html#SP24">&#167;24</a>, <a href="2-dk.html#SP24_1">&#167;24.1</a>, <a href="2-dk.html#SP24_1_1">&#167;24.1.1</a>, <a href="2-dk.html#SP25">&#167;25</a><br/>Dimensions - <a href="3-dmn.html#SP11">&#167;11</a><br/>Neptune Syntax - <a href="4-ns.html#SP5_2">&#167;5.2</a><br/>Kind Constructors - <a href="4-kc2.html#SP9">&#167;9</a>, <a href="4-kc2.html#SP16">&#167;16</a>, <a href="4-kc2.html#SP21">&#167;21</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><span class="identifier-syntax">K</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">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP12" class="paragraph-anchor"></a><b>&#167;12. </b>But for the benefit of intermediate and variable kind nodes, we also need:
</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">Kinds::is_intermediate</span><button class="popup" onclick="togglePopup('usagePopup9')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup9">Usage of <span class="code-font"><span class="function-syntax">Kinds::is_intermediate</span></span>:<br/>Dimensions - <a href="3-dmn.html#SP29">&#167;29</a>, <a href="3-dmn.html#SP30">&#167;30</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><span class="identifier-syntax">K</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax"> == </span><span class="identifier-syntax">CON_INTERMEDIATE</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</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">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Kinds::get_variable_number</span><button class="popup" onclick="togglePopup('usagePopup10')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup10">Usage of <span class="code-font"><span class="function-syntax">Kinds::get_variable_number</span></span>:<br/><a href="2-knd.html#SP17">&#167;17</a>, <a href="2-knd.html#SP24">&#167;24</a><br/>The Lattice of Kinds - <a href="2-tlok.html#SP13">&#167;13</a>, <a href="2-tlok.html#SP13_7">&#167;13.7</a><br/>Describing Kinds - <a href="2-dk.html#SP24_1_2">&#167;24.1.2</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><span class="identifier-syntax">K</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax"> == </span><span class="identifier-syntax">CON_KIND_VARIABLE</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">-&gt;</span><span class="element-syntax">kind_variable_number</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</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">Kinds::get_variable_stipulation</span><button class="popup" onclick="togglePopup('usagePopup11')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup11">Usage of <span class="code-font"><span class="function-syntax">Kinds::get_variable_stipulation</span></span>:<br/>The Lattice of Kinds - <a href="2-tlok.html#SP13_7">&#167;13.7</a>, <a href="2-tlok.html#SP13_7_1">&#167;13.7.1</a><br/>Describing Kinds - <a href="2-dk.html#SP24_1_2">&#167;24.1.2</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><span class="identifier-syntax">K</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax"> == </span><span class="identifier-syntax">CON_KIND_VARIABLE</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">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[0];</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>
</pre>
<p class="commentary firstcommentary"><a id="SP13" class="paragraph-anchor"></a><b>&#167;13. </b>Two convenient wrappers for talking about the constructor used:
</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">Kinds::is_proper_constructor</span><button class="popup" onclick="togglePopup('usagePopup12')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup12">Usage of <span class="code-font"><span class="function-syntax">Kinds::is_proper_constructor</span></span>:<br/><a href="2-knd.html#SP17">&#167;17</a>, <a href="2-knd.html#SP18">&#167;18</a>, <a href="2-knd.html#SP19">&#167;19</a><br/>Describing Kinds - <a href="2-dk.html#SP24">&#167;24</a>, <a href="2-dk.html#SP26">&#167;26</a><br/>Dimensions - <a href="3-dmn.html#SP15">&#167;15</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#SP13" class="function-link"><span class="function-syntax">Kinds::arity_of_constructor</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">) &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</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">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Kinds::arity_of_constructor</span><button class="popup" onclick="togglePopup('usagePopup13')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup13">Usage of <span class="code-font"><span class="function-syntax">Kinds::arity_of_constructor</span></span>:<br/><a href="2-knd.html#SP14">&#167;14</a>, <a href="2-knd.html#SP15">&#167;15</a>, <a href="2-knd.html#SP17">&#167;17</a>, <a href="2-knd.html#SP18">&#167;18</a>, <a href="2-knd.html#SP19">&#167;19</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><span class="identifier-syntax">K</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="4-kc2.html#SP15" class="function-link"><span class="function-syntax">KindConstructors::arity</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP14" class="paragraph-anchor"></a><b>&#167;14. </b>Given, say, <span class="extract"><span class="extract-syntax">list of numbers</span></span>, the following returns <span class="extract"><span class="extract-syntax">number</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">Kinds::unary_construction_material</span><button class="popup" onclick="togglePopup('usagePopup14')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup14">Usage of <span class="code-font"><span class="function-syntax">Kinds::unary_construction_material</span></span>:<br/><a href="2-knd.html#SP17">&#167;17</a>, <a href="2-knd.html#SP18">&#167;18</a>, <a href="2-knd.html#SP19">&#167;19</a><br/>The Lattice of Kinds - <a href="2-tlok.html#SP13_1">&#167;13.1</a><br/>Describing Kinds - <a href="2-dk.html#SP24_3">&#167;24.3</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#SP13" class="function-link"><span class="function-syntax">Kinds::arity_of_constructor</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</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><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="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP15" class="paragraph-anchor"></a><b>&#167;15. </b>More awkwardly:
</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">Kinds::binary_construction_material</span><button class="popup" onclick="togglePopup('usagePopup15')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup15">Usage of <span class="code-font"><span class="function-syntax">Kinds::binary_construction_material</span></span>:<br/><a href="2-knd.html#SP17">&#167;17</a>, <a href="2-knd.html#SP18">&#167;18</a>, <a href="2-knd.html#SP19">&#167;19</a><br/>Describing Kinds - <a href="2-dk.html#SP24_1_1">&#167;24.1.1</a>, <a href="2-dk.html#SP24_3">&#167;24.3</a>, <a href="2-dk.html#SP25">&#167;25</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="reserved-syntax">kind</span><span class="plain-syntax"> **</span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> **</span><span class="identifier-syntax">Y</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#SP13" class="function-link"><span class="function-syntax">Kinds::arity_of_constructor</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">) != </span><span class="constant-syntax">2</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">X</span><span class="plain-syntax">) *</span><span class="identifier-syntax">X</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><span class="identifier-syntax">Y</span><span class="plain-syntax">) *</span><span class="identifier-syntax">Y</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">else</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">X</span><span class="plain-syntax">) *</span><span class="identifier-syntax">X</span><span class="plain-syntax"> = </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Y</span><span class="plain-syntax">) *</span><span class="identifier-syntax">Y</span><span class="plain-syntax"> = </span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[1];</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP16" class="paragraph-anchor"></a><b>&#167;16. Traversing the tree. </b>Here we look through a kind tree in search of a given constructor at any node.
</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">Kinds::contains</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="reserved-syntax">kind_constructor</span><span class="plain-syntax"> *</span><span class="identifier-syntax">con</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">return</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">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="identifier-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">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="constant-syntax">MAX_KIND_CONSTRUCTION_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-knd.html#SP16" class="function-link"><span class="function-syntax">Kinds::contains</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">con</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">TRUE</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">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP17" class="paragraph-anchor"></a><b>&#167;17. Kind variable substitution. </b>Once we have determined what the kind variables stand for, we sometimes want
to perform substitution to convert (say) "relation of K to list of K" to
</p>
<ul class="items"><li>(say) "relation of numbers to list of numbers".
</li></ul>
<p class="commentary">However, in order to ensure that caches are never invalidated, we are careful
never to alter a <span class="extract"><span class="extract-syntax">kind</span></span> structure once it has been created; instead,
we return a different structure imitating the shape of the original.
</p>
<p class="commentary">We set the flag indicated by <span class="extract"><span class="extract-syntax">changed</span></span> to <span class="extract"><span class="extract-syntax">TRUE</span></span> if we make any change,
assuming that it was originally <span class="extract"><span class="extract-syntax">FALSE</span></span> before the first use of this function.
</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">Kinds::substitute</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="reserved-syntax">kind</span><span class="plain-syntax"> **</span><span class="identifier-syntax">meanings</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *</span><span class="identifier-syntax">changed</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">contra</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-knd.html#SP17" class="function-link"><span class="function-syntax">Kinds::substitute_inner</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">meanings</span><span class="plain-syntax">, </span><span class="identifier-syntax">changed</span><span class="plain-syntax">, </span><span class="identifier-syntax">contra</span><span class="plain-syntax">, </span><span class="constant-syntax">COVARIANT</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">Kinds::substitute_inner</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="reserved-syntax">kind</span><span class="plain-syntax"> **</span><span class="identifier-syntax">meanings</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *</span><span class="identifier-syntax">changed</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">contra</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">way_in</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">meanings</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">meanings</span><span class="plain-syntax"> = </span><span class="identifier-syntax">values_of_kind_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">N</span><span class="plain-syntax"> = </span><a href="2-knd.html#SP12" class="function-link"><span class="function-syntax">Kinds::get_variable_number</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><span class="identifier-syntax">N</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> *</span><span class="identifier-syntax">changed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</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">contra</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">way_in</span><span class="plain-syntax"> == </span><span class="constant-syntax">CONTRAVARIANT</span><span class="plain-syntax">) &amp;&amp; (</span><a href="2-knd.html#SP24" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">meanings</span><span class="plain-syntax">[</span><span class="identifier-syntax">N</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">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_nil</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">meanings</span><span class="plain-syntax">[</span><span class="identifier-syntax">N</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#SP13" class="function-link"><span class="function-syntax">Kinds::is_proper_constructor</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">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">X</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, *</span><span class="identifier-syntax">X_after</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, *</span><span class="identifier-syntax">Y</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, *</span><span class="identifier-syntax">Y_after</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">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">tx</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">, </span><span class="identifier-syntax">ty</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">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">a</span><span class="plain-syntax"> = </span><a href="2-knd.html#SP13" class="function-link"><span class="function-syntax">Kinds::arity_of_constructor</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><span class="identifier-syntax">a</span><span class="plain-syntax"> == </span><span class="constant-syntax">1</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">X</span><span class="plain-syntax"> = </span><a href="2-knd.html#SP14" class="function-link"><span class="function-syntax">Kinds::unary_construction_material</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="identifier-syntax">X_after</span><span class="plain-syntax"> = </span><a href="2-knd.html#SP17" class="function-link"><span class="function-syntax">Kinds::substitute_inner</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="identifier-syntax">meanings</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">tx</span><span class="plain-syntax">, </span><span class="identifier-syntax">contra</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><a href="4-kc2.html#SP15" class="function-link"><span class="function-syntax">KindConstructors::variance</span></a><span class="plain-syntax">(</span><a href="2-knd.html#SP11" class="function-link"><span class="function-syntax">Kinds::get_construct</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</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">tx</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> *</span><span class="identifier-syntax">changed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</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-knd.html#SP6_3" class="function-link"><span class="function-syntax">Kinds::unary_con</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">X_after</span><span class="plain-syntax">);</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><a href="2-knd.html#SP15" class="function-link"><span class="function-syntax">Kinds::binary_construction_material</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">X</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">Y</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">vx</span><span class="plain-syntax"> = </span><a href="4-kc2.html#SP15" class="function-link"><span class="function-syntax">KindConstructors::variance</span></a><span class="plain-syntax">(</span><a href="2-knd.html#SP11" class="function-link"><span class="function-syntax">Kinds::get_construct</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</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">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">vy</span><span class="plain-syntax"> = </span><a href="4-kc2.html#SP15" class="function-link"><span class="function-syntax">KindConstructors::variance</span></a><span class="plain-syntax">(</span><a href="2-knd.html#SP11" class="function-link"><span class="function-syntax">Kinds::get_construct</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</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">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP11" class="function-link"><span class="function-syntax">Kinds::get_construct</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">) == </span><span class="identifier-syntax">CON_TUPLE_ENTRY</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">vx</span><span class="plain-syntax"> = </span><span class="identifier-syntax">way_in</span><span class="plain-syntax">; </span><span class="identifier-syntax">vy</span><span class="plain-syntax"> = </span><span class="identifier-syntax">way_in</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">X_after</span><span class="plain-syntax"> = </span><a href="2-knd.html#SP17" class="function-link"><span class="function-syntax">Kinds::substitute_inner</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="identifier-syntax">meanings</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">tx</span><span class="plain-syntax">, </span><span class="identifier-syntax">contra</span><span class="plain-syntax">, </span><span class="identifier-syntax">vx</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Y_after</span><span class="plain-syntax"> = </span><a href="2-knd.html#SP17" class="function-link"><span class="function-syntax">Kinds::substitute_inner</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">Y</span><span class="plain-syntax">, </span><span class="identifier-syntax">meanings</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">ty</span><span class="plain-syntax">, </span><span class="identifier-syntax">contra</span><span class="plain-syntax">, </span><span class="identifier-syntax">vy</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">tx</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">ty</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> *</span><span class="identifier-syntax">changed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</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-knd.html#SP6_3" class="function-link"><span class="function-syntax">Kinds::binary_con</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">X_after</span><span class="plain-syntax">, </span><span class="identifier-syntax">Y_after</span><span class="plain-syntax">);</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">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP18" class="paragraph-anchor"></a><b>&#167;18. Weakening. </b>This operation corresponds to rounding kinds up to <span class="extract"><span class="extract-syntax">W</span></span>: that is, any
subkind of <span class="extract"><span class="extract-syntax">W</span></span> is replaced by <span class="extract"><span class="extract-syntax">W</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">Kinds::weaken</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="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">W</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#SP13" class="function-link"><span class="function-syntax">Kinds::is_proper_constructor</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">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">X</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, *</span><span class="identifier-syntax">Y</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">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">a</span><span class="plain-syntax"> = </span><a href="2-knd.html#SP13" class="function-link"><span class="function-syntax">Kinds::arity_of_constructor</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><span class="identifier-syntax">a</span><span class="plain-syntax"> == </span><span class="constant-syntax">1</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">X</span><span class="plain-syntax"> = </span><a href="2-knd.html#SP14" class="function-link"><span class="function-syntax">Kinds::unary_construction_material</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">return</span><span class="plain-syntax"> </span><a href="2-knd.html#SP6_3" class="function-link"><span class="function-syntax">Kinds::unary_con</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><a href="2-knd.html#SP18" class="function-link"><span class="function-syntax">Kinds::weaken</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</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><a href="2-knd.html#SP15" class="function-link"><span class="function-syntax">Kinds::binary_construction_material</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">X</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">Y</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-knd.html#SP6_3" class="function-link"><span class="function-syntax">Kinds::binary_con</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><a href="2-knd.html#SP18" class="function-link"><span class="function-syntax">Kinds::weaken</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">), </span><a href="2-knd.html#SP18" class="function-link"><span class="function-syntax">Kinds::weaken</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">Y</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">));</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="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">K</span><span class="plain-syntax">) &amp;&amp; (</span><a href="2-knd.html#SP25" class="function-link"><span class="function-syntax">Kinds::conforms_to</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">)) &amp;&amp; (</span><a href="2-knd.html#SP24" 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="identifier-syntax">FALSE</span><span class="plain-syntax">) &amp;&amp; (</span><a href="2-knd.html#SP24" 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="identifier-syntax">FALSE</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</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">K</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP19" class="paragraph-anchor"></a><b>&#167;19. Property dereferencing. </b>Properties are sometimes nouns referring to themselves, and sometimes nouns
referring to their values, and these have different kinds. So:
</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">Kinds::dereference_properties</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="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">K</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax"> == </span><span class="identifier-syntax">CON_property</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-knd.html#SP14" class="function-link"><span class="function-syntax">Kinds::unary_construction_material</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#SP13" class="function-link"><span class="function-syntax">Kinds::is_proper_constructor</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">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">X</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, *</span><span class="identifier-syntax">Y</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">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">a</span><span class="plain-syntax"> = </span><a href="2-knd.html#SP13" class="function-link"><span class="function-syntax">Kinds::arity_of_constructor</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><span class="identifier-syntax">a</span><span class="plain-syntax"> == </span><span class="constant-syntax">1</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">X</span><span class="plain-syntax"> = </span><a href="2-knd.html#SP14" class="function-link"><span class="function-syntax">Kinds::unary_construction_material</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">return</span><span class="plain-syntax"> </span><a href="2-knd.html#SP6_3" class="function-link"><span class="function-syntax">Kinds::unary_con</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><a href="2-knd.html#SP19" class="function-link"><span class="function-syntax">Kinds::dereference_properties</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">X</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><a href="2-knd.html#SP15" class="function-link"><span class="function-syntax">Kinds::binary_construction_material</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">X</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">Y</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-knd.html#SP6_3" class="function-link"><span class="function-syntax">Kinds::binary_con</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><a href="2-knd.html#SP19" class="function-link"><span class="function-syntax">Kinds::dereference_properties</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">X</span><span class="plain-syntax">), </span><a href="2-knd.html#SP19" class="function-link"><span class="function-syntax">Kinds::dereference_properties</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">Y</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">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP20" class="paragraph-anchor"></a><b>&#167;20. Creating new base kind constructors. </b>Inform's whole stock of constructors comes from two routes: this one, from the
source text, and another we shall see later, from the Kind Interpreter. The
following is called in response to sentences like:
</p>
<blockquote>
<p>Texture is a kind of value. A musical instrument is a kind of thing.</p>
</blockquote>
<p class="commentary">The word range is the name ("texture", "musical instrument"), and <span class="extract"><span class="extract-syntax">super</span></span>
is the super-kind ("value", "thing").
</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">Kinds::new_base</span><span class="plain-syntax">(</span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">super</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">PROTECTED_MODEL_PROCEDURE</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PROTECTED_MODEL_PROCEDURE</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">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><a href="2-knd.html#SP6" class="function-link"><span class="function-syntax">Kinds::base_construction</span></a><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><a href="4-kc2.html#SP9" class="function-link"><span class="function-syntax">KindConstructors::new</span></a><span class="plain-syntax">(</span><a href="2-knd.html#SP11" class="function-link"><span class="function-syntax">Kinds::get_construct</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">super</span><span class="plain-syntax">), </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"#NEW"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="constant-syntax">BASE_CONSTRUCTOR_GRP</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-knd.html#SP20_1" class="named-paragraph-link"><span class="named-paragraph">Use the source-text name to attach a noun to the constructor</span><span class="named-paragraph-number">20.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="2-fk.html#SP13" class="function-link"><span class="function-syntax">FamiliarKinds::notice_new_kind</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</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">NEW_BASE_KINDS_CALLBACK</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">NEW_BASE_KINDS_CALLBACK</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">super</span><span class="plain-syntax">, </span><a href="2-uk.html#SP19" class="function-link"><span class="function-syntax">Kinds::Behaviour::get_identifier</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">), </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::make_subkind_inner</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">super</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">latest_base_kind_of_value</span><span class="plain-syntax"> = </span><span class="identifier-syntax">K</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_CREATIONS</span><span class="plain-syntax">, </span><span class="string-syntax">"Created base kind %u\n"</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>
</pre>
<p class="commentary firstcommentary"><a id="SP20_1" class="paragraph-anchor"></a><b>&#167;20.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Use the source-text name to attach a noun to the constructor</span><span class="named-paragraph-number">20.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="identifier-syntax">noun</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nt</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">REGISTER_NOUN_KINDS_CALLBACK</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">REGISTER_NOUN_KINDS_CALLBACK</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">super</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">STORE_POINTER_kind_constructor</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">));</span>
<span class="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">REGISTER_NOUN_KINDS_CALLBACK</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Nouns::new_common_noun</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">NEUTER_GENDER</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ADD_TO_LEXICON_NTOPT</span><span class="plain-syntax"> + </span><span class="identifier-syntax">WITH_PLURAL_FORMS_NTOPT</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="constant-syntax">KIND_SLOW_MC</span><span class="plain-syntax">, </span><span class="identifier-syntax">STORE_POINTER_kind_constructor</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">), </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><a href="4-kc2.html#SP10" class="function-link"><span class="function-syntax">KindConstructors::attach_noun</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">, </span><span class="identifier-syntax">nt</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-knd.html#SP20">&#167;20</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP21" class="paragraph-anchor"></a><b>&#167;21. Making subkinds. </b>This does not need to be done at creation time.
</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">Kinds::make_subkind</span><span class="plain-syntax">(</span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sub</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">super</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">PROTECTED_MODEL_PROCEDURE</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PROTECTED_MODEL_PROCEDURE</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><span class="identifier-syntax">sub</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">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Tried to set kind to %u\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">super</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Tried to set the kind of a null kind"</span><span class="plain-syntax">);</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_VETO_MOVE_KINDS_CALLBACK</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">HIERARCHY_VETO_MOVE_KINDS_CALLBACK</span><span class="plain-syntax">(</span><span class="identifier-syntax">sub</span><span class="plain-syntax">, </span><span class="identifier-syntax">super</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</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">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">existing</span><span class="plain-syntax"> = </span><a href="2-tlok.html#SP6" class="function-link"><span class="function-syntax">Latticework::super</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">sub</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP25" class="function-link"><span class="function-syntax">Kinds::compatible</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">existing</span><span class="plain-syntax">, </span><span class="identifier-syntax">super</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">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Tried to make %u a kind of %u\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">sub</span><span class="plain-syntax">, </span><span class="identifier-syntax">super</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">problem_count</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="1-km.html#SP5" class="function-link"><span class="function-syntax">KindsModule::problem_handler</span></a><span class="plain-syntax">(</span><span class="constant-syntax">KindUnalterable_KINDERROR</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><a href="2-uk.html#SP13" class="function-link"><span class="function-syntax">Kinds::Behaviour::get_superkind_set_at</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">sub</span><span class="plain-syntax">), </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">super</span><span class="plain-syntax">, </span><span class="identifier-syntax">existing</span><span class="plain-syntax">);</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><a href="2-knd.html#SP21" class="function-link"><span class="function-syntax">Kinds::make_subkind_inner</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">sub</span><span class="plain-syntax">, </span><span class="identifier-syntax">super</span><span class="plain-syntax">);</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="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Kinds::make_subkind_inner</span><button class="popup" onclick="togglePopup('usagePopup16')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup16">Usage of <span class="code-font"><span class="function-syntax">Kinds::make_subkind_inner</span></span>:<br/><a href="2-knd.html#SP20">&#167;20</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sub</span><span class="plain-syntax">, </span><span class="reserved-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">super</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#SP24" class="function-link"><span class="function-syntax">Kinds::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">super</span><span class="plain-syntax">, </span><span class="identifier-syntax">sub</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">problem_count</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="1-km.html#SP5" class="function-link"><span class="function-syntax">KindsModule::problem_handler</span></a><span class="plain-syntax">(</span><span class="constant-syntax">KindsCircular2_KINDERROR</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><a href="2-uk.html#SP13" class="function-link"><span class="function-syntax">Kinds::Behaviour::get_superkind_set_at</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">sub</span><span class="plain-syntax">), </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">super</span><span class="plain-syntax">, </span><span class="identifier-syntax">sub</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</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">super</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#SP24" 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">sub</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">problem_count</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="1-km.html#SP5" class="function-link"><span class="function-syntax">KindsModule::problem_handler</span></a><span class="plain-syntax">(</span><span class="constant-syntax">KindsCircular_KINDERROR</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><a href="2-uk.html#SP13" class="function-link"><span class="function-syntax">Kinds::Behaviour::get_superkind_set_at</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">super</span><span class="plain-syntax">), </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">super</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><a href="2-tlok.html#SP6" class="function-link"><span class="function-syntax">Latticework::super</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">sub</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</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#SP6" 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="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">HIERARCHY_MOVE_KINDS_CALLBACK</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">HIERARCHY_MOVE_KINDS_CALLBACK</span><span class="plain-syntax">(</span><span class="identifier-syntax">sub</span><span class="plain-syntax">, </span><span class="identifier-syntax">super</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><a href="2-uk.html#SP13" class="function-link"><span class="function-syntax">Kinds::Behaviour::set_superkind_set_at</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">sub</span><span class="plain-syntax">, </span><span class="identifier-syntax">current_sentence</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_CHANGES</span><span class="plain-syntax">, </span><span class="string-syntax">"Making %u a subkind of %u\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">sub</span><span class="plain-syntax">, </span><span class="identifier-syntax">super</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP22" class="paragraph-anchor"></a><b>&#167;22. Annotating vocabulary. </b></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">Kinds::read_kind_marking_from_vocabulary</span><button class="popup" onclick="togglePopup('usagePopup17')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup17">Usage of <span class="code-font"><span class="function-syntax">Kinds::read_kind_marking_from_vocabulary</span></span>:<br/>Describing Kinds - <a href="2-dk.html#SP10">&#167;10</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ve</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">ve</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">means</span><span class="plain-syntax">.</span><span class="identifier-syntax">one_word_kind</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">Kinds::mark_vocabulary_as_kind</span><button class="popup" onclick="togglePopup('usagePopup18')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup18">Usage of <span class="code-font"><span class="function-syntax">Kinds::mark_vocabulary_as_kind</span></span>:<br/>Kind Commands - <a href="4-kc.html#SP1_4">&#167;1.4</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ve</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="plain-syntax"> </span><span class="identifier-syntax">ve</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">means</span><span class="plain-syntax">.</span><span class="identifier-syntax">one_word_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="identifier-syntax">Vocabulary::set_flags</span><span class="plain-syntax">(</span><span class="identifier-syntax">ve</span><span class="plain-syntax">, </span><span class="constant-syntax">KIND_FAST_MC</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">NTI::mark_vocabulary</span><span class="plain-syntax">(</span><span class="identifier-syntax">ve</span><span class="plain-syntax">, </span><span class="function-syntax">&lt;k-kind&gt;</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP23" class="paragraph-anchor"></a><b>&#167;23. From context. </b>Sometimes we need to know the current values of the 26 kind variables, A
to Z: that depends on a much wider context than the <span class="extract"><span class="extract-syntax">kinds</span></span> module can see,
so we need the client to help us. <span class="extract"><span class="extract-syntax">v</span></span> is in the range 1 to 26. Returning
<span class="extract"><span class="extract-syntax">NULL</span></span> means there is no current meaning; so if the client provides no
function to tell us, then all variables are permanently unset.
</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">Kinds::variable_from_context</span><button class="popup" onclick="togglePopup('usagePopup19')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup19">Usage of <span class="code-font"><span class="function-syntax">Kinds::variable_from_context</span></span>:<br/>The Lattice of Kinds - <a href="2-tlok.html#SP14">&#167;14</a><br/>Describing Kinds - <a href="2-dk.html#SP17">&#167;17</a>, <a href="2-dk.html#SP24_1_2">&#167;24.1.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">v</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">KIND_VARIABLE_FROM_CONTEXT</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">KIND_VARIABLE_FROM_CONTEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</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">KIND_VARIABLE_FROM_CONTEXT</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">endif</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP24" class="paragraph-anchor"></a><b>&#167;24. Equality. </b>It may well happen that there are two different <a href="2-knd.html#SP1" class="internal">kind</a> structures in memory
which both mean (say) "list of texts", so we cannot simply test if two
<span class="extract"><span class="extract-syntax">kind *</span></span> pointers are equal when we want to ask if they represent the same
kind.
</p>
<p class="commentary">The following determines whether or not two kinds are the same. Clearly
all base kinds are different from each other, but in some programming
languages it's an interesting question whether different sequences of
constructors applied to these bases can ever produce an equivalent kind.
Most of the interesting cases are to do with unions (which Inform
disallows as type unsafe) and records (which Inform supports only by its
"combination" operator). For example, is "combination (number, text)"
the same as "combination (text, number)"? One might also consider
whether <span class="extract"><span class="extract-syntax">-&gt;</span></span> (function mapping) ought to be an associative operation, as
it would be in a language like Haskell which curried all functions.
</p>
<p class="commentary">At any rate, for Inform the answer is no: every different sequence of kind
constructors produces a different kind.
</p>
<p class="commentary">With kind variables, we take the "name" approach rather than the
"structural" approach: that is, the kind "X" (a variable) is not equivalent
to the kind "number" even if that's the current value of X.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Kinds::eq</span><button class="popup" onclick="togglePopup('usagePopup20')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup20">Usage of <span class="code-font"><span class="function-syntax">Kinds::eq</span></span>:<br/><a href="2-knd.html#SP17">&#167;17</a>, <a href="2-knd.html#SP18">&#167;18</a>, <a href="2-knd.html#SP21">&#167;21</a>, <a href="2-knd.html#SP25">&#167;25</a><br/>The Lattice of Kinds - <a href="2-tlok.html#SP6">&#167;6</a>, <a href="2-tlok.html#SP7_1">&#167;7.1</a>, <a href="2-tlok.html#SP7_2">&#167;7.2</a>, <a href="2-tlok.html#SP13_1">&#167;13.1</a>, <a href="2-tlok.html#SP13_2">&#167;13.2</a>, <a href="2-tlok.html#SP13_5">&#167;13.5</a>, <a href="2-tlok.html#SP13_6">&#167;13.6</a><br/>Describing Kinds - <a href="2-dk.html#SP24_1_2">&#167;24.1.2</a>, <a href="2-dk.html#SP24_2">&#167;24.2</a>, <a href="2-dk.html#SP24_3_1">&#167;24.3.1</a>, <a href="2-dk.html#SP24_3_2">&#167;24.3.2</a><br/>Using Kinds - <a href="2-uk.html#SP2">&#167;2</a>, <a href="2-uk.html#SP4">&#167;4</a><br/>Dimensions - <a href="3-dmn.html#SP15">&#167;15</a>, <a href="3-dmn.html#SP20">&#167;20</a>, <a href="3-dmn.html#SP21">&#167;21</a>, <a href="3-dmn.html#SP24">&#167;24</a>, <a href="3-dmn.html#SP29">&#167;29</a>, <a href="3-dmn.html#SP31_2">&#167;31.2</a><br/>Floating-Point Values - <a href="3-fv.html#SP1">&#167;1</a><br/>Star Templates - <a href="4-st.html#SP4">&#167;4</a></span></button><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">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">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">TRUE</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</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">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">FALSE</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">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax"> != </span><span class="identifier-syntax">K2</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">construct</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</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">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">K1</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">intermediate_result</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">K2</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">intermediate_result</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">FALSE</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">-&gt;</span><span class="element-syntax">intermediate_result</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">K2</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">intermediate_result</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</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">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">K1</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">intermediate_result</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax"> (</span><a href="3-dmn.html#SP20" class="function-link"><span class="function-syntax">Kinds::Dimensions::compare_unit_sequences</span></a><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K1</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">intermediate_result</span><span class="plain-syntax">, </span><span class="identifier-syntax">K2</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">intermediate_result</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</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">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP12" class="function-link"><span class="function-syntax">Kinds::get_variable_number</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">K1</span><span class="plain-syntax">) != </span><a href="2-knd.html#SP12" class="function-link"><span class="function-syntax">Kinds::get_variable_number</span></a><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">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="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="constant-syntax">MAX_KIND_CONSTRUCTION_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-knd.html#SP24" 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">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">K2</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kc_args</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">]) == </span><span class="identifier-syntax">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">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">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Kinds::ne</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-knd.html#SP24" 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">K2</span><span class="plain-syntax">))?</span><span class="identifier-syntax">FALSE:TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP25" class="paragraph-anchor"></a><b>&#167;25. Conformance and compatibility. </b>For the distinction between these, see <a href="P-wtmd.html" class="internal">What This Module Does</a>.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">ALWAYS_MATCH</span><span class="plain-syntax"> </span><span class="constant-syntax">2</span><span class="plain-syntax"> </span><span class="comment-syntax"> provably correct at compile time</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">SOMETIMES_MATCH</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax"> </span><span class="comment-syntax"> provably reduced to a check feasible at run-time</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">NEVER_MATCH</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax"> </span><span class="comment-syntax"> provably incorrect at compile time</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Kinds::conforms_to</span><button class="popup" onclick="togglePopup('usagePopup21')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup21">Usage of <span class="code-font"><span class="function-syntax">Kinds::conforms_to</span></span>:<br/><a href="2-knd.html#SP18">&#167;18</a><br/>The Lattice of Kinds - <a href="2-tlok.html#SP7">&#167;7</a><br/>Using Kinds - <a href="2-uk.html#SP2">&#167;2</a><br/>Star Templates - <a href="4-st.html#SP4">&#167;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="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-tlok.html#SP13" 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="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</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="identifier-syntax">TRUE</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">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Kinds::compatible</span><button class="popup" onclick="togglePopup('usagePopup22')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup22">Usage of <span class="code-font"><span class="function-syntax">Kinds::compatible</span></span>:<br/><a href="2-knd.html#SP21">&#167;21</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="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-knd.html#SP24" 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">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">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">KIND_CHECKING</span><span class="plain-syntax">, </span><span class="string-syntax">"(Is the kind %u compatible with %u?"</span><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="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><a href="2-tlok.html#SP13" 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="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">TRUE</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">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">KIND_CHECKING</span><span class="plain-syntax">, </span><span class="string-syntax">" No)\n"</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">ALWAYS_MATCH:</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">" Yes)\n"</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">SOMETIMES_MATCH:</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">" Sometimes)\n"</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="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"bad return value from Kinds::compatible"</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>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="1-km.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-km.html">1</a></li><li class="progresscurrentchapter">2</li><li class="progresscurrent">knd</li><li class="progresssection"><a href="2-fk.html">fk</a></li><li class="progresssection"><a href="2-tlok.html">tlok</a></li><li class="progresssection"><a href="2-dk.html">dk</a></li><li class="progresssection"><a href="2-uk.html">uk</a></li><li class="progresschapter"><a href="3-dmn.html">3</a></li><li class="progresschapter"><a href="4-abgtn.html">4</a></li><li class="progressnext"><a href="2-fk.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>