1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 16:44:21 +03:00
inform7/docs/kinds-module/2-dk.html
2020-04-07 01:06:09 +01:00

984 lines
131 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>2/uk</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../compiler.html"><b>compiler tools</b></a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul>
<h2>Compiler Webs</h2>
<ul>
<li><a href="../inbuild/index.html">inbuild</a></li>
<li><a href="../inform7/index.html">inform7</a></li>
<li><a href="../inter/index.html">inter</a></li>
</ul>
<h2>Inbuild Modules</h2>
<ul>
<li><a href="../inbuild-module/index.html">inbuild</a></li>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../syntax-module/index.html">syntax</a></li>
<li><a href="../html-module/index.html">html</a></li>
</ul>
<h2>Inform7 Modules</h2>
<ul>
<li><a href="../core-module/index.html">core</a></li>
<li><a href="../problems-module/index.html">problems</a></li>
<li><a href="../inflections-module/index.html">inflections</a></li>
<li><a href="../linguistics-module/index.html">linguistics</a></li>
<li><a href="../kinds-module/index.html">kinds</a></li>
<li><a href="../if-module/index.html">if</a></li>
<li><a href="../multimedia-module/index.html">multimedia</a></li>
<li><a href="../index-module/index.html">index</a></li>
</ul>
<h2>Inter Modules</h2>
<ul>
<li><a href="../inter-module/index.html">inter</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../codegen-module/index.html">codegen</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '2/dk' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="../compiler.html">Compiler Modules</a></li><li><a href="index.html">kinds</a></li><li><a href="index.html#2">Chapter 2: Kinds</a></li><li><b>Describing Kinds</b></li></ul><p class="purpose">Translating kind structures to and from textual or run-time descriptions.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP4">&#167;4. The K-grammar</a></li><li><a href="#SP15">&#167;15. Kinds of kind</a></li><li><a href="#SP16">&#167;16. Parsing kind variables</a></li><li><a href="#SP21">&#167;21. Textual descriptions</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>We shall need these when parsing (see below):
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">NORMAL_KIND_PARSING</span><span class="plain"> </span><span class="constant">1</span>
<span class="definitionkeyword">define</span> <span class="constant">PHRASE_TOKEN_KIND_PARSING</span><span class="plain"> </span><span class="constant">2</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">kind_parsing_mode</span><span class="plain"> = </span><span class="constant">NORMAL_KIND_PARSING</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>For speed, we parse some kind names as single words, and others as common
nouns, which is slower:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">KIND_SLOW_MC</span><span class="plain"> </span><span class="constant">0x00000008</span><span class="plain"> </span><span class="comment">e.g., <code class="display"><span class="extract">weight</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">KIND_FAST_MC</span><span class="plain"> </span><span class="constant">0x01000000</span><span class="plain"> </span><span class="comment">number, text, relation, rule, ...</span>
</pre>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. The K-grammar. </b>This innermost of Inform's grammars is used to match the names of kinds. It's
a nicely unambiguous and clean language, with a specification closer to
traditional computer-science norms &mdash; this is not an accident: it allows for
awkward functional-programming needs in a way which vaguer natural language
syntax would not.
</p>
<p class="inwebparagraph">All K-grammar nonterminals begin with the "k-" prefix, and their result
pointers are to <code class="display"><span class="extract">kind</span></code> structures.
</p>
<p class="inwebparagraph">The K-grammar actually has two modes: normal, and phrase-token-mode. Normal
mode is aptly named: it's almost always the one we're using. Phrase token
mode is used only when parsing definitions of phrases, like so:
</p>
<blockquote>
<p>To repeat with (LV - nonexisting K variable) running from (V1 - arithmetic value of kind K) to (V2 - K)</p>
</blockquote>
<p class="inwebparagraph">Here the tokens "nonexisting K variable" and so on are parsed as
specifications, but in such a way that any kinds mentioned are parsed in
phrase-token-mode. The difference is that this enables them to refer to kind
variables such as K which are still being defined; in normal mode, that would
only be allowed if K already existed.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">if</span><span class="plain">-</span><span class="identifier">parsing</span><span class="plain">-</span><span class="identifier">phrase</span><span class="plain">-</span><span class="identifier">tokens</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> </span><span class="constant">0</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kind_parsing_mode</span><span class="plain"> != </span><span class="constant">NORMAL_KIND_PARSING</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="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>And the following internal is in fact only &lt;k-kind&gt; but inside phrase
token parsing mode; it's used when parsing the kind to be decided by a
phrase (which, like phrase tokens, can involve the variables).
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="reserved">for</span><span class="plain">-</span><span class="identifier">template</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">s</span><span class="plain"> = </span><span class="identifier">kind_parsing_mode</span><span class="plain">;</span>
<span class="identifier">kind_parsing_mode</span><span class="plain"> = </span><span class="constant">PHRASE_TOKEN_KIND_PARSING</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</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="identifier">W</span><span class="plain">);</span>
<span class="identifier">kind_parsing_mode</span><span class="plain"> = </span><span class="identifier">s</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">t</span><span class="plain">) { *</span><span class="identifier">XP</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;; </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="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>And here is that "name of kind..." construction, which is valid only in
phrase tokens.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">as</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">-</span><span class="identifier">token</span><span class="plain">&gt; ::=</span>
<span class="plain">( &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">as</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">-</span><span class="identifier">token</span><span class="plain">&gt; ) | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="identifier">name</span><span class="plain"> </span><span class="identifier">of</span><span class="plain"> </span><span class="reserved">kind</span><span class="plain"> </span><span class="identifier">of</span><span class="plain"> &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">abbreviating</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="identifier">name</span><span class="plain"> </span><span class="identifier">of</span><span class="plain"> </span><span class="reserved">kind</span><span class="plain"> &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">abbreviating</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="identifier">name</span><span class="plain"> </span><span class="identifier">of</span><span class="plain"> </span><span class="reserved">kind</span><span class="plain"> </span><span class="identifier">of</span><span class="plain"> ... | ==&gt; </span><span class="identifier">NULL</span>
<span class="identifier">name</span><span class="plain"> </span><span class="identifier">of</span><span class="plain"> </span><span class="reserved">kind</span><span class="plain"> ... ==&gt; </span><span class="identifier">NULL</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">abbreviating</span><span class="plain">&gt; ::=</span>
<span class="plain">( &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">abbreviating</span><span class="plain">&gt; ) | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">of</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">formal</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">variable</span><span class="plain">&gt; | ==&gt; </span><span class="functiontext">Kinds::variable_construction</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">[2], </span><span class="identifier">RP</span><span class="plain">[1])</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>So now we can begin properly. Every valid kind matches &lt;k-kind&gt;:
</p>
<pre class="display">
<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">( &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; ) | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">^&lt;</span><span class="reserved">if</span><span class="plain">-</span><span class="identifier">parsing</span><span class="plain">-</span><span class="identifier">phrase</span><span class="plain">-</span><span class="identifier">tokens</span><span class="plain">&gt; &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">variable</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[2]</span>
<span class="plain">&lt;</span><span class="reserved">if</span><span class="plain">-</span><span class="identifier">parsing</span><span class="plain">-</span><span class="identifier">phrase</span><span class="plain">-</span><span class="identifier">tokens</span><span class="plain">&gt; &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">variable</span><span class="plain">-</span><span class="identifier">definition</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[2]</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">base</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">irregular</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">construction</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">construction</span><span class="plain">&gt; ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>And, as a convenient shorthand:
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">articled</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">indefinite</span><span class="plain">-</span><span class="identifier">article</span><span class="plain">&gt; &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[2]</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>In phrase-token mode, kind variables are treated as formal symbols, not as
the kinds which are their current values:
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">variable</span><span class="plain">-</span><span class="identifier">definition</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">formal</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">variable</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">of</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; </span><span class="identifier">of</span><span class="plain"> </span><span class="reserved">kind</span><span class="plain"> &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">formal</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">variable</span><span class="plain">&gt; ==&gt; </span><span class="functiontext">Kinds::variable_construction</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">[2], </span><span class="identifier">RP</span><span class="plain">[1])</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>Some base kinds with one-word names have that word flagged with a direct
pointer to the kind, for speed of parsing. Names of base kinds, such as
"number" or "vehicle", can be registered in two different ways (according
to whether they come from the source text or from template files), so we then
make two further checks:
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">base</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; </span><span class="identifier">internal</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">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::empty</span><span class="plain">(</span><span class="identifier">W</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">Wordings::length</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">) == </span><span class="constant">1</span><span class="plain">) </span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Kinds::read_kind_marking_from_vocabulary</span><span class="plain">(</span><span class="identifier">Lexer::word</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</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">if</span><span class="plain"> (&lt;</span><span class="identifier">definite</span><span class="plain">-</span><span class="identifier">article</span><span class="plain">&gt;(</span><span class="identifier">Wordings::first_word</span><span class="plain">(</span><span class="identifier">W</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="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">ExParser::parse_excerpt</span><span class="plain">(</span><span class="constant">KIND_SLOW_MC</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="identifier">excerpt_meaning</span><span class="plain"> *</span><span class="identifier">em</span><span class="plain"> = </span><span class="identifier">ParseTree::get_meaning</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="functiontext">Kinds::base_construction</span><span class="plain">(</span>
<span class="identifier">RETRIEVE_POINTER_kind_constructor</span><span class="plain">(</span><span class="identifier">ExcerptMeanings::data</span><span class="plain">(</span><span class="identifier">em</span><span class="plain">)));</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">p</span><span class="plain"> = </span><span class="identifier">ExParser::parse_excerpt</span><span class="plain">(</span><span class="identifier">NOUN_MC</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</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::disambiguate</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">HIGH_NOUN_PRIORITY</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nt</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="identifier">RETRIEVE_POINTER_kind_constructor</span><span class="plain">(</span><span class="identifier">Nouns::tag_holder</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)));</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">) { *</span><span class="identifier">XP</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">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="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>"Object based rulebook" has been on a voyage of unhyphenation: in the
early public beta of Inform 7, it was "object-based-rulebook" (at that
time, built-in kinds had to have one-word names); then it became "object-based
rulebook", when one-word adjectives were allowed to modify the names of
built-in kinds; and now it is preferably "object based rulebook". But the
previous syntax is permitted as an alias to keep old source text working.
And similarly for the others here, except "either/or property", which is a
2010 addition.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">irregular</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">construction</span><span class="plain">&gt; ::=</span>
<span class="identifier">indexed</span><span class="plain"> </span><span class="identifier">text</span><span class="plain"> | ==&gt; </span><span class="identifier">K_text</span>
<span class="identifier">indexed</span><span class="plain"> </span><span class="identifier">texts</span><span class="plain"> | ==&gt; </span><span class="identifier">K_text</span>
<span class="identifier">stored</span><span class="plain"> </span><span class="identifier">action</span><span class="plain"> | ==&gt; </span><span class="identifier">K_stored_action</span><span class="plain">; </span><span class="reserved">if</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">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">stored</span><span class="plain"> </span><span class="identifier">actions</span><span class="plain"> | ==&gt; </span><span class="identifier">K_stored_action</span><span class="plain">; </span><span class="reserved">if</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">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">object</span><span class="plain">-</span><span class="identifier">based</span><span class="plain"> </span><span class="identifier">rulebook</span><span class="plain"> </span><span class="identifier">producing</span><span class="plain"> &lt;</span><span class="identifier">indefinite</span><span class="plain">-</span><span class="identifier">article</span><span class="plain">&gt; &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; | ==&gt; </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_rulebook</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">RP</span><span class="plain">[2])</span>
<span class="identifier">object</span><span class="plain">-</span><span class="identifier">based</span><span class="plain"> </span><span class="identifier">rulebook</span><span class="plain"> </span><span class="identifier">producing</span><span class="plain"> &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; | ==&gt; </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_rulebook</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">RP</span><span class="plain">[1])</span>
<span class="identifier">object</span><span class="plain">-</span><span class="identifier">based</span><span class="plain"> </span><span class="identifier">rulebook</span><span class="plain"> | ==&gt; </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_rulebook</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">K_nil</span><span class="plain">)</span>
<span class="identifier">action</span><span class="plain">-</span><span class="identifier">based</span><span class="plain"> </span><span class="identifier">rulebook</span><span class="plain"> | ==&gt; </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_rulebook</span><span class="plain">, </span><span class="identifier">K_action_name</span><span class="plain">, </span><span class="identifier">K_nil</span><span class="plain">); </span><span class="reserved">if</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">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">object</span><span class="plain">-</span><span class="identifier">based</span><span class="plain"> </span><span class="identifier">rule</span><span class="plain"> </span><span class="identifier">producing</span><span class="plain"> &lt;</span><span class="identifier">indefinite</span><span class="plain">-</span><span class="identifier">article</span><span class="plain">&gt; &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; | ==&gt; </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_rule</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">RP</span><span class="plain">[2])</span>
<span class="identifier">object</span><span class="plain">-</span><span class="identifier">based</span><span class="plain"> </span><span class="identifier">rule</span><span class="plain"> </span><span class="identifier">producing</span><span class="plain"> &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; | ==&gt; </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_rule</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">RP</span><span class="plain">[1])</span>
<span class="identifier">object</span><span class="plain">-</span><span class="identifier">based</span><span class="plain"> </span><span class="identifier">rule</span><span class="plain"> | ==&gt; </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_rule</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">K_nil</span><span class="plain">)</span>
<span class="identifier">action</span><span class="plain">-</span><span class="identifier">based</span><span class="plain"> </span><span class="identifier">rule</span><span class="plain"> | ==&gt; </span><span class="functiontext">Kinds::binary_construction</span><span class="plain">(</span><span class="identifier">CON_rule</span><span class="plain">, </span><span class="identifier">K_action_name</span><span class="plain">, </span><span class="identifier">K_nil</span><span class="plain">); </span><span class="reserved">if</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">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">either</span><span class="plain">-</span><span class="identifier">or</span><span class="plain"> </span><span class="identifier">property</span><span class="plain"> ==&gt; </span><span class="functiontext">Kinds::unary_construction</span><span class="plain">(</span><span class="identifier">CON_property</span><span class="plain">, </span><span class="identifier">K_truth_state</span><span class="plain">)</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>This loop looks a little slow, but there are only about 10 proper constructors.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">construction</span><span class="plain">&gt; </span><span class="identifier">internal</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="functiontext">Kinds::Constructors::arity</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Textual::parse_constructor_name</span><span class="plain">(</span><span class="identifier">con</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>
&lt;<span class="cwebmacro">See if this partial kind-constructor match works out</span> <span class="cwebmacronumber">12.1</span>&gt;<span class="plain">;</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="inwebparagraph"><a id="SP12_1"></a><b>&#167;12.1. </b>So at this point we have a match of the fixed words in the constructor.
For example, we might have "list of ...", where the X excerpt represents
the "..." and the Y excerpt is empty; or "... based rule producing ...",
where both X and Y are non-empty; or even something like "relation",
where both X and Y are empty.
</p>
<p class="inwebparagraph">We try to match X and Y against kinds, filling in defaults if either is
unspecified because a short form of the constructor is used (e.g.,
"relation" instead of "relation of ..." or "relation of ... to ...").
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">See if this partial kind-constructor match works out</span> <span class="cwebmacronumber">12.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">KX</span><span class="plain"> = </span><span class="identifier">K_value</span><span class="plain">, *</span><span class="identifier">KY</span><span class="plain"> = </span><span class="identifier">K_value</span><span class="plain">;</span>
&lt;<span class="cwebmacro">The rule and rulebook constructors default to actions for X</span> <span class="cwebmacronumber">12.1.1</span>&gt;<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">X</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">tupling</span><span class="plain"> = </span><span class="functiontext">Kinds::Constructors::tupling</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">tupling</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) &amp;&amp; (&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">single</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt;(</span><span class="identifier">X</span><span class="plain">))) </span><span class="identifier">KX</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">tupling</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">) &amp;&amp; (&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">optional</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt;(</span><span class="identifier">X</span><span class="plain">))) </span><span class="identifier">KX</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">tupling</span><span class="plain"> &gt;= </span><span class="constant">2</span><span class="plain">) &amp;&amp; (&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">tupled</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt;(</span><span class="identifier">X</span><span class="plain">))) </span><span class="identifier">KX</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">KX</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</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">Y</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">tupling</span><span class="plain"> = </span><span class="functiontext">Kinds::Constructors::tupling</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">tupling</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) &amp;&amp; (&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">single</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt;(</span><span class="identifier">Y</span><span class="plain">))) </span><span class="identifier">KY</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">tupling</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">) &amp;&amp; (&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">optional</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt;(</span><span class="identifier">Y</span><span class="plain">))) </span><span class="identifier">KY</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">tupling</span><span class="plain"> &gt;= </span><span class="constant">2</span><span class="plain">) &amp;&amp; (&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">tupled</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt;(</span><span class="identifier">Y</span><span class="plain">))) </span><span class="identifier">KY</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">KY</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">The relation constructor defaults to Y matching X, if X is specified</span> <span class="cwebmacronumber">12.1.2</span>&gt;<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">) == </span><span class="constant">1</span><span class="plain">) &amp;&amp; (</span><span class="identifier">KX</span><span class="plain">)) {</span>
<span class="plain">*</span><span class="identifier">XP</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">KX</span><span class="plain">); </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<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">) == </span><span class="constant">2</span><span class="plain">) &amp;&amp; (</span><span class="identifier">KX</span><span class="plain">) &amp;&amp; (</span><span class="identifier">KY</span><span class="plain">)) {</span>
<span class="plain">*</span><span class="identifier">XP</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">KX</span><span class="plain">, </span><span class="identifier">KY</span><span class="plain">); </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP12_1_1"></a><b>&#167;12.1.1. </b>Ordinarily missing X or Y are filled in as "value", but...
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">The rule and rulebook constructors default to actions for X</span> <span class="cwebmacronumber">12.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">con</span><span class="plain"> == </span><span class="identifier">CON_rule</span><span class="plain">) || (</span><span class="identifier">con</span><span class="plain"> == </span><span class="identifier">CON_rulebook</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K_action_name</span><span class="plain">) </span><span class="identifier">KX</span><span class="plain"> = </span><span class="identifier">K_action_name</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">KX</span><span class="plain"> = </span><span class="identifier">K_nil</span><span class="plain">;</span>
<span class="identifier">KY</span><span class="plain"> = </span><span class="identifier">K_nil</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12_1">&#167;12.1</a>.</p>
<p class="inwebparagraph"><a id="SP12_1_2"></a><b>&#167;12.1.2. </b>And...
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">The relation constructor defaults to Y matching X, if X is specified</span> <span class="cwebmacronumber">12.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">con</span><span class="plain"> == </span><span class="identifier">CON_relation</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Wordings::empty</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">))) </span><span class="identifier">KY</span><span class="plain"> = </span><span class="identifier">KX</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12_1">&#167;12.1</a>.</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b>Where the materials used in construction are not quite kinds, but can
be more varied.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">single</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt; ::=</span>
<span class="plain">( &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">single</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt; ) | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">article</span><span class="plain">&gt; &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">single</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[2]</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">optional</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt; ::=</span>
<span class="plain">( &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">optional</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt; ) | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">article</span><span class="plain">&gt; &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">optional</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[2]</span>
<span class="identifier">nothing</span><span class="plain"> | ==&gt; </span><span class="identifier">K_nil</span>
<span class="identifier">action</span><span class="plain"> | ==&gt; </span><span class="identifier">K_action_name</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">tupled</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt; ::=</span>
<span class="plain">( &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">tuple</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt; ) | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="identifier">nothing</span><span class="plain"> | ==&gt; </span><span class="identifier">K_nil</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">single</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt; ==&gt; </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">RP</span><span class="plain">[1], </span><span class="identifier">K_nil</span><span class="plain">)</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">tuple</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">single</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt; , &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">tuple</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt; | ==&gt; </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">RP</span><span class="plain">[1], </span><span class="identifier">RP</span><span class="plain">[2])</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">single</span><span class="plain">-</span><span class="identifier">material</span><span class="plain">&gt; ==&gt; </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">RP</span><span class="plain">[1], </span><span class="identifier">K_nil</span><span class="plain">)</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. </b>The following looks at a word range and tries to find text making a kind
construction: if it does, it adjusts the word ranges to the kind(s) being
constructed on, and returns <code class="display"><span class="extract">TRUE</span></code>; if it fails, it returns <code class="display"><span class="extract">FALSE</span></code>. For
instance, given "list of marbles", it adjusts the word range to "marbles"
and returns <code class="display"><span class="extract">TRUE</span></code>.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Textual::parse_constructor_name</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">wording</span><span class="plain"> *</span><span class="identifier">KW</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> *</span><span class="identifier">LW</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="identifier">KW</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">p</span><span class="plain">=1; </span><span class="identifier">p</span><span class="plain">&lt;=2; </span><span class="identifier">p</span><span class="plain">++) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">NW</span><span class="plain"> = </span><span class="functiontext">Kinds::Constructors::get_name</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">, (</span><span class="identifier">p</span><span class="plain">==1)?</span><span class="identifier">FALSE:TRUE</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">NW</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">full_length</span><span class="plain"> = </span><span class="identifier">Wordings::length</span><span class="plain">(</span><span class="identifier">NW</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k1</span><span class="plain"> = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">NW</span><span class="plain">);</span>
<span class="plain">*</span><span class="identifier">KW</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">; *</span><span class="identifier">LW</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Try this as a constructor name</span> <span class="cwebmacronumber">14.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">*</span><span class="identifier">KW</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">; *</span><span class="identifier">LW</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</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::Textual::parse_constructor_name is used in <a href="#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP14_1"></a><b>&#167;14.1. </b>Note that the name text for a constructor is likely to have a form like so:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">relation STROKE relation of k to l STROKE relation of k</span>
</pre>
<p class="inwebparagraph">with multiple possibilities divided by strokes; each possibility must be
checked for.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Try this as a constructor name</span> <span class="cwebmacronumber">14.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">base</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">length</span><span class="plain"> = </span><span class="identifier">full_length</span><span class="plain">;</span>
<span class="reserved">int</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">=0; </span><span class="identifier">k</span><span class="plain">&lt;</span><span class="identifier">full_length</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">Lexer::word</span><span class="plain">(</span><span class="identifier">k1</span><span class="plain">+</span><span class="identifier">k</span><span class="plain">) == </span><span class="identifier">STROKE_V</span><span class="plain">) {</span>
<span class="identifier">length</span><span class="plain"> = </span><span class="identifier">k</span><span class="plain"> - </span><span class="identifier">base</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">length</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span>&lt;<span class="cwebmacro">Try one option among the constructor's names</span> <span class="cwebmacronumber">14.1.1</span>&gt;<span class="character">;</span>
<span class="identifier">base</span><span class="plain"> = </span><span class="identifier">k</span><span class="plain">+1;</span>
<span class="plain">}</span>
<span class="identifier">length</span><span class="plain"> = </span><span class="identifier">full_length</span><span class="plain"> - </span><span class="identifier">base</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">length</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span>&lt;<span class="cwebmacro">Try one option among the constructor's names</span> <span class="cwebmacronumber">14.1.1</span>&gt;<span class="character">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP14">&#167;14</a>.</p>
<p class="inwebparagraph"><a id="SP14_1_1"></a><b>&#167;14.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Try one option among the constructor's names</span> <span class="cwebmacronumber">14.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::length</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">) &gt;= </span><span class="identifier">length</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">failed</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0, </span><span class="identifier">p</span><span class="plain">=</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">length</span><span class="plain">; </span><span class="identifier">i</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="identifier">Lexer::word</span><span class="plain">(</span><span class="identifier">k1</span><span class="plain">+</span><span class="identifier">base</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ve</span><span class="plain"> == </span><span class="identifier">CAPITAL_K_V</span><span class="plain">) || (</span><span class="identifier">ve</span><span class="plain"> == </span><span class="identifier">CAPITAL_L_V</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">from</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="identifier">i</span><span class="plain"> == </span><span class="identifier">length</span><span class="plain">-1) { </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)+1; }</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">bl</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain"> &lt;= </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="identifier">vocabulary_entry</span><span class="plain"> *</span><span class="identifier">nw</span><span class="plain"> = </span><span class="identifier">Lexer::word</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="identifier">nw</span><span class="plain"> == </span><span class="identifier">OPENBRACKET_V</span><span class="plain">) </span><span class="identifier">bl</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">nw</span><span class="plain"> == </span><span class="identifier">CLOSEBRACKET_V</span><span class="plain">) </span><span class="identifier">bl</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">bl</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nw</span><span class="plain"> == </span><span class="identifier">Lexer::word</span><span class="plain">(</span><span class="identifier">k1</span><span class="plain">+</span><span class="identifier">base</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">+1)) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">p</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain"> &gt; </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) { </span><span class="identifier">failed</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">; }</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ve</span><span class="plain"> == </span><span class="identifier">CAPITAL_K_V</span><span class="plain">) { *</span><span class="identifier">KW</span><span class="plain"> = </span><span class="identifier">Wordings::new</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">-1); }</span>
<span class="reserved">else</span><span class="plain"> { *</span><span class="identifier">LW</span><span class="plain"> = </span><span class="identifier">Wordings::new</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">-1); }</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ve</span><span class="plain"> != </span><span class="identifier">Lexer::word</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">++)) { </span><span class="identifier">failed</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">; }</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain"> != </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)+1) </span><span class="identifier">failed</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="identifier">failed</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP14_1">&#167;14.1</a> (twice).</p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. Kinds of kind. </b>This is actually just &lt;k-kind&gt; in disguise, but only lets the result through
if it's a kind of kind, like "arithmetic value"; something like "number"
or "list of texts" will fail.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">of</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt; ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]; </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Behaviour::is_kind_of_kind</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1]) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. Parsing kind variables. </b>As a small detour, here's how we deal with the pleasingly simple names A to Z
for kind variables, converting them to and from the numbers 1 to 26:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Textual::parse_variable</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">if</span><span class="plain"> (</span><span class="identifier">ve</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::Textual::parse_kind_variable_name</span><span class="plain">(</span><span class="identifier">Vocabulary::get_exemplar</span><span class="plain">(</span><span class="identifier">ve</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">), </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Textual::parse_kind_variable_name</span><span class="plain">(</span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">allow_lower</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[1] == </span><span class="constant">0</span><span class="plain">) || ((</span><span class="identifier">p</span><span class="plain">[1] == </span><span class="character">'s'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[2] == </span><span class="constant">0</span><span class="plain">))) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[0] &gt;= </span><span class="character">'A'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[0] &lt;= </span><span class="character">'Z'</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">p</span><span class="plain">[0] - </span><span class="character">'A'</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">allow_lower</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[0] &gt;= </span><span class="character">'a'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[0] &lt;= </span><span class="character">'z'</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">p</span><span class="plain">[0] - </span><span class="character">'a'</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Textual::parse_kind_variable_name_singular</span><span class="plain">(</span><span class="identifier">wchar_t</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="identifier">p</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[1] == </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[0] &gt;= </span><span class="character">'A'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[0] &lt;= </span><span class="character">'Z'</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">p</span><span class="plain">[0] - </span><span class="character">'A'</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Textual::parse_variable appears nowhere else.</p>
<p class="endnote">The function Kinds::Textual::parse_kind_variable_name is used in <a href="#SP17">&#167;17</a>, <a href="#SP18">&#167;18</a>.</p>
<p class="endnote">The function Kinds::Textual::parse_kind_variable_name_singular is used in <a href="#SP19">&#167;19</a>.</p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. </b>Kind variables are written with the letters A to Z. That provides for only
26 of them, but it's very, very rare to need more than 2, in practice. At
one time I was tempted by the syntax used in the early functional programming
language Miranda (1985), which uses rows of asterisks <code class="display"><span class="extract">*</span></code>, <code class="display"><span class="extract">**</span></code>, <code class="display"><span class="extract">***</span></code>, and
so on as needed. But using the letters seemed fractionally closer to natural
language conventions. In English, we do say pseudo-algebraic things like
"So, let's call our spy Mr X." &mdash; or at least we do if we lead slightly
more exciting lives than the present author. The use of letters emphasises
that this is some kind of reference, not a direct identification. Whereas
when we use asterisks, it's with an air of censorship, of something that
must not be named (compare St\'ephanie de Genlis's gothic novella "Histoire
de la duchesse de C***", 1782).
</p>
<p class="inwebparagraph">The following nonterminal matches only those kind variables whose values are
actually set, and it returns those values. This is how kind variables are
parsed almost all of the time.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">variable</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> </span><span class="constant">1</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain"> = </span><span class="functiontext">Kinds::Textual::parse_kind_variable_name</span><span class="plain">(</span><span class="identifier">Lexer::word_raw_text</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</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="constant">0</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="functiontext">Kinds::variable_from_context</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">X</span><span class="plain"> = </span><span class="identifier">k</span><span class="plain">; *</span><span class="identifier">XP</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">TRUE</span><span class="plain">; }</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="inwebparagraph"><a id="SP18"></a><b>&#167;18. </b>But we can also formally parse A to Z as their own abstract identities;
now they always parse, regardless of what might be stored in them, and
they aren't replaced with their values (which they may not even have).
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">formal</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">variable</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> </span><span class="constant">1</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain"> = </span><span class="functiontext">Kinds::Textual::parse_kind_variable_name</span><span class="plain">(</span><span class="identifier">Lexer::word_raw_text</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</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="constant">0</span><span class="plain">) {</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="identifier">XP</span><span class="plain"> = </span><span class="functiontext">Kinds::variable_construction</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">TRUE</span><span class="plain">;</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="inwebparagraph"><a id="SP19"></a><b>&#167;19. </b>And it's also convenient to have:
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">formal</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">variable</span><span class="plain">-</span><span class="identifier">singular</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> </span><span class="constant">1</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain"> = </span><span class="functiontext">Kinds::Textual::parse_kind_variable_name_singular</span><span class="plain">(</span><span class="identifier">Lexer::word_raw_text</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</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="constant">0</span><span class="plain">) {</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="identifier">XP</span><span class="plain"> = </span><span class="functiontext">Kinds::variable_construction</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">TRUE</span><span class="plain">;</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="inwebparagraph"><a id="SP20"></a><b>&#167;20. </b>For efficiency's sake, we don't actually parse directly using this
nonterminal, but it's needed all the same because of Preform's optimisations.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">-</span><span class="identifier">variable</span><span class="plain">-</span><span class="identifier">texts</span><span class="plain">&gt; ::=</span>
<span class="identifier">a</span><span class="plain">/</span><span class="identifier">as</span><span class="plain"> |</span>
<span class="identifier">b</span><span class="plain">/</span><span class="identifier">bs</span><span class="plain"> |</span>
<span class="identifier">c</span><span class="plain">/</span><span class="identifier">cs</span><span class="plain"> |</span>
<span class="identifier">d</span><span class="plain">/</span><span class="identifier">ds</span><span class="plain"> |</span>
<span class="identifier">e</span><span class="plain">/</span><span class="identifier">es</span><span class="plain"> |</span>
<span class="identifier">f</span><span class="plain">/</span><span class="identifier">fs</span><span class="plain"> |</span>
<span class="identifier">g</span><span class="plain">/</span><span class="identifier">gs</span><span class="plain"> |</span>
<span class="identifier">h</span><span class="plain">/</span><span class="identifier">hs</span><span class="plain"> |</span>
<span class="identifier">i</span><span class="plain">/</span><span class="identifier">is</span><span class="plain"> |</span>
<span class="identifier">j</span><span class="plain">/</span><span class="identifier">js</span><span class="plain"> |</span>
<span class="identifier">k</span><span class="plain">/</span><span class="identifier">ks</span><span class="plain"> |</span>
<span class="identifier">l</span><span class="plain">/</span><span class="identifier">ls</span><span class="plain"> |</span>
<span class="identifier">m</span><span class="plain">/</span><span class="identifier">ms</span><span class="plain"> |</span>
<span class="identifier">n</span><span class="plain">/</span><span class="identifier">ns</span><span class="plain"> |</span>
<span class="identifier">o</span><span class="plain">/</span><span class="identifier">os</span><span class="plain"> |</span>
<span class="identifier">p</span><span class="plain">/</span><span class="identifier">ps</span><span class="plain"> |</span>
<span class="identifier">q</span><span class="plain">/</span><span class="identifier">qs</span><span class="plain"> |</span>
<span class="identifier">r</span><span class="plain">/</span><span class="identifier">rs</span><span class="plain"> |</span>
<span class="identifier">s</span><span class="plain">/</span><span class="identifier">ss</span><span class="plain"> |</span>
<span class="identifier">t</span><span class="plain">/</span><span class="identifier">ts</span><span class="plain"> |</span>
<span class="identifier">u</span><span class="plain">/</span><span class="identifier">us</span><span class="plain"> |</span>
<span class="identifier">v</span><span class="plain">/</span><span class="identifier">vs</span><span class="plain"> |</span>
<span class="identifier">w</span><span class="plain">/</span><span class="identifier">ws</span><span class="plain"> |</span>
<span class="identifier">x</span><span class="plain">/</span><span class="identifier">xs</span><span class="plain"> |</span>
<span class="identifier">y</span><span class="plain">/</span><span class="identifier">ys</span><span class="plain"> |</span>
<span class="identifier">z</span><span class="plain">/</span><span class="identifier">zs</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP21"></a><b>&#167;21. Textual descriptions. </b>The following pretty-printer is inverse to the code which parses text and
turns it into a <code class="display"><span class="extract">kind</span></code> structure, or very nearly so. We use common
code to handle all of the reasons why we might want to spell out a kind
in words &mdash; the log, the index, problem messages, comments in code, and
so on. For example:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Textual::log</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="functiontext">Kinds::Textual::write</span><span class="plain">(</span><span class="identifier">DL</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::Textual::log appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP22"></a><b>&#167;22. </b>Thus we have a basic pretty-printer...
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Textual::write</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</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="functiontext">Kinds::Textual::write_inner</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Textual::write_plural</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</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="functiontext">Kinds::Textual::write_inner</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">TRUE</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::Textual::write is used in <a href="#SP21">&#167;21</a>, <a href="#SP24_1_2">&#167;24.1.2</a>, 2/dmn (<a href="2-dmn.html#SP28">&#167;28</a>).</p>
<p class="endnote">The function Kinds::Textual::write_plural appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP23"></a><b>&#167;23. </b>...and also one which prefaces the kind name with an article.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Textual::write_articled</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</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">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">);</span>
<span class="functiontext">Kinds::Textual::write_inner</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="identifier">ArticleInflection::preface_by_article</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">TEMP</span><span class="plain">, </span><span class="identifier">English_language</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Textual::write_articled appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP24"></a><b>&#167;24. </b>In all cases we make use of the following recursive method:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Textual::write_inner</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</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">int</span><span class="plain"> </span><span class="identifier">plural_form</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">substituting</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="identifier">WRITE</span><span class="plain">(</span><span class="string">"nothing"</span><span class="plain">); </span><span class="reserved">return</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">K_nil</span><span class="plain">) { </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"nothing"</span><span class="plain">); </span><span class="reserved">return</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">NULL</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="identifier">con</span><span class="plain"> = </span><span class="functiontext">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Write punctuation kinds out to the stream</span> <span class="cwebmacronumber">24.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">con</span><span class="plain">) </span>&lt;<span class="cwebmacro">Write constructor kinds out to the stream</span> <span class="cwebmacronumber">24.3</span>&gt;
<span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Write base kinds out to the stream</span> <span class="cwebmacronumber">24.2</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Textual::write_inner is used in <a href="#SP22">&#167;22</a>, <a href="#SP23">&#167;23</a>, <a href="#SP24_1_1">&#167;24.1.1</a>, <a href="#SP24_1_2">&#167;24.1.2</a>, <a href="#SP25">&#167;25</a>.</p>
<p class="inwebparagraph"><a id="SP24_1"></a><b>&#167;24.1. </b>Note that we do cheat in one case, in our resolve to have only a single
written form for kinds in all contexts &mdash; we give a low-level description of
an intermediate value in the debugging log. But such a thing can't be exposed
higher up in Inform, so it's no loss to the index, problem messages, etc.,
to miss out on this detail.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Write punctuation kinds out to the stream</span> <span class="cwebmacronumber">24.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">con</span><span class="plain"> = </span><span class="functiontext">Kinds::get_construct</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">con</span><span class="plain"> == </span><span class="identifier">CON_NIL</span><span class="plain">) { </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"nothing&lt;nil&gt;"</span><span class="plain">); </span><span class="reserved">return</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_TUPLE_ENTRY</span><span class="plain">) { </span>&lt;<span class="cwebmacro">Describe a continuing tuple</span> <span class="cwebmacronumber">24.1.1</span>&gt;<span class="plain">; </span><span class="reserved">return</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>&lt;<span class="cwebmacro">Describe a kind variable, either by name or by value</span> <span class="cwebmacronumber">24.1.2</span>&gt;<span class="plain">; </span><span class="reserved">return</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_INTERMEDIATE</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">OUT</span><span class="plain"> == </span><span class="identifier">DL</span><span class="plain">)</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$Q"</span><span class="plain">, </span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">));</span>
<span class="reserved">else</span>
<span class="functiontext">Kinds::Dimensions::index_unit_sequence</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">), </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP24">&#167;24</a>.</p>
<p class="inwebparagraph"><a id="SP24_1_1"></a><b>&#167;24.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Describe a continuing tuple</span> <span class="cwebmacronumber">24.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">head</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">tail</span><span class="plain"> = </span><span class="identifier">NULL</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">head</span><span class="plain">, &amp;</span><span class="identifier">tail</span><span class="plain">);</span>
<span class="functiontext">Kinds::Textual::write_inner</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">head</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">substituting</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">tail</span><span class="plain">) != </span><span class="identifier">CON_NIL</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">", "</span><span class="plain">);</span>
<span class="functiontext">Kinds::Textual::write_inner</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">tail</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">substituting</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP24_1">&#167;24.1</a>.</p>
<p class="inwebparagraph"><a id="SP24_1_2"></a><b>&#167;24.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Describe a kind variable, either by name or by value</span> <span class="cwebmacronumber">24.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">vn</span><span class="plain"> = </span><span class="functiontext">Kinds::get_variable_number</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">substituting</span><span class="plain">) &amp;&amp; (</span><span class="identifier">vn</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">)) {</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">subst</span><span class="plain"> = </span><span class="functiontext">Kinds::variable_from_context</span><span class="plain">(</span><span class="identifier">vn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">subst</span><span class="plain">) { </span><span class="functiontext">Kinds::Textual::write_inner</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">subst</span><span class="plain">, </span><span class="identifier">plural_form</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="plain">}</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%c"</span><span class="plain">, </span><span class="character">'A'</span><span class="plain"> + </span><span class="identifier">vn</span><span class="plain"> - </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">plural_form</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"s"</span><span class="plain">);</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain"> = </span><span class="functiontext">Kinds::get_variable_stipulation</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">S</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" ["</span><span class="plain">); </span><span class="functiontext">Kinds::Textual::write</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">); </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"]"</span><span class="plain">); }</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP24_1">&#167;24.1</a>.</p>
<p class="inwebparagraph"><a id="SP24_2"></a><b>&#167;24.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Write base kinds out to the stream</span> <span class="cwebmacronumber">24.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%W"</span><span class="plain">, </span><span class="functiontext">Kinds::Behaviour::get_name</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">plural_form</span><span class="plain">));</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP24">&#167;24</a>.</p>
<p class="inwebparagraph"><a id="SP24_3"></a><b>&#167;24.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Write constructor kinds out to the stream</span> <span class="cwebmacronumber">24.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">first_base</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">second_base</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="functiontext">Kinds::Constructors::arity</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">) == </span><span class="constant">1</span><span class="plain">)</span>
<span class="identifier">first_base</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">else</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">first_base</span><span class="plain">, &amp;</span><span class="identifier">second_base</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Make a special case for either/or properties</span> <span class="cwebmacronumber">24.3.1</span>&gt;<span class="plain">;</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">KW</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_name</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">plural_form</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k1</span><span class="plain"> = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">KW</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">full_length</span><span class="plain"> = </span><span class="identifier">Wordings::length</span><span class="plain">(</span><span class="identifier">KW</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Choose which form of the constructor to use when writing this out</span> <span class="cwebmacronumber">24.3.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Actually write out the chosen form of the constructor</span> <span class="cwebmacronumber">24.3.3</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP24">&#167;24</a>.</p>
<p class="inwebparagraph"><a id="SP24_3_1"></a><b>&#167;24.3.1. </b>Since Inform reads "either/or property" as syntactic sugar for "truth
state valued property", we'll also write it: it's a much more familiar
usage.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Make a special case for either/or properties</span> <span class="cwebmacronumber">24.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">con</span><span class="plain"> == </span><span class="identifier">CON_property</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">first_base</span><span class="plain">, </span><span class="identifier">K_truth_state</span><span class="plain">))) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"either/or property"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP24_3">&#167;24.3</a>.</p>
<p class="inwebparagraph"><a id="SP24_3_2"></a><b>&#167;24.3.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Choose which form of the constructor to use when writing this out</span> <span class="cwebmacronumber">24.3.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_present</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">l_present</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="comment">these initialisations can have no effect but gcc requires them</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">choice_from</span><span class="plain">[2][2], </span><span class="identifier">choice_to</span><span class="plain">[2][2];</span>
&lt;<span class="cwebmacro">Determine the possible forms for writing this constructor</span> <span class="cwebmacronumber">24.3.2.1</span>&gt;<span class="plain">;</span>
<span class="identifier">k_present</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">; </span><span class="identifier">l_present</span><span class="plain"> = </span><span class="constant">1</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_rule</span><span class="plain">) || (</span><span class="identifier">con</span><span class="plain"> == </span><span class="identifier">CON_rulebook</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">first_base</span><span class="plain">, </span><span class="identifier">K_action_name</span><span class="plain">)) </span><span class="identifier">k_present</span><span class="plain"> = </span><span class="constant">0</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="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">first_base</span><span class="plain">, </span><span class="identifier">K_nil</span><span class="plain">)) </span><span class="identifier">k_present</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</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_property</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">first_base</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">))) </span><span class="identifier">k_present</span><span class="plain"> = </span><span class="constant">0</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_table_column</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">first_base</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">))) </span><span class="identifier">k_present</span><span class="plain"> = </span><span class="constant">0</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_relation</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">first_base</span><span class="plain">, </span><span class="identifier">second_base</span><span class="plain">))) </span><span class="identifier">l_present</span><span class="plain"> = </span><span class="constant">0</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">) == </span><span class="constant">1</span><span class="plain">) </span><span class="identifier">l_present</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">second_base</span><span class="plain">, </span><span class="identifier">K_nil</span><span class="plain">)) </span><span class="identifier">l_present</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">choice_from</span><span class="plain">[</span><span class="identifier">k_present</span><span class="plain">][</span><span class="identifier">l_present</span><span class="plain">] == -1) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">k_present</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">choice_from</span><span class="plain">[1][</span><span class="identifier">l_present</span><span class="plain">] &gt;= </span><span class="constant">0</span><span class="plain">)) </span><span class="identifier">k_present</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">l_present</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">choice_from</span><span class="plain">[</span><span class="identifier">k_present</span><span class="plain">][1] &gt;= </span><span class="constant">0</span><span class="plain">)) </span><span class="identifier">l_present</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_present</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">l_present</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">choice_from</span><span class="plain">[1][1] &gt;= </span><span class="constant">0</span><span class="plain">)) {</span>
<span class="identifier">k_present</span><span class="plain">++; </span><span class="identifier">l_present</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">from</span><span class="plain"> = </span><span class="identifier">choice_from</span><span class="plain">[</span><span class="identifier">k_present</span><span class="plain">][</span><span class="identifier">l_present</span><span class="plain">];</span>
<span class="identifier">to</span><span class="plain"> = </span><span class="identifier">choice_to</span><span class="plain">[</span><span class="identifier">k_present</span><span class="plain">][</span><span class="identifier">l_present</span><span class="plain">];</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">from</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) || (</span><span class="identifier">from</span><span class="plain"> &gt;= </span><span class="identifier">full_length</span><span class="plain">) || (</span><span class="identifier">to</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) || (</span><span class="identifier">to</span><span class="plain"> &gt;= </span><span class="identifier">full_length</span><span class="plain">) || (</span><span class="identifier">to</span><span class="plain">&lt;</span><span class="identifier">from</span><span class="plain">)) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%W: %d, %d, %d\n"</span><span class="plain">, </span><span class="identifier">KW</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">, </span><span class="identifier">full_length</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"constructor form choice failed"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP24_3">&#167;24.3</a>.</p>
<p class="inwebparagraph"><a id="SP24_3_2_1"></a><b>&#167;24.3.2.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Determine the possible forms for writing this constructor</span> <span class="cwebmacronumber">24.3.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">;</span>
<span class="identifier">choice_from</span><span class="plain">[0][0] = -1; </span><span class="identifier">choice_from</span><span class="plain">[0][1] = -1;</span>
<span class="identifier">choice_from</span><span class="plain">[1][0] = -1; </span><span class="identifier">choice_from</span><span class="plain">[1][1] = -1;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0, </span><span class="identifier">from</span><span class="plain"> = -1; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">full_length</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain"> == -1) { </span><span class="identifier">from</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">; </span><span class="identifier">k_present</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">l_present</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Lexer::word</span><span class="plain">(</span><span class="identifier">k1</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">) == </span><span class="identifier">CAPITAL_K_V</span><span class="plain">) </span><span class="identifier">k_present</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Lexer::word</span><span class="plain">(</span><span class="identifier">k1</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">) == </span><span class="identifier">CAPITAL_L_V</span><span class="plain">) </span><span class="identifier">l_present</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Lexer::word</span><span class="plain">(</span><span class="identifier">k1</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">) == </span><span class="identifier">STROKE_V</span><span class="plain">) </span>&lt;<span class="cwebmacro">End this constructor possibility</span> <span class="cwebmacronumber">24.3.2.1.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">End this constructor possibility</span> <span class="cwebmacronumber">24.3.2.1.1</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP24_3_2">&#167;24.3.2</a>.</p>
<p class="inwebparagraph"><a id="SP24_3_2_1_1"></a><b>&#167;24.3.2.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">End this constructor possibility</span> <span class="cwebmacronumber">24.3.2.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">choice_from</span><span class="plain">[</span><span class="identifier">k_present</span><span class="plain">][</span><span class="identifier">l_present</span><span class="plain">] = </span><span class="identifier">from</span><span class="plain">;</span>
<span class="identifier">choice_to</span><span class="plain">[</span><span class="identifier">k_present</span><span class="plain">][</span><span class="identifier">l_present</span><span class="plain">] = </span><span class="identifier">i</span><span class="plain">-1;</span>
<span class="identifier">from</span><span class="plain"> = -1;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP24_3_2_1">&#167;24.3.2.1</a> (twice).</p>
<p class="inwebparagraph"><a id="SP24_3_3"></a><b>&#167;24.3.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Actually write out the chosen form of the constructor</span> <span class="cwebmacronumber">24.3.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<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">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;=</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> &gt; </span><span class="identifier">from</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" "</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Lexer::word</span><span class="plain">(</span><span class="identifier">k1</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">) == </span><span class="identifier">CAPITAL_K_V</span><span class="plain">) </span><span class="functiontext">Kinds::Textual::desc_base</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">con</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">first_base</span><span class="plain">, </span><span class="identifier">substituting</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">Lexer::word</span><span class="plain">(</span><span class="identifier">k1</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">) == </span><span class="identifier">CAPITAL_L_V</span><span class="plain">) </span><span class="functiontext">Kinds::Textual::desc_base</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">con</span><span class="plain">, </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">second_base</span><span class="plain">, </span><span class="identifier">substituting</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%V"</span><span class="plain">, </span><span class="identifier">Lexer::word</span><span class="plain">(</span><span class="identifier">k1</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">));</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP24_3">&#167;24.3</a>.</p>
<p class="inwebparagraph"><a id="SP25"></a><b>&#167;25. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Textual::desc_base</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</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">int</span><span class="plain"> </span><span class="identifier">b</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">int</span><span class="plain"> </span><span class="identifier">substituting</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="identifier">WRITE</span><span class="plain">(</span><span class="string">"nothing"</span><span class="plain">); </span><span class="reserved">return</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">K_nil</span><span class="plain">) { </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"nothing"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pluralised</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">tupled</span><span class="plain"> = </span><span class="functiontext">Kinds::Constructors::tupling</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">, </span><span class="identifier">b</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">bracketed</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">tupled</span><span class="plain"> &gt; </span><span class="constant">1</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) == </span><span class="identifier">CON_TUPLE_ENTRY</span><span class="plain">)) {</span>
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">first_base</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">second_base</span><span class="plain"> = </span><span class="identifier">NULL</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">first_base</span><span class="plain">, &amp;</span><span class="identifier">second_base</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">second_base</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">second_base</span><span class="plain">) == </span><span class="identifier">CON_TUPLE_ENTRY</span><span class="plain">)) </span><span class="identifier">bracketed</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">b</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">) &amp;&amp; (</span><span class="identifier">con</span><span class="plain"> == </span><span class="identifier">CON_phrase</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) == </span><span class="identifier">CON_phrase</span><span class="plain">)) </span><span class="identifier">bracketed</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="identifier">bracketed</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"("</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">tupled</span><span class="plain"> &gt; </span><span class="constant">1</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="identifier">pluralised</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="functiontext">Kinds::Textual::write_inner</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">pluralised</span><span class="plain">, </span><span class="identifier">substituting</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">bracketed</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">")"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Textual::desc_base is used in <a href="#SP24_3_3">&#167;24.3.3</a>.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="2-uk.html">Back to 'Using Kinds'</a></li><li><a href="2-dmn.html">Continue with 'Dimensions'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>