1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/kinds-module/2-knd.html
2019-04-22 15:42:10 +01:00

1147 lines
118 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>2/itk</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<!--Weave of '2/knd' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</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><p class="purpose">To build tree structures which represent Inform's universe of kinds.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP10">&#167;10. </a></li><li><a href="#SP18">&#167;18. Constructing kinds</a></li><li><a href="#SP19">&#167;19. Constructing kinds for functions</a></li><li><a href="#SP20">&#167;20. Constructing kinds for pairs</a></li><li><a href="#SP21">&#167;21. Iterating through kinds</a></li><li><a href="#SP23">&#167;23. Annotations of kinds</a></li><li><a href="#SP28">&#167;28. Traversing the tree</a></li><li><a href="#SP29">&#167;29. Kind variable substitution</a></li><li><a href="#SP30">&#167;30. Weakening</a></li><li><a href="#SP31">&#167;31. Property dereferencing</a></li><li><a href="#SP33">&#167;33. Creating new base kind constructors</a></li><li><a href="#SP34">&#167;34. Kind names in the I6 template</a></li><li><a href="#SP35">&#167;35. Annotating vocabulary</a></li><li><a href="#SP36">&#167;36. Errors</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Definitions. </b></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>Inform has a rich universe of kinds: "number", "list of texts",
"relation of texts to lists of times", and so on. We can regard
each valid kind as the outcome of a series of constructions performed on
existing kinds. Here, for example, we get to out destination with four
constructions in a row:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">(nothing) --&gt; text</span>
<span class="plain">(nothing) --&gt; time</span>
<span class="plain">time --&gt; list of times</span>
<span class="plain">text, list of times --&gt; relation of texts to lists of times</span>
</pre>
<p class="inwebparagraph">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.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_KIND_CONSTRUCTION_ARITY</span><span class="plain"> 2</span>
</pre>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Inform stores the possible constructions in <code class="display"><span class="extract">kind_constructor</span></code> structures;
about 40 of these are used to provide the built-in range of kinds, and come
in a mixture of arities. (The four constructions above all use built-in
constructors.) Further constructors are added each time the source text
creates a new kind. For example,
</p>
<blockquote>
<p>A weight is a kind of value. A mammal is a kind of animal.</p>
</blockquote>
<p class="inwebparagraph">creates two new constructors:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">(nothing) --&gt; weight</span>
<span class="plain">(nothing) --&gt; animal</span>
</pre>
<p class="inwebparagraph">At present these additional constructors all have arity 0. High-level Inform 7
source is not currently able to define new constructors of higher arity;
I6 template code can do this (and that's how the built-in set is defined),
and it may be that future developments of Inform will bring this ability up
to source text level.
</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>A given kind is represented in Inform by a pointer to a <code class="display"><span class="extract">kind</span></code> tree.
A <code class="display"><span class="extract">NULL</span></code> pointer is a valid kind, and means "unknown".
</p>
<p class="inwebparagraph">Each node in the tree has a pointer (<code class="display"><span class="extract">-&gt;construct</span></code>) to the kind constructor
used to make it; this is never null. In the case of two special
constructors, there are further annotations (see below). The number of
downward branches at the node is equal to the arity of the constructor
being used; so the kind "number" is represented by a single leaf node:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">number</span>
</pre>
<p class="inwebparagraph">whereas "relation of texts to lists of times" is represented by a tree of
four nodes like so:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">relation of K to L</span>
<span class="plain"> text</span>
<span class="plain"> list of K</span>
<span class="plain"> time</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>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 K" is not. We call constructors of higher arity "proper".
</p>
<p class="inwebparagraph">It would be neat if there were exactly one <code class="display"><span class="extract">kind</span></code> structure somewhere in
memory for each different kind &mdash; if that were true then we could compare
two kinds for equality simply by comparing pointers, and by definition it
would use the least possible memory. But in practice we don't do this,
because (i) it's too slow and tricky to arrange, (ii) we want to abstract
the testing process with the <code class="display"><span class="extract">Kinds::Compare::eq</span></code> function in case of later changes,
and (iii) careful use of caches where access is fast enable us to reduce
memory waste, mostly through intermediates but sometimes constructors, to
only a very small percentage in typical Inform usage &mdash; say about 2K on a
medium-sized source text like "Bronze", which is not worth economising.
</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </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 the tree. For example,
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">function K -&gt; L</span>
<span class="plain"> CON_TUPLE_ENTRY</span>
<span class="plain"> text</span>
<span class="plain"> CON_TUPLE_ENTRY</span>
<span class="plain"> text</span>
<span class="plain"> CON_NIL</span>
<span class="plain"> number</span>
</pre>
<p class="inwebparagraph">represents <code class="display"><span class="extract">function (text, text) -&gt; number</span></code>. Note two special constructors
used here: <code class="display"><span class="extract">CON_TUPLE_ENTRY</span></code> and <code class="display"><span class="extract">CON_NIL</span></code>. These are called "punctuation";
they cannot appear in isolation &mdash; see below.
</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>In the Inform source code, we're clearly going to need to refer to some
of these kinds. The compiler provides support for, say, parsing times of
day, or for indexing scenes, which go beyond the generic facilities it
provides for kinds created in source text. We adopt two naming conventions:
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(i) Kinds are written as <code class="display"><span class="extract">K_source_text_name</span></code>, that is, <code class="display"><span class="extract">K_</span></code> followed by
the name of the kind in I7 source text, with spaces made into underscores.
For instance, <code class="display"><span class="extract">K_number</span></code>. These are all <code class="display"><span class="extract">kind *</span></code> global variables
which are initially <code class="display"><span class="extract">NULL</span></code>, but which, once set, are never changed.
</li></ul>
<ul class="items"><li>(ii) Constructors are likewise written as <code class="display"><span class="extract">CON_source_text_name</span></code> if they can
be created in source text; or by <code class="display"><span class="extract">CON_TEMPLATE_NAME</span></code>, that is, <code class="display"><span class="extract">CON_</span></code>
followed by the constructor's identifier as given in the I6 template file
which created it (but with the <code class="display"><span class="extract">_TY</span></code> suffix removed) if not. For instance,
<code class="display"><span class="extract">CON_list_of</span></code> means the constructor able to make, e.g., "list of texts";
<code class="display"><span class="extract">CON_TUPLE_ENTRY</span></code> refers to the constructor created by the <code class="display"><span class="extract">TUPLE_ENTRY_TY</span></code>
block in the <code class="display"><span class="extract">Load-Core.i6t</span></code> template file. These are all <code class="display"><span class="extract">kind_constructor
</span></code>*<code class="display"><span class="extract"> global variables which are initially </span></code>NULL<code class="display"><span class="extract">, but which, once set, are
</span></code>never changed.
</li></ul>
<p class="inwebparagraph">We will now define all of the <code class="display"><span class="extract">K_...</span></code> and <code class="display"><span class="extract">CON_...</span></code> used by the core of
Inform. (Others are created and used within specific plugins.)
</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>We begin with some base kinds which are "kinds of kinds" useful in
generic programming.
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">K_value</span></code> is a superhero, or perhaps a supervillain: it matches values of
every kind. Not being a kind in its own right, it can't be the kind of a
variable &mdash; which is just as well, since no use of such a variable could
ever be safe.
</p>
<p class="inwebparagraph">The finer distinctions <code class="display"><span class="extract">K_word_value</span></code> and <code class="display"><span class="extract">K_pointer_value</span></code> are used to
divide all run-time data into two very different storage implementations:
</p>
<ul class="items"><li>(a) those where instances are stored as word-value data, where a single I6 value
holds the whole thing, like "number";
</li><li>(b) those where instances are stored as pointers to larger blocks of data on the
heap, like "stored action".
</li></ul>
<pre class="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_value</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_word_value</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_pointer_value</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_sayable_value</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>The following refer to values subject to arithmetic operations (drawn with a
little calculator icon in the Kinds index), and those which are implemented as
enumerations of named constants. (This includes, e.g., scenes and figure names
but not objects, whose run-time storage is not a simple numerical enumeration,
or truth states, which are stored as 0 and 1 not 1 and 2. In particular, it
isn't the same thing as having a finite range in the Kinds index.)
</p>
<pre class="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_arithmetic_value</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_real_arithmetic_value</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span> <span class="comment">those using real, not integer, arithmetic</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_enumerated_value</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>Next, the two constructors used to punctuate tuples, that is, collections
(K_1, K_2, ..., K_n) of kinds of value. <code class="display"><span class="extract">CON_NIL</span></code> represents the empty
tuple, where n=0; while <code class="display"><span class="extract">CON_TUPLE_ENTRY</span></code> behaves like a kind constructor
with arity 2, its two bases being the first item and the rest, respectively.
Thus we store (A, B, C) as
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">CON_TUPLE_ENTRY(A, CON_TUPLE_ENTRY(B, CON_TUPLE_ENTRY(C, CON_NIL)))</span>
</pre>
<p class="inwebparagraph">This traditional LISP-like device enables us to store tuples of arbitrary
size without need for any constructor of arity greater than 2.
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(a) Inform has no "nil" or "void" kind visible to the writer of source
text, though it does occasionally use a kind it calls <code class="display"><span class="extract">K_nil</span></code> internally
to represent this idea &mdash; for instance for a rulebook producing nothing;
<code class="display"><span class="extract">K_nil</span></code> is the kind constructed by <code class="display"><span class="extract">CON_NIL</span></code>.
</li></ul>
<ul class="items"><li>(b) Inform does allow combinations, but they're identified by trees headed
by the constructor <code class="display"><span class="extract">CON_combination</span></code>, which then uses punctuation in its own
subtree. You might guess that an ordered pair of a text and a time would be
represented by the <code class="display"><span class="extract">CON_TUPLE_ENTRY</span></code> constructor on its own, but it isn't.
</li></ul>
<pre class="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_nil</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">CON_NIL</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">CON_TUPLE_ENTRY</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>It was mentioned above that two special constructors carry additional
annotations with them. The first of these is <code class="display"><span class="extract">CON_INTERMEDIATE</span></code>, used to
represent kinds which are brought into being through uncompleted arithmetic
operations: see "Dimensions.w" for a full discussion. Such a node in a
kind tree might represent "area divided by time squared", say, and it must
be annotated to show exactly which intermediate kind is meant.
</p>
<pre class="display">
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">CON_INTERMEDIATE</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>While that doesn't significantly change the kinds system, the second special
constructor certainly does. This is <code class="display"><span class="extract">CON_KIND_VARIABLE</span></code>, annotated to show
which of the 26 kind variables it represents in any given situation. These
variables are, in effect, wildcards; each is marked with a "kind of kind"
as its range of possible values. (Thus a typical use of this constructor
might result in a kind node labelled as L, which can be any kind matching
"arithmetic value".)
</p>
<pre class="display">
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">CON_KIND_VARIABLE</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b>So much for the exotica: back onto familiar ground for anyone who uses
Inform. Some standard kinds:
</p>
<pre class="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_action_name</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_equation</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_grammatical_gender</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_natural_language</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_number</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_object</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_real_number</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_response</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_snippet</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_stored_action</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_table</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_text</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_truth_state</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_unicode_character</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_use_option</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_verb</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. </b>And here are two more standard kinds, but which most Inform uses don't
realise are there, because they are omitted from the Kinds index:
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(a) <code class="display"><span class="extract">K_rulebook_outcome</span></code>. Rulebooks end in success, failure, no outcome, or
possibly one of a range of named alternative outcomes. These all share a
single namespace, and the names in question share a single kind of value.
It's not a very elegant system, and we really don't want people storing
these in variables; we want them to be used only as part of the process of
receiving the outcome back. So although there's no technical reason why this
kind shouldn't be used for storage, it's hidden from the user.
</li></ul>
<ul class="items"><li>(b) <code class="display"><span class="extract">K_understanding</span></code> is used to hold the result of a grammar token. An actual
constant value specification of this kind stores a <code class="display"><span class="extract">grammar_verb *</span></code> pointer.
It's an untidy internal device which may well be removed later.
</li></ul>
<pre class="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_rulebook_outcome</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K_understanding</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. </b>Finally, the constructors used by Inform authors:
</p>
<pre class="display">
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">CON_list_of</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">CON_description</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">CON_relation</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">CON_rule</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">CON_rulebook</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">CON_activity</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">CON_phrase</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">CON_property</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">CON_table_column</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">CON_combination</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">CON_variable</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. </b>Finally, then, it's time to define what a kind node looks like:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">construct</span><span class="plain">; </span> <span class="comment">which can never be <code class="display"><span class="extract">NULL</span></code></span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">kind_variable_number</span><span class="plain">; </span> <span class="comment">only used if construct is <code class="display"><span class="extract">CON_KIND_VARIABLE</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">intermediate_result</span><span class="plain">; </span> <span class="comment">only used if construct is <code class="display"><span class="extract">CON_INTERMEDIATE</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kc_args</span><span class="plain">[</span><span class="constant">MAX_KIND_CONSTRUCTION_ARITY</span><span class="plain">]; </span> <span class="comment">used if arity positive, or for <code class="display"><span class="extract">CON_KIND_VARIABLE</span></code></span>
<span class="plain">} </span><span class="reserved">kind</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure kind is accessed in 2/kc, 2/uk, 2/fv and here.</p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. </b>We keep some statistics for tracking memory usage:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_base_kinds_created</span><span class="plain"> = 0;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_intermediate_kinds_created</span><span class="plain"> = 0;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_constructed_kinds_created</span><span class="plain"> = 0;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP18"></a><b>&#167;18. Constructing kinds. </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="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::base_construction</span><span class="plain">(</span><span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">con</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">con</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"impossible construction"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">con</span><span class="plain"> == </span><span class="identifier">CON_KIND_VARIABLE</span><span class="plain">) || (</span><span class="identifier">con</span><span class="plain"> == </span><span class="identifier">CON_INTERMEDIATE</span><span class="plain">))</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"forbidden construction"</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="functiontext">Kinds::Constructors::arity</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">)) {</span>
<span class="reserved">case</span><span class="plain"> 1:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">con</span><span class="plain"> == </span><span class="identifier">CON_list_of</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::unary_construction</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::unary_construction</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">);</span>
<span class="reserved">case</span><span class="plain"> 2: </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">kind</span><span class="plain"> **</span><span class="identifier">cache</span><span class="plain"> = </span><span class="functiontext">Kinds::Constructors::cache_location</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cache</span><span class="plain">) { </span><span class="reserved">if</span><span class="plain"> (*</span><span class="identifier">cache</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> *</span><span class="identifier">cache</span><span class="plain">; }</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Create a raw kind structure</span> <span class="cwebmacronumber">18.4</span>&gt;<span class="plain">;</span>
<span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain"> = </span><span class="identifier">con</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cache</span><span class="plain">) *</span><span class="identifier">cache</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">;</span>
<span class="identifier">no_base_kinds_created</span><span class="plain">++;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::base_construction is used in <a href="#SP22">&#167;22</a>, <a href="#SP33">&#167;33</a>, 2/kc2 (<a href="2-kc2.html#SP3">&#167;3</a>, <a href="2-kc2.html#SP7">&#167;7</a>, <a href="2-kc2.html#SP7_1">&#167;7.1</a>), 2/ki (<a href="2-ki.html#SP14_1">&#167;14.1</a>, <a href="2-ki.html#SP28_4">&#167;28.4</a>), 2/dk (<a href="2-dk.html#SP10">&#167;10</a>).</p>
<p class="inwebparagraph"><a id="SP18_1"></a><b>&#167;18.1. </b>As noted above, <code class="display"><span class="extract">CON_INTERMEDIATE</span></code> 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 <code class="display"><span class="extract">CON_INTERMEDIATE</span></code>.
These are needed relatively seldom and are not cached.
</p>
<pre class="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::intermediate_construction</span><span class="plain">(</span><span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">ik</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ik</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"made unknown as Kinds::intermediate_construction"</span><span class="plain">);</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Create a raw kind structure</span> <span class="cwebmacronumber">18.4</span>&gt;<span class="plain">;</span>
<span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain"> = </span><span class="identifier">CON_INTERMEDIATE</span><span class="plain">;</span>
<span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;intermediate_result</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">unit_sequence</span><span class="plain">);</span>
<span class="plain">*(</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;intermediate_result</span><span class="plain">) = *</span><span class="identifier">ik</span><span class="plain">;</span>
<span class="identifier">no_intermediate_kinds_created</span><span class="plain">++;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::intermediate_construction is used in 2/dmn (<a href="2-dmn.html#SP40_4">&#167;40.4</a>).</p>
<p class="inwebparagraph"><a id="SP18_2"></a><b>&#167;18.2. </b>Kind variables A to Z (where <code class="display"><span class="extract">N</span></code> is 1 to 26 below) can usually stand for
any kind, but can also be marked with a "declaration", usually
constraining what kind of value they are allowed to hold. For example, K
might be marked as being an arithmetical kind of value. See "Kind
Checking.w".
</p>
<pre class="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::variable_construction</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">declaration</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">N</span><span class="plain"> == 0) || (</span><span class="identifier">N</span><span class="plain"> &gt; </span><span class="constant">MAX_KIND_VARIABLES</span><span class="plain">)) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad kind variable"</span><span class="plain">);</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Create a raw kind structure</span> <span class="cwebmacronumber">18.4</span>&gt;<span class="plain">;</span>
<span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain"> = </span><span class="identifier">CON_KIND_VARIABLE</span><span class="plain">;</span>
<span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;kind_variable_number</span><span class="plain"> = </span><span class="identifier">N</span><span class="plain">;</span>
<span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;kc_args</span><span class="plain">[0] = </span><span class="identifier">declaration</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::variable_construction is used in 2/dk (<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>).</p>
<p class="inwebparagraph"><a id="SP18_3"></a><b>&#167;18.3. </b>That completes the possible base constructions. Proper constructions are made
using the following. For example,
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">Kinds::unary_construction(CON_list_of, K_number)</span>
</pre>
<p class="inwebparagraph">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="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::unary_construction</span><span class="plain">(</span><span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">con</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">X</span><span class="plain">) {</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Constructors::arity</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">) != 1) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad unary construction"</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Create a raw kind structure</span> <span class="cwebmacronumber">18.4</span>&gt;<span class="plain">;</span>
<span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain"> = </span><span class="identifier">con</span><span class="plain">; </span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;kc_args</span><span class="plain">[0] = </span><span class="identifier">X</span><span class="plain">;</span>
<span class="identifier">no_constructed_kinds_created</span><span class="plain">++;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">con</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">X</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">Y</span><span class="plain">) {</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Constructors::arity</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">) != 2) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad binary construction"</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Create a raw kind structure</span> <span class="cwebmacronumber">18.4</span>&gt;<span class="plain">;</span>
<span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain"> = </span><span class="identifier">con</span><span class="plain">; </span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;kc_args</span><span class="plain">[0] = </span><span class="identifier">X</span><span class="plain">; </span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;kc_args</span><span class="plain">[1] = </span><span class="identifier">Y</span><span class="plain">;</span>
<span class="identifier">no_constructed_kinds_created</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">con</span><span class="plain"> == </span><span class="identifier">CON_phrase</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">X</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">Y</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad function kind"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">X</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain"> == </span><span class="identifier">CON_TUPLE_ENTRY</span><span class="plain">) &amp;&amp; (</span><span class="identifier">X</span><span class="plain">-</span><span class="element">&gt;kc_args</span><span class="plain">[0] == </span><span class="identifier">K_nil</span><span class="plain">))</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"nil nil"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain"> == </span><span class="identifier">CON_TUPLE_ENTRY</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bizarre"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::unary_construction is used in <a href="#SP18">&#167;18</a>, <a href="#SP29">&#167;29</a>, <a href="#SP30">&#167;30</a>, <a href="#SP31">&#167;31</a>, 2/kc (<a href="2-kc.html#SP12">&#167;12</a>, <a href="2-kc.html#SP18_6">&#167;18.6</a>), 2/dk (<a href="2-dk.html#SP11">&#167;11</a>, <a href="2-dk.html#SP12_1">&#167;12.1</a>).</p>
<p class="endnote">The function Kinds::binary_construction is used in <a href="#SP18">&#167;18</a>, <a href="#SP19">&#167;19</a>, <a href="#SP20">&#167;20</a>, <a href="#SP29">&#167;29</a>, <a href="#SP30">&#167;30</a>, <a href="#SP31">&#167;31</a>, 2/kc (<a href="2-kc.html#SP12">&#167;12</a>, <a href="2-kc.html#SP18_6">&#167;18.6</a>), 2/dk (<a href="2-dk.html#SP11">&#167;11</a>, <a href="2-dk.html#SP12_1">&#167;12.1</a>, <a href="2-dk.html#SP13">&#167;13</a>).</p>
<p class="inwebparagraph"><a id="SP18_4"></a><b>&#167;18.4. </b>We've now seen the only ways to create a kind structure, and they share the
following initialisation:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Create a raw kind structure</span> <span class="cwebmacronumber">18.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">K</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain">);</span>
<span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;intermediate_result</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;kind_variable_number</span><span class="plain"> = 0;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">MAX_KIND_CONSTRUCTION_ARITY</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;kc_args</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP18">&#167;18</a>, <a href="#SP18_1">&#167;18.1</a>, <a href="#SP18_2">&#167;18.2</a>, <a href="#SP18_3">&#167;18.3</a> (twice).</p>
<p class="inwebparagraph"><a id="SP19"></a><b>&#167;19. 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 <code class="display"><span class="extract">CON_TUPLE_ENTRY</span></code> and <code class="display"><span class="extract">CON_NIL</span></code>. Note
that we use <code class="display"><span class="extract">K_nil</span></code> 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>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">CON_phrase</span>
<span class="plain"> CON_TUPLE_ENTRY</span>
<span class="plain"> X</span>
<span class="plain"> CON_NIL</span>
<span class="plain"> Y</span>
</pre>
<p class="inwebparagraph">rather than as:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">CON_phrase</span>
<span class="plain"> X</span>
<span class="plain"> Y</span>
</pre>
<p class="inwebparagraph">(It's more convenient to have a predictable form than to save on kind nodes.)
</p>
<pre class="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::function_kind</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_args</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> **</span><span class="identifier">args</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">return_K</span><span class="plain">) {</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">arguments_K</span><span class="plain"> = </span><span class="identifier">K_nil</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">no_args</span><span class="plain">-1; </span><span class="identifier">i</span><span class="plain">&gt;=0; </span><span class="identifier">i</span><span class="plain">--)</span>
<span class="identifier">arguments_K</span><span class="plain"> = </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_TUPLE_ENTRY</span><span class="plain">, </span><span class="identifier">args</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">arguments_K</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">return_K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">return_K</span><span class="plain"> = </span><span class="identifier">K_nil</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_phrase</span><span class="plain">, </span><span class="identifier">arguments_K</span><span class="plain">, </span><span class="identifier">return_K</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::function_kind appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP20"></a><b>&#167;20. Constructing kinds for pairs. </b>Similarly, but more simply, here is the kind for an ordered pair of values:
</p>
<pre class="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::pair_kind</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">X</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">Y</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_combination</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::pair_kind appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP21"></a><b>&#167;21. 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">
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">=</span><span class="functiontext">Kinds::first_base_k</span><span class="plain">(); </span><span class="identifier">K</span><span class="plain">; </span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Kinds::next_base_k</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">))</span>
</pre>
<p class="inwebparagraph"><a id="SP22"></a><b>&#167;22. </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="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::first_base_k</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">con</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">, </span><span class="reserved">kind_constructor</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">con</span><span class="plain"> != </span><span class="identifier">CON_KIND_VARIABLE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">con</span><span class="plain"> != </span><span class="identifier">CON_INTERMEDIATE</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::base_construction</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::next_base_k</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">con</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain">;</span>
<span class="reserved">do</span><span class="plain"> {</span>
<span class="identifier">con</span><span class="plain"> = </span><span class="identifier">NEXT_OBJECT</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">, </span><span class="reserved">kind_constructor</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">con</span><span class="plain"> == </span><span class="identifier">CON_KIND_VARIABLE</span><span class="plain">) || (</span><span class="identifier">con</span><span class="plain"> == </span><span class="identifier">CON_INTERMEDIATE</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">con</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::base_construction</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::first_base_k is used in <a href="#SP21">&#167;21</a>.</p>
<p class="endnote">The function Kinds::next_base_k is used in <a href="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP23"></a><b>&#167;23. Annotations of kinds. </b>Most of the time, the only annotation of a kind node is the constructor used:
</p>
<pre class="display">
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="functiontext">Kinds::get_construct</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::get_construct is used in <a href="#SP33">&#167;33</a>, 2/kc (<a href="2-kc.html#SP15_1">&#167;15.1</a>), 2/kc2 (<a href="2-kc2.html#SP7">&#167;7</a>, <a href="2-kc2.html#SP15">&#167;15</a>, <a href="2-kc2.html#SP19">&#167;19</a>), 2/ki (<a href="2-ki.html#SP14_1">&#167;14.1</a>), 2/uk (<a href="2-uk.html#SP16">&#167;16</a>, <a href="2-uk.html#SP32">&#167;32</a>), 2/dk (<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>), 2/dmn (<a href="2-dmn.html#SP14">&#167;14</a>).</p>
<p class="inwebparagraph"><a id="SP24"></a><b>&#167;24. </b>But for the benefit of intermediate and variable kind nodes, we also need:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::is_intermediate</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K</span><span class="plain">) &amp;&amp; (</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain"> == </span><span class="identifier">CON_INTERMEDIATE</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::get_variable_number</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K</span><span class="plain">) &amp;&amp; (</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain"> == </span><span class="identifier">CON_KIND_VARIABLE</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;kind_variable_number</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> -1;</span>
<span class="plain">}</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::get_variable_stipulation</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K</span><span class="plain">) &amp;&amp; (</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain"> == </span><span class="identifier">CON_KIND_VARIABLE</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;kc_args</span><span class="plain">[0];</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::is_intermediate is used in 2/dmn (<a href="2-dmn.html#SP32_2">&#167;32.2</a>, <a href="2-dmn.html#SP33">&#167;33</a>).</p>
<p class="endnote">The function Kinds::get_variable_number is used in <a href="#SP29">&#167;29</a>, 2/kc (<a href="2-kc.html#SP10">&#167;10</a>, <a href="2-kc.html#SP15">&#167;15</a>, <a href="2-kc.html#SP15_6">&#167;15.6</a>), 2/dk (<a href="2-dk.html#SP24_1_2">&#167;24.1.2</a>).</p>
<p class="endnote">The function Kinds::get_variable_stipulation is used in 2/kc (<a href="2-kc.html#SP15_6">&#167;15.6</a>, <a href="2-kc.html#SP15_6_1">&#167;15.6.1</a>), 2/dk (<a href="2-dk.html#SP24_1_2">&#167;24.1.2</a>).</p>
<p class="inwebparagraph"><a id="SP25"></a><b>&#167;25. </b>Two convenient wrappers for talking about the constructor used:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::is_proper_constructor</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::arity_of_constructor</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) &gt; 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::arity_of_constructor</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::Constructors::arity</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> 0;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::is_proper_constructor is used in <a href="#SP29">&#167;29</a>, <a href="#SP30">&#167;30</a>, <a href="#SP31">&#167;31</a>, 2/dk (<a href="2-dk.html#SP24">&#167;24</a>), 2/dmn (<a href="2-dmn.html#SP18">&#167;18</a>).</p>
<p class="endnote">The function Kinds::arity_of_constructor is used in <a href="#SP26">&#167;26</a>, <a href="#SP27">&#167;27</a>, <a href="#SP29">&#167;29</a>, <a href="#SP30">&#167;30</a>, <a href="#SP31">&#167;31</a>.</p>
<p class="inwebparagraph"><a id="SP26"></a><b>&#167;26. </b>Given, say, "list of numbers", the following returns "number":
</p>
<pre class="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::unary_construction_material</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::arity_of_constructor</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) != 1) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;kc_args</span><span class="plain">[0];</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::unary_construction_material is used in <a href="#SP29">&#167;29</a>, <a href="#SP30">&#167;30</a>, <a href="#SP31">&#167;31</a>, 2/kc (<a href="2-kc.html#SP15_1">&#167;15.1</a>), 2/dk (<a href="2-dk.html#SP24_3">&#167;24.3</a>).</p>
<p class="inwebparagraph"><a id="SP27"></a><b>&#167;27. </b>More awkwardly:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::binary_construction_material</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> **</span><span class="identifier">X</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> **</span><span class="identifier">Y</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::arity_of_constructor</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) != 2) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">X</span><span class="plain">) *</span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain">) *</span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">X</span><span class="plain">) *</span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;kc_args</span><span class="plain">[0];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain">) *</span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;kc_args</span><span class="plain">[1];</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::binary_construction_material is used in <a href="#SP29">&#167;29</a>, <a href="#SP30">&#167;30</a>, <a href="#SP31">&#167;31</a>, 2/dk (<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>).</p>
<p class="inwebparagraph"><a id="SP28"></a><b>&#167;28. Traversing the tree. </b>Here we look through a kind tree in search of a given constructor at any node.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::contains</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">, </span><span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">con</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain"> == </span><span class="identifier">con</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">MAX_KIND_CONSTRUCTION_ARITY</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::contains</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;kc_args</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">con</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::contains appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP29"></a><b>&#167;29. 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="inwebparagraph">However, in order to ensure that caches are never invalidated, we are careful
never to alter a <code class="display"><span class="extract">kind</span></code> structure once it has been created; instead,
we return a different structure imitating the shape of the original.
</p>
<p class="inwebparagraph">We set the flag indicated by <code class="display"><span class="extract">changed</span></code> to <code class="display"><span class="extract">TRUE</span></code> if we make any change,
assuming that it was originally <code class="display"><span class="extract">FALSE</span></code> before the first use of this function.
</p>
<pre class="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::substitute</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> **</span><span class="identifier">meanings</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">changed</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">meanings</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">meanings</span><span class="plain"> = </span><span class="identifier">values_of_kind_variables</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="functiontext">Kinds::get_variable_number</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> &gt; 0) {</span>
<span class="plain">*</span><span class="identifier">changed</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">meanings</span><span class="plain">[</span><span class="identifier">N</span><span class="plain">];</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::is_proper_constructor</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)) {</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">X_after</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">Y_after</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">tx</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">ty</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">a</span><span class="plain"> = </span><span class="functiontext">Kinds::arity_of_constructor</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">a</span><span class="plain"> == 1) {</span>
<span class="identifier">X</span><span class="plain"> = </span><span class="functiontext">Kinds::unary_construction_material</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="identifier">X_after</span><span class="plain"> = </span><span class="functiontext">Kinds::substitute</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">meanings</span><span class="plain">, &amp;</span><span class="identifier">tx</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tx</span><span class="plain">) {</span>
<span class="plain">*</span><span class="identifier">changed</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::unary_construction</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain">, </span><span class="identifier">X_after</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="functiontext">Kinds::binary_construction_material</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, &amp;</span><span class="identifier">X</span><span class="plain">, &amp;</span><span class="identifier">Y</span><span class="plain">);</span>
<span class="identifier">X_after</span><span class="plain"> = </span><span class="functiontext">Kinds::substitute</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">meanings</span><span class="plain">, &amp;</span><span class="identifier">tx</span><span class="plain">);</span>
<span class="identifier">Y_after</span><span class="plain"> = </span><span class="functiontext">Kinds::substitute</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">meanings</span><span class="plain">, &amp;</span><span class="identifier">ty</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">tx</span><span class="plain">) || (</span><span class="identifier">ty</span><span class="plain">)) {</span>
<span class="plain">*</span><span class="identifier">changed</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain">, </span><span class="identifier">X_after</span><span class="plain">, </span><span class="identifier">Y_after</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::substitute appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP30"></a><b>&#167;30. Weakening. </b>This operation corresponds to rounding kinds up to "object": that is, any
subkind of "object" is replaced by "object".
</p>
<pre class="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::weaken</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::is_proper_constructor</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)) {</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">a</span><span class="plain"> = </span><span class="functiontext">Kinds::arity_of_constructor</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">a</span><span class="plain"> == 1) {</span>
<span class="identifier">X</span><span class="plain"> = </span><span class="functiontext">Kinds::unary_construction_material</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::unary_construction</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain">, </span><span class="functiontext">Kinds::weaken</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">));</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="functiontext">Kinds::binary_construction_material</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, &amp;</span><span class="identifier">X</span><span class="plain">, &amp;</span><span class="identifier">Y</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain">, </span><span class="functiontext">Kinds::weaken</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">), </span><span class="functiontext">Kinds::weaken</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Kinds::Compare::lt</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">))) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K_object</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::weaken is used in 2/uk (<a href="2-uk.html#SP26">&#167;26</a>).</p>
<p class="inwebparagraph"><a id="SP31"></a><b>&#167;31. 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="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::dereference_properties</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K</span><span class="plain">) &amp;&amp; (</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain"> == </span><span class="identifier">CON_property</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::unary_construction_material</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::is_proper_constructor</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)) {</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">a</span><span class="plain"> = </span><span class="functiontext">Kinds::arity_of_constructor</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">a</span><span class="plain"> == 1) {</span>
<span class="identifier">X</span><span class="plain"> = </span><span class="functiontext">Kinds::unary_construction_material</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::unary_construction</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain">,</span>
<span class="functiontext">Kinds::dereference_properties</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">));</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="functiontext">Kinds::binary_construction_material</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, &amp;</span><span class="identifier">X</span><span class="plain">, &amp;</span><span class="identifier">Y</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain">,</span>
<span class="functiontext">Kinds::dereference_properties</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">), </span><span class="functiontext">Kinds::dereference_properties</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::dereference_properties appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP32"></a><b>&#167;32. </b>Inform builds "natural language" in so that it can create an instance for
each natural language whose bundle it can find. "Grammatical gender" is used
as a kind whose name coincides with a property.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">notable</span><span class="plain">-</span><span class="identifier">linguistic</span><span class="plain">-</span><span class="identifier">kinds</span><span class="plain">&gt; ::=</span>
<span class="identifier">natural</span><span class="plain"> </span><span class="identifier">language</span><span class="plain"> |</span>
<span class="identifier">grammatical</span><span class="plain"> </span><span class="identifier">gender</span><span class="plain"> |</span>
<span class="identifier">grammatical</span><span class="plain"> </span><span class="identifier">tense</span><span class="plain"> |</span>
<span class="identifier">narrative</span><span class="plain"> </span><span class="identifier">viewpoint</span><span class="plain"> |</span>
<span class="identifier">grammatical</span><span class="plain"> </span><span class="reserved">case</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP33"></a><b>&#167;33. 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="inwebparagraph">The word range is the name ("texture", "musical instrument"), and <code class="display"><span class="extract">super</span></code>
is the super-kind ("value", "thing").
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_kinds_of_object</span><span class="plain"> = 1;</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::new_base</span><span class="plain">(</span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">super</span><span class="plain">) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">PROTECTED_MODEL_PROCEDURE</span>
<span class="identifier">PROTECTED_MODEL_PROCEDURE</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Kinds::base_construction</span><span class="plain">(</span>
<span class="functiontext">Kinds::Constructors::new</span><span class="plain">(</span><span class="functiontext">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">super</span><span class="plain">), </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"#NEW"</span><span class="plain">));</span>
&lt;<span class="cwebmacro">Renew the subject if necessary to cope with an early subject creation</span> <span class="cwebmacronumber">33.1</span>&gt;<span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">super</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">))</span>
<span class="identifier">InferenceSubjects::falls_within</span><span class="plain">(</span><span class="identifier">Kinds::Knowledge::as_subject</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">), </span><span class="identifier">Kinds::Knowledge::as_subject</span><span class="plain">(</span><span class="identifier">super</span><span class="plain">));</span>
<span class="plain">#</span><span class="identifier">endif</span>
&lt;<span class="cwebmacro">Use the source-text name to attach a noun to the constructor</span> <span class="cwebmacronumber">33.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">notable</span><span class="plain">-</span><span class="identifier">linguistic</span><span class="plain">-</span><span class="identifier">kinds</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="functiontext">Kinds::Constructors::mark_as_linguistic</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (&lt;&lt;</span><span class="identifier">r</span><span class="plain">&gt;&gt;) {</span>
<span class="reserved">case</span><span class="plain"> 0: </span><span class="identifier">K_natural_language</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">NATURAL_LANGUAGES_PRESENT</span>
<span class="identifier">NaturalLanguages::stock_nl_kind</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> 1: </span><span class="identifier">K_grammatical_gender</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">property</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="identifier">property</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="identifier">Properties::Valued::set_kind</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="identifier">Instances::make_kind_coincident</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">P</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_grammatical_gender</span><span class="plain">)) </span><span class="identifier">P_grammatical_gender</span><span class="plain"> = </span><span class="identifier">P</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">NEW_BASE_KIND_NOTIFY</span>
<span class="identifier">Plugins::Call::new_base_kind_notify</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="functiontext">Kinds::Behaviour::get_name_in_template_code</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">), </span><span class="identifier">W</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">latest_base_kind_of_value</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CREATIONS</span><span class="plain">, </span><span class="string">"Created base kind $u\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::new_base appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP33_1"></a><b>&#167;33.1. </b>This is used to overcome a timing problem. A few inference subjects need to
be defined early in Inform's run to set up relations &mdash; "thing", for example.
So when we do finally create "thing" as a kind of object, it needs to be
matched up with the inference subject already existing.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Renew the subject if necessary to cope with an early subject creation</span> <span class="cwebmacronumber">33.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="identifier">inference_subject</span><span class="plain"> *</span><span class="identifier">revised</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) </span><span class="identifier">Plugins::Call::name_to_early_infs</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, &amp;</span><span class="identifier">revised</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">revised</span><span class="plain">) {</span>
<span class="identifier">InferenceSubjects::renew</span><span class="plain">(</span><span class="identifier">revised</span><span class="plain">,</span>
<span class="identifier">Kinds::Knowledge::as_subject</span><span class="plain">(</span><span class="identifier">super</span><span class="plain">), </span><span class="identifier">KIND_SUB</span><span class="plain">, </span><span class="identifier">STORE_POINTER_kind_constructor</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain">), </span><span class="identifier">LIKELY_CE</span><span class="plain">);</span>
<span class="identifier">Kinds::Knowledge::set_subject</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">revised</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP33">&#167;33</a>.</p>
<p class="inwebparagraph"><a id="SP33_2"></a><b>&#167;33.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Use the source-text name to attach a noun to the constructor</span> <span class="cwebmacronumber">33.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">unsigned</span><span class="plain"> </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">mc</span><span class="plain"> = </span><span class="constant">KIND_SLOW_MC</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">super</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">)) </span><span class="identifier">mc</span><span class="plain"> = </span><span class="identifier">NOUN_MC</span><span class="plain">;</span>
<span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain"> = </span><span class="identifier">Nouns::new_common_noun</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">NEUTER_GENDER</span><span class="plain">,</span>
<span class="identifier">PARSE_EXACTLY_NTOPT</span><span class="plain"> + </span><span class="identifier">REGISTER_SINGULAR_NTOPT</span><span class="plain"> +</span>
<span class="identifier">REGISTER_PLURAL_NTOPT</span><span class="plain"> + </span><span class="identifier">ATTACH_TO_SEARCH_LIST_NTOPT</span><span class="plain">,</span>
<span class="constant">KIND_SLOW_MC</span><span class="plain">, </span><span class="identifier">STORE_POINTER_kind_constructor</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::le</span><span class="plain">(</span><span class="identifier">super</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">))</span>
<span class="identifier">Nouns::set_range_number</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">no_kinds_of_object</span><span class="plain">++);</span>
<span class="functiontext">Kinds::Constructors::attach_noun</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">-</span><span class="element">&gt;construct</span><span class="plain">, </span><span class="identifier">nt</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP33">&#167;33</a>.</p>
<p class="inwebparagraph"><a id="SP34"></a><b>&#167;34. Kind names in the I6 template. </b>We defined some "constant" kinds and constructors above, to provide
values like <code class="display"><span class="extract">K_number</span></code> for use in this C source code. We will also want to
refer to these kinds in the Inform 6 source code for the template, where
they will have identifiers such as <code class="display"><span class="extract">NUMBER_TY</span></code>. (If anything it's the other
way round, since the template creates these kinds at run-time, using the
kind interpreter &mdash; of which, more later.)
</p>
<p class="inwebparagraph">So we need a way of pairing up names in these two source codes, and here
it is. There is no need for speed here.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="identifier">text_of_I6_name</span><span class="plain">, </span><span class="identifier">pointer_to_I7_structure</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">sn</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Str::eq_narrow_string</span><span class="plain">(</span><span class="identifier">sn</span><span class="plain">, </span><span class="identifier">text_of_I6_name</span><span class="plain">))) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">pointer_to_I7_structure</span><span class="plain">;</span>
</pre>
<pre class="display">
<span class="reserved">kind_constructor</span><span class="plain"> **</span><span class="functiontext">Kinds::known_constructor_name</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">sn</span><span class="plain">) {</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"ACTIVITY_TY"</span><span class="plain">, &amp;</span><span class="identifier">CON_activity</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"COMBINATION_TY"</span><span class="plain">, &amp;</span><span class="identifier">CON_combination</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"DESCRIPTION_OF_TY"</span><span class="plain">, &amp;</span><span class="identifier">CON_description</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"INTERMEDIATE_TY"</span><span class="plain">, &amp;</span><span class="identifier">CON_INTERMEDIATE</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"KIND_VARIABLE_TY"</span><span class="plain">, &amp;</span><span class="identifier">CON_KIND_VARIABLE</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"LIST_OF_TY"</span><span class="plain">, &amp;</span><span class="identifier">CON_list_of</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"PHRASE_TY"</span><span class="plain">, &amp;</span><span class="identifier">CON_phrase</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"NIL_TY"</span><span class="plain">, &amp;</span><span class="identifier">CON_NIL</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"PROPERTY_TY"</span><span class="plain">, &amp;</span><span class="identifier">CON_property</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"RELATION_TY"</span><span class="plain">, &amp;</span><span class="identifier">CON_relation</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"RULE_TY"</span><span class="plain">, &amp;</span><span class="identifier">CON_rule</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"RULEBOOK_TY"</span><span class="plain">, &amp;</span><span class="identifier">CON_rulebook</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"TABLE_COLUMN_TY"</span><span class="plain">, &amp;</span><span class="identifier">CON_table_column</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"TUPLE_ENTRY_TY"</span><span class="plain">, &amp;</span><span class="identifier">CON_TUPLE_ENTRY</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"VARIABLE_TY"</span><span class="plain">, &amp;</span><span class="identifier">CON_variable</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">kind</span><span class="plain"> **</span><span class="functiontext">Kinds::known_kind_name</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">sn</span><span class="plain">) {</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"ARITHMETIC_VALUE_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_arithmetic_value</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"ENUMERATED_VALUE_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_enumerated_value</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"EQUATION_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_equation</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"TEXT_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_text</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"NUMBER_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_number</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"OBJECT_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_object</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"POINTER_VALUE_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_pointer_value</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"REAL_ARITHMETIC_VALUE_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_real_arithmetic_value</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"REAL_NUMBER_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_real_number</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"RESPONSE_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_response</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"RULEBOOK_OUTCOME_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_rulebook_outcome</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"SAYABLE_VALUE_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_sayable_value</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"SNIPPET_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_snippet</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"TABLE_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_table</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"TRUTH_STATE_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_truth_state</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"UNDERSTANDING_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_understanding</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"UNICODE_CHARACTER_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_unicode_character</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"USE_OPTION_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_use_option</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"VALUE_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_value</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"VERB_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_verb</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"WORD_VALUE_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_word_value</span><span class="plain">);</span>
<span class="identifier">IDENTIFIERS_CORRESPOND</span><span class="plain">(</span><span class="string">"NIL_TY"</span><span class="plain">, &amp;</span><span class="identifier">K_nil</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::known_name</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">sn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::known_constructor_name</span><span class="plain">(</span><span class="identifier">sn</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::known_kind_name</span><span class="plain">(</span><span class="identifier">sn</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::known_constructor_name is used in 2/kc2 (<a href="2-kc2.html#SP7">&#167;7</a>).</p>
<p class="endnote">The function Kinds::known_kind_name is used in 2/kc2 (<a href="2-kc2.html#SP7">&#167;7</a>).</p>
<p class="endnote">The function Kinds::known_name is used in 2/ki (<a href="2-ki.html#SP14_1">&#167;14.1</a>).</p>
<p class="inwebparagraph"><a id="SP35"></a><b>&#167;35. Annotating vocabulary. </b></p>
<pre class="display">
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::read_kind_marking_from_vocabulary</span><span class="plain">(</span><span class="identifier">vocabulary_entry</span><span class="plain"> *</span><span class="identifier">ve</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">ve</span><span class="plain">-&gt;</span><span class="identifier">means</span><span class="plain">.</span><span class="identifier">one_word_kind</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::mark_vocabulary_as_kind</span><span class="plain">(</span><span class="identifier">vocabulary_entry</span><span class="plain"> *</span><span class="identifier">ve</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="identifier">ve</span><span class="plain">-&gt;</span><span class="identifier">means</span><span class="plain">.</span><span class="identifier">one_word_kind</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">;</span>
<span class="identifier">Vocabulary::set_flags</span><span class="plain">(</span><span class="identifier">ve</span><span class="plain">, </span><span class="constant">KIND_FAST_MC</span><span class="plain">);</span>
<span class="identifier">Preform::mark_vocabulary</span><span class="plain">(</span><span class="identifier">ve</span><span class="plain">, &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt;);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::read_kind_marking_from_vocabulary is used in 2/dk (<a href="2-dk.html#SP10">&#167;10</a>).</p>
<p class="endnote">The function Kinds::mark_vocabulary_as_kind is used in 2/ki (<a href="2-ki.html#SP28_4">&#167;28.4</a>).</p>
<p class="inwebparagraph"><a id="SP36"></a><b>&#167;36. Errors. </b></p>
<pre class="definitions">
<span class="definitionkeyword">enum</span> <span class="constant">DimensionRedundant_KINDERROR</span><span class="definitionkeyword"> from </span><span class="constant">1</span>
<span class="definitionkeyword">enum</span> <span class="constant">DimensionNotBaseKOV_KINDERROR</span>
<span class="definitionkeyword">enum</span> <span class="constant">NonDimensional_KINDERROR</span>
<span class="definitionkeyword">enum</span> <span class="constant">UnitSequenceOverflow_KINDERROR</span>
<span class="definitionkeyword">enum</span> <span class="constant">DimensionsInconsistent_KINDERROR</span>
<span class="definitionkeyword">enum</span> <span class="constant">KindUnalterable_KINDERROR</span>
<span class="definitionkeyword">enum</span> <span class="constant">KindsCircular_KINDERROR</span>
<span class="definitionkeyword">enum</span> <span class="constant">LPCantScaleYet_KINDERROR</span>
<span class="definitionkeyword">enum</span> <span class="constant">LPCantScaleTwice_KINDERROR</span>
</pre>
<hr class="tocbar">
<ul class="toc"><li><a href="2-itk.html">Back to 'Introduction to Kinds'</a></li><li><a href="2-kc.html">Continue with 'Kind Checking'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>