1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/kinds-module/2-ki.html
2020-03-22 10:50:19 +00:00

1486 lines
166 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>2/kc2</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</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/ki' 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>Kind Interpreter</b></li></ul><p class="purpose">To read in details of the built-in kinds from template files, setting them up ready for use.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP12">&#167;12. Errors and limitations</a></li><li><a href="#SP13">&#167;13. Setting up the interpreter</a></li><li><a href="#SP14">&#167;14. The kind command despatcher</a></li><li><a href="#SP15">&#167;15. Parsing single kind commands</a></li><li><a href="#SP16">&#167;16. Source text templates</a></li><li><a href="#SP22">&#167;22. Type macros</a></li><li><a href="#SP25">&#167;25. The kind text archiver</a></li><li><a href="#SP27">&#167;27. Error messages</a></li><li><a href="#SP28">&#167;28. Applying kind commands</a></li><li><a href="#SP29">&#167;29. Completing a batch</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>Everyone loves a mini-language, so here is one. At the top level:
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(a) Lines consisting of white space or whose first non-white space character is
<code class="display"><span class="extract">!</span></code> are ignored as comments.
</li></ul>
<ul class="items"><li>(b) A line ending with a colon <code class="display"><span class="extract">:</span></code> opens a new block. The text before the colon
is the title of the block, except that the first character indicates its type:
<ul class="items"><li>(1) An asterisk means that the block is a template definition: for instance,
<code class="display"><span class="extract">*PRINTING-ROUTINE:</span></code> says the block defines a template called <code class="display"><span class="extract">PRINTING-ROUTINE</span></code>.
A template consists of Inform 7 source text which extends as far as the next
<code class="display"><span class="extract">*END</span></code> line.
</li><li>(2) A sharp sign <code class="display"><span class="extract">#</span></code> means that the block is a macro definition. For
instance, <code class="display"><span class="extract">#UNIT:</span></code> says the block defines a template called <code class="display"><span class="extract">UNIT</span></code>. A macro
is just a sequence of lines holding kind commands which continues to
the beginning of the next block, or the end of the file.
</li><li>(3) And otherwise the block is a kind definition, but the optional opening
character <code class="display"><span class="extract">+</span></code> marks the kind as one which Inform requires the existence of.
Thus <code class="display"><span class="extract">+NUMBER_TY:</span></code>, since Inform will crash if the template doesn't set this
kind up, but <code class="display"><span class="extract">BOOJUMS_TY:</span></code> would validly declare a new kind called
<code class="display"><span class="extract">BOOJUMS_TY</span></code> which isn't special to any of Inform's internals. The <code class="display"><span class="extract">+</span></code> signs
are there as a help for hackers looking at the I6 template and wondering what
they can safely monkey with.
</li></ul>
</li></ul>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>The body of a kind definition is a sequence of one-line commands setting
what properties the kind has. These commands take the form of a name, a colon,
and an operand; for instance,
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">i6-printing-routine-actions:DA_Number</span>
</pre>
<p class="inwebparagraph">The operands have different types, and the possibilities are given here:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">NO_KCA</span><span class="plain"> -1 </span> <span class="comment">there's no operand</span>
<span class="definitionkeyword">define</span> <span class="constant">BOOLEAN_KCA</span><span class="plain"> 1 </span> <span class="comment">must be <code class="display"><span class="extract">yes</span></code> or <code class="display"><span class="extract">no</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">CCM_KCA</span><span class="plain"> 2 </span> <span class="comment">a constant compilation method</span>
<span class="definitionkeyword">define</span> <span class="constant">TEXT_KCA</span><span class="plain"> 3 </span> <span class="comment">any text (no quotation marks or other delimiters are used)</span>
<span class="definitionkeyword">define</span> <span class="constant">VOCABULARY_KCA</span><span class="plain"> 4 </span> <span class="comment">any single word</span>
<span class="definitionkeyword">define</span> <span class="constant">NUMERIC_KCA</span><span class="plain"> 5 </span> <span class="comment">any decimal number</span>
<span class="definitionkeyword">define</span> <span class="constant">CONSTRUCTOR_KCA</span><span class="plain"> 6 </span> <span class="comment">any valid kind number, such as "number"</span>
<span class="definitionkeyword">define</span> <span class="constant">TEMPLATE_KCA</span><span class="plain"> 7 </span> <span class="comment">the name of a template whose definition is given in the file</span>
<span class="definitionkeyword">define</span> <span class="constant">MACRO_KCA</span><span class="plain"> 8 </span> <span class="comment">the name of a macro whose definition is given in the file</span>
</pre>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>When processing a command, we parse it into one of the following structures:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">single_kind_command</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_command_definition</span><span class="plain"> *</span><span class="identifier">which_kind_command</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">boolean_argument</span><span class="plain">; </span> <span class="comment">where appropriate</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">numeric_argument</span><span class="plain">; </span> <span class="comment">where appropriate</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">textual_argument</span><span class="plain">; </span> <span class="comment">where appropriate</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ccm_argument</span><span class="plain">; </span> <span class="comment">where appropriate</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">word_assemblage</span><span class="plain"> </span><span class="identifier">vocabulary_argument</span><span class="plain">; </span> <span class="comment">where appropriate</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">constructor_argument</span><span class="plain">; </span> <span class="comment">where appropriate</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_template_definition</span><span class="plain"> *</span><span class="identifier">template_argument</span><span class="plain">; </span> <span class="comment">where appropriate</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_macro_definition</span><span class="plain"> *</span><span class="identifier">macro_argument</span><span class="plain">; </span> <span class="comment">where appropriate</span>
<span class="plain">} </span><span class="reserved">single_kind_command</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure single_kind_command is private to this section.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>A few of the commands connect pairs of kinds together: for instance,
when we write
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">cast:RULEBOOK_TY</span>
</pre>
<p class="inwebparagraph">in the definition block for <code class="display"><span class="extract">RULE_TY</span></code>, we're saying that every rulebook
can always be cast implicitly to a rule. There can be any number of these
in the definition block, so we need somewhere to store details, and the
following structure provides an entry in a linked list.
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_constructor_casting_rule</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">cast_from_kind_unparsed</span><span class="plain">; </span> <span class="comment">to the one which has the rule</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">cast_from_kind</span><span class="plain">; </span> <span class="comment">to the one which has the rule</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_constructor_casting_rule</span><span class="plain"> *</span><span class="identifier">next_casting_rule</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">kind_constructor_casting_rule</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure kind_constructor_casting_rule is accessed in 2/kc2 and here.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>And this is the analogous structure for giving I6 schemas to compare
data of two different kinds:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_constructor_comparison_schema</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">comparator_unparsed</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">comparator</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">comparison_schema</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_constructor_comparison_schema</span><span class="plain"> *</span><span class="identifier">next_comparison_schema</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">kind_constructor_comparison_schema</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure kind_constructor_comparison_schema is private to this section.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>And this is the analogous structure for giving I6 schemas to compare
data of two different kinds:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_constructor_instance</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">instance_of_this_unparsed</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">instance_of_this</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_constructor_instance</span><span class="plain"> *</span><span class="identifier">next_instance_rule</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">kind_constructor_instance</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure kind_constructor_instance is accessed in 2/kc2 and here.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>And, to cut to the chase, here is the complete table of commands:
</p>
<pre class="display">
<span class="reserved">kind_command_definition</span><span class="plain"> </span><span class="identifier">table_of_kind_commands</span><span class="plain">[] = {</span>
<span class="plain">{ </span><span class="string">"can-coincide-with-property"</span><span class="plain">, </span><span class="constant">can_coincide_with_property_KCC</span><span class="plain">, </span><span class="constant">BOOLEAN_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"can-exchange"</span><span class="plain">, </span><span class="constant">can_exchange_KCC</span><span class="plain">, </span><span class="constant">BOOLEAN_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"defined-in-source-text"</span><span class="plain">, </span><span class="constant">defined_in_source_text_KCC</span><span class="plain">, </span><span class="constant">BOOLEAN_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"has-i6-GPR"</span><span class="plain">, </span><span class="constant">has_i6_GPR_KCC</span><span class="plain">, </span><span class="constant">BOOLEAN_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"indexed-grey-if-empty"</span><span class="plain">, </span><span class="constant">indexed_grey_if_empty_KCC</span><span class="plain">, </span><span class="constant">BOOLEAN_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"is-incompletely-defined"</span><span class="plain">, </span><span class="constant">is_incompletely_defined_KCC</span><span class="plain">, </span><span class="constant">BOOLEAN_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"is-template-variable"</span><span class="plain">, </span><span class="constant">is_template_variable_KCC</span><span class="plain">, </span><span class="constant">BOOLEAN_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"multiple-block"</span><span class="plain">, </span><span class="constant">multiple_block_KCC</span><span class="plain">, </span><span class="constant">BOOLEAN_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"named-values-created-with-assertions"</span><span class="plain">,</span>
<span class="constant">named_values_created_with_assertions_KCC</span><span class="plain">, </span><span class="constant">BOOLEAN_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"constant-compilation-method"</span><span class="plain">, </span><span class="constant">constant_compilation_method_KCC</span><span class="plain">, </span><span class="constant">CCM_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"comparison-routine"</span><span class="plain">, </span><span class="constant">comparison_routine_KCC</span><span class="plain">, </span><span class="constant">TEXT_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"default-value"</span><span class="plain">, </span><span class="constant">default_value_KCC</span><span class="plain">, </span><span class="constant">TEXT_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"description"</span><span class="plain">, </span><span class="constant">description_KCC</span><span class="plain">, </span><span class="constant">TEXT_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"distinguisher"</span><span class="plain">, </span><span class="constant">distinguisher_KCC</span><span class="plain">, </span><span class="constant">TEXT_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"documentation-reference"</span><span class="plain">, </span><span class="constant">documentation_reference_KCC</span><span class="plain">, </span><span class="constant">TEXT_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"explicit-i6-GPR"</span><span class="plain">, </span><span class="constant">explicit_i6_GPR_KCC</span><span class="plain">, </span><span class="constant">TEXT_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"i6-printing-routine"</span><span class="plain">, </span><span class="constant">i6_printing_routine_KCC</span><span class="plain">, </span><span class="constant">TEXT_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"i6-printing-routine-actions"</span><span class="plain">, </span><span class="constant">i6_printing_routine_actions_KCC</span><span class="plain">, </span><span class="constant">TEXT_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"index-default-value"</span><span class="plain">, </span><span class="constant">index_default_value_KCC</span><span class="plain">, </span><span class="constant">TEXT_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"index-maximum-value"</span><span class="plain">, </span><span class="constant">index_maximum_value_KCC</span><span class="plain">, </span><span class="constant">TEXT_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"index-minimum-value"</span><span class="plain">, </span><span class="constant">index_minimum_value_KCC</span><span class="plain">, </span><span class="constant">TEXT_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"loop-domain-schema"</span><span class="plain">, </span><span class="constant">loop_domain_schema_KCC</span><span class="plain">, </span><span class="constant">TEXT_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"recognition-only-GPR"</span><span class="plain">, </span><span class="constant">recognition_only_GPR_KCC</span><span class="plain">, </span><span class="constant">TEXT_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"specification-text"</span><span class="plain">, </span><span class="constant">specification_text_KCC</span><span class="plain">, </span><span class="constant">TEXT_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"cast"</span><span class="plain">, </span><span class="constant">cast_KCC</span><span class="plain">, </span><span class="constant">CONSTRUCTOR_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"comparison-schema"</span><span class="plain">, </span><span class="constant">comparison_schema_KCC</span><span class="plain">, </span><span class="constant">CONSTRUCTOR_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"instance-of"</span><span class="plain">, </span><span class="constant">instance_of_KCC</span><span class="plain">, </span><span class="constant">CONSTRUCTOR_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"modifying-adjective"</span><span class="plain">, </span><span class="constant">modifying_adjective_KCC</span><span class="plain">, </span><span class="constant">VOCABULARY_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"plural"</span><span class="plain">, </span><span class="constant">plural_KCC</span><span class="plain">, </span><span class="constant">VOCABULARY_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"singular"</span><span class="plain">, </span><span class="constant">singular_KCC</span><span class="plain">, </span><span class="constant">VOCABULARY_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"constructor-arity"</span><span class="plain">, </span><span class="constant">constructor_arity_KCC</span><span class="plain">, </span><span class="constant">TEXT_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"group"</span><span class="plain">, </span><span class="constant">group_KCC</span><span class="plain">, </span><span class="constant">NUMERIC_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"heap-size-estimate"</span><span class="plain">, </span><span class="constant">heap_size_estimate_KCC</span><span class="plain">, </span><span class="constant">NUMERIC_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"index-priority"</span><span class="plain">, </span><span class="constant">index_priority_KCC</span><span class="plain">, </span><span class="constant">NUMERIC_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"small-block-size"</span><span class="plain">, </span><span class="constant">small_block_size_KCC</span><span class="plain">, </span><span class="constant">NUMERIC_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"template-variable-number"</span><span class="plain">, </span><span class="constant">template_variable_number_KCC</span><span class="plain">, </span><span class="constant">NUMERIC_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"apply-template"</span><span class="plain">, </span><span class="constant">apply_template_KCC</span><span class="plain">, </span><span class="constant">TEMPLATE_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="string">"apply-macro"</span><span class="plain">, </span><span class="constant">apply_macro_KCC</span><span class="plain">, </span><span class="constant">MACRO_KCA</span><span class="plain"> },</span>
<span class="plain">{ </span><span class="identifier">NULL</span><span class="plain">, -1, </span><span class="constant">NO_KCA</span><span class="plain"> }</span>
<span class="plain">};</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>Where each legal command is defined with a block like so:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_command_definition</span><span class="plain"> {</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">text_of_command</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">opcode_number</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">operand_type</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">kind_command_definition</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure kind_command_definition is private to this section.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>Macros and templates have their definitions stored in structures thus:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_template_definition</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">template_name</span><span class="plain">; </span> <span class="comment">including the asterisk, e.g., <code class="display"><span class="extract">"*PRINTING-ROUTINE"</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">template_text</span><span class="plain">;</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">kind_template_definition</span><span class="plain">;</span>
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_macro_definition</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">kind_macro_name</span><span class="plain">; </span> <span class="comment">including the sharp, e.g., <code class="display"><span class="extract">"#UNIT"</span></code></span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">kind_macro_line_count</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">single_kind_command</span><span class="plain"> </span><span class="identifier">kind_macro_line</span><span class="plain">[</span><span class="constant">MAX_KIND_MACRO_LENGTH</span><span class="plain">];</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">kind_macro_definition</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure kind_template_definition is private to this section.</p>
<p class="endnote">The structure kind_macro_definition is private to this section.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>And this makes a note to insert the relevant chunk of I7 source text
later on. (We do this because kind definitions are read very early on
in Inform's run, whereas I7 source text can only be lexed later.)
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_template_obligation</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_template_definition</span><span class="plain"> *</span><span class="identifier">remembered_template</span><span class="plain">; </span> <span class="comment">I7 source to insert...</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">remembered_constructor</span><span class="plain">; </span> <span class="comment">...concerning this kind</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">kind_template_obligation</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure kind_template_obligation is private to this section.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. Errors and limitations. </b>In implementing the interpreter, we have to ask: who is it for? It occupies
a strange position in being not quite for end users &mdash; the average Inform
user will never know what the template is &mdash; and yet not quite for internal
use only, either. The main motivation for moving properties of kinds out of
Inform's program logic and into an external text file was to make it easier
to verify that they were correctly described; but it was certainly also
meant to give future Inform hackers &mdash; users who like to burrow into
internals &mdash; scope for play.
</p>
<p class="inwebparagraph">The I6 template files supplied with Inform's standard distribution are,
of course, correct. So how forgiving should we be, if errors are found in it?
(These must result from mistakes by hackers.) To what extent should we allow
arbitrarily complex constructions, as we would if it were a feature intended
for end users?
</p>
<p class="inwebparagraph">We strike a sort of middle position. Inform will probably not crash if an
incorrect kind command is supplied, but it is free to throw internal
errors or generate I6 code which fails to compile through I6.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_KIND_MACRO_LENGTH</span><span class="plain"> 20 </span> <span class="comment">maximum number of commands in any one macro</span>
</pre>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. Setting up the interpreter. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::start</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Interpreter::start appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. The kind command despatcher. </b>And this is where textual commands are received. (They come in from the
template interpreter.) Comments and blank lines have already been stripped out.
</p>
<p class="inwebparagraph">A template absorbs the raw text of its definition, and ends with <code class="display"><span class="extract">*END</span></code>;
whereas a macro absorbs the parsed form of its commands, and continues to
the next new heading. (Templates can't use the same end syntax because
they often need to contain I7 phrase definitions, where lines end with
colons.)
</p>
<pre class="display">
<span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">constructor_described</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::despatch_kind_command</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">command</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Interpreter::recording_a_kind_template</span><span class="plain">()) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"*END"</span><span class="plain">)) </span><span class="functiontext">Kinds::Interpreter::end_kind_template</span><span class="plain">();</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::record_into_kind_template</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::get_last_char</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">) == </span><span class="character">':'</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Interpreter::recording_a_kind_macro</span><span class="plain">()) </span><span class="functiontext">Kinds::Interpreter::end_kind_macro</span><span class="plain">();</span>
<span class="identifier">Str::delete_last_character</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">); </span> <span class="comment">remove the terminal colon</span>
&lt;<span class="cwebmacro">Deal with the heading at the top of a kind command block</span> <span class="cwebmacronumber">14.1</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">single_kind_command</span><span class="plain"> </span><span class="identifier">stc</span><span class="plain"> = </span><span class="functiontext">Kinds::Interpreter::parse_kind_command</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Interpreter::recording_a_kind_macro</span><span class="plain">()) </span><span class="functiontext">Kinds::Interpreter::record_into_kind_macro</span><span class="plain">(</span><span class="identifier">stc</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">constructor_described</span><span class="plain">) </span><span class="functiontext">Kinds::Interpreter::apply_kind_command</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">stc</span><span class="plain">, </span><span class="identifier">constructor_described</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"kind command describes unspecified kind"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Interpreter::despatch_kind_command appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP14_1"></a><b>&#167;14.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Deal with the heading at the top of a kind command block</span> <span class="cwebmacronumber">14.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::get_first_char</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">) == </span><span class="character">'#'</span><span class="plain">) </span><span class="functiontext">Kinds::Interpreter::begin_kind_macro</span><span class="plain">(</span><span class="identifier">command</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">Str::get_first_char</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">) == </span><span class="character">'*'</span><span class="plain">) </span><span class="functiontext">Kinds::Interpreter::begin_kind_template</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">);</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">command</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">should_know</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">Str::get_first_char</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">) == </span><span class="character">'+'</span><span class="plain">) { </span><span class="identifier">Str::delete_first_character</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">); </span><span class="identifier">should_know</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">do_know</span><span class="plain"> = </span><span class="functiontext">Kinds::known_name</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">do_know</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">should_know</span><span class="plain"> == </span><span class="identifier">TRUE</span><span class="plain">))</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"kind command describes kind with no known name"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">do_know</span><span class="plain"> == </span><span class="identifier">TRUE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">should_know</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">))</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"kind command describes already-known kind"</span><span class="plain">);</span>
<span class="identifier">constructor_described</span><span class="plain"> =</span>
<span class="functiontext">Kinds::Constructors::new</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="functiontext">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">), </span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">NEW_BASE_KIND_NOTIFY</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">constructor_described</span><span class="plain"> != </span><span class="identifier">CON_KIND_VARIABLE</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">constructor_described</span><span class="plain"> != </span><span class="identifier">CON_INTERMEDIATE</span><span class="plain">)) {</span>
<span class="identifier">NEW_BASE_KIND_NOTIFY</span><span class="plain">(</span>
<span class="functiontext">Kinds::base_construction</span><span class="plain">(</span><span class="identifier">constructor_described</span><span class="plain">), </span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">EMPTY_WORDING</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">name</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">&#167;14</a>.</p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. Parsing single kind commands. </b>Each command is read in as text, parsed and stored into a modest structure.
</p>
<pre class="display">
<span class="reserved">single_kind_command</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::parse_kind_command</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">whole_command</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">);</span>
<span class="reserved">single_kind_command</span><span class="plain"> </span><span class="identifier">stc</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Parse line into command and argument, divided by a colon</span> <span class="cwebmacronumber">15.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Initialise the STC to a blank command</span> <span class="cwebmacronumber">15.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Identify the command being used</span> <span class="cwebmacronumber">15.3</span>&gt;<span class="plain">;</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.which_kind_command</span><span class="plain">-</span><span class="element">&gt;operand_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">BOOLEAN_KCA</span><span class="plain">: </span>&lt;<span class="cwebmacro">Parse a boolean argument for a kind command</span> <span class="cwebmacronumber">15.4</span>&gt;<span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CCM_KCA</span><span class="plain">: </span>&lt;<span class="cwebmacro">Parse a CCM argument for a kind command</span> <span class="cwebmacronumber">15.5</span>&gt;<span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CONSTRUCTOR_KCA</span><span class="plain">: </span>&lt;<span class="cwebmacro">Parse a constructor-name argument for a kind command</span> <span class="cwebmacronumber">15.9</span>&gt;<span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">MACRO_KCA</span><span class="plain">: </span>&lt;<span class="cwebmacro">Parse a macro name argument for a kind command</span> <span class="cwebmacronumber">15.11</span>&gt;<span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">NUMERIC_KCA</span><span class="plain">: </span>&lt;<span class="cwebmacro">Parse a numeric argument for a kind command</span> <span class="cwebmacronumber">15.8</span>&gt;<span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">TEMPLATE_KCA</span><span class="plain">: </span>&lt;<span class="cwebmacro">Parse a template name argument for a kind command</span> <span class="cwebmacronumber">15.10</span>&gt;<span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">TEXT_KCA</span><span class="plain">: </span>&lt;<span class="cwebmacro">Parse a textual argument for a kind command</span> <span class="cwebmacronumber">15.6</span>&gt;<span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">VOCABULARY_KCA</span><span class="plain">: </span>&lt;<span class="cwebmacro">Parse a vocabulary argument for a kind command</span> <span class="cwebmacronumber">15.7</span>&gt;<span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">stc</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Interpreter::parse_kind_command is used in <a href="#SP14">&#167;14</a>.</p>
<p class="inwebparagraph"><a id="SP15_1"></a><b>&#167;15.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Initialise the STC to a blank command</span> <span class="cwebmacronumber">15.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">stc</span><span class="element">.which_kind_command</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">stc</span><span class="element">.boolean_argument</span><span class="plain"> = </span><span class="identifier">NOT_APPLICABLE</span><span class="plain">;</span>
<span class="identifier">stc</span><span class="element">.numeric_argument</span><span class="plain"> = 0;</span>
<span class="identifier">stc</span><span class="element">.textual_argument</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="identifier">stc</span><span class="element">.ccm_argument</span><span class="plain"> = -1;</span>
<span class="identifier">stc</span><span class="element">.vocabulary_argument</span><span class="plain"> = </span><span class="identifier">WordAssemblages::lit_0</span><span class="plain">();</span>
<span class="identifier">stc</span><span class="element">.constructor_argument</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="identifier">stc</span><span class="element">.macro_argument</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">stc</span><span class="element">.template_argument</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_2"></a><b>&#167;15.2. </b>Spaces and tabs after the colon are skipped; so a textual argument cannot
begin with those characters, but that doesn't matter for the things we need.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Parse line into command and argument, divided by a colon</span> <span class="cwebmacronumber">15.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="identifier">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">whole_command</span><span class="plain">, </span><span class="identifier">L</span><span class="string">" *(%c+?) *: *(%c+?) *"</span><span class="plain">)) {</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0]);</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[1]);</span>
<span class="identifier">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="functiontext">Kinds::Interpreter::kind_command_error</span><span class="plain">(</span><span class="identifier">whole_command</span><span class="plain">, </span><span class="string">"kind command without argument"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_3"></a><b>&#167;15.3. </b>The following is clearly inefficient, but is not worth optimising. It makes
about 20 string comparisons per command, and there are about 600 commands in a
typical run of Inform, so the total cost is about 12,000 comparisons with
quite small strings as arguments &mdash; which is negligible for our purposes,
so we neglect it.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Identify the command being used</span> <span class="cwebmacronumber">15.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">table_of_kind_commands</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.text_of_command</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">Str::eq_narrow_string</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">, </span><span class="identifier">table_of_kind_commands</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.text_of_command</span><span class="plain">))</span>
<span class="identifier">stc</span><span class="element">.which_kind_command</span><span class="plain"> = &amp;(</span><span class="identifier">table_of_kind_commands</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">stc</span><span class="element">.which_kind_command</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="functiontext">Kinds::Interpreter::kind_command_error</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">, </span><span class="string">"no such kind command"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_4"></a><b>&#167;15.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Parse a boolean argument for a kind command</span> <span class="cwebmacronumber">15.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"yes"</span><span class="plain">)) </span><span class="identifier">stc</span><span class="element">.boolean_argument</span><span class="plain"> = </span><span class="identifier">TRUE</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">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"no"</span><span class="plain">)) </span><span class="identifier">stc</span><span class="element">.boolean_argument</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::kind_command_error</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">, </span><span class="string">"boolean kind command takes yes/no argument"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_5"></a><b>&#167;15.5. </b><code class="display">
&lt;<span class="cwebmacrodefn">Parse a CCM argument for a kind command</span> <span class="cwebmacronumber">15.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"none"</span><span class="plain">)) </span><span class="identifier">stc</span><span class="element">.ccm_argument</span><span class="plain"> = </span><span class="constant">NONE_CCM</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">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"literal"</span><span class="plain">)) </span><span class="identifier">stc</span><span class="element">.ccm_argument</span><span class="plain"> = </span><span class="constant">LITERAL_CCM</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">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"quantitative"</span><span class="plain">)) </span><span class="identifier">stc</span><span class="element">.ccm_argument</span><span class="plain"> = </span><span class="constant">NAMED_CONSTANT_CCM</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">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"special"</span><span class="plain">)) </span><span class="identifier">stc</span><span class="element">.ccm_argument</span><span class="plain"> = </span><span class="constant">SPECIAL_CCM</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::kind_command_error</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">, </span><span class="string">"kind command with unknown constant-compilation-method"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_6"></a><b>&#167;15.6. </b><code class="display">
&lt;<span class="cwebmacrodefn">Parse a textual argument for a kind command</span> <span class="cwebmacronumber">15.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.textual_argument</span><span class="plain">, </span><span class="identifier">argument</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_7"></a><b>&#167;15.7. </b><code class="display">
&lt;<span class="cwebmacrodefn">Parse a vocabulary argument for a kind command</span> <span class="cwebmacronumber">15.7</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">stc</span><span class="element">.vocabulary_argument</span><span class="plain"> = </span><span class="identifier">WordAssemblages::lit_0</span><span class="plain">();</span>
<span class="identifier">feed_t</span><span class="plain"> </span><span class="identifier">id</span><span class="plain"> = </span><span class="identifier">Feeds::begin</span><span class="plain">();</span>
<span class="identifier">Feeds::feed_stream</span><span class="plain">(</span><span class="identifier">argument</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">Feeds::end</span><span class="plain">(</span><span class="identifier">id</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">) &gt;= 30)</span>
<span class="functiontext">Kinds::Interpreter::kind_command_error</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">, </span><span class="string">"too many words in kind command"</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">stc</span><span class="element">.vocabulary_argument</span><span class="plain"> = </span><span class="identifier">WordAssemblages::from_wording</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_8"></a><b>&#167;15.8. </b><code class="display">
&lt;<span class="cwebmacrodefn">Parse a numeric argument for a kind command</span> <span class="cwebmacronumber">15.8</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">stc</span><span class="element">.numeric_argument</span><span class="plain"> = </span><span class="identifier">Str::atoi</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">, 0);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_9"></a><b>&#167;15.9. </b><code class="display">
&lt;<span class="cwebmacrodefn">Parse a constructor-name argument for a kind command</span> <span class="cwebmacronumber">15.9</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="identifier">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c*?)&gt;&gt;&gt;(%c+)"</span><span class="plain">)) {</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0]);</span>
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.textual_argument</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[1]);</span>
<span class="identifier">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">stc</span><span class="element">.constructor_argument</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_10"></a><b>&#167;15.10. </b><code class="display">
&lt;<span class="cwebmacrodefn">Parse a template name argument for a kind command</span> <span class="cwebmacronumber">15.10</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">stc</span><span class="element">.template_argument</span><span class="plain"> = </span><span class="functiontext">Kinds::Interpreter::parse_kind_template_name</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stc</span><span class="element">.template_argument</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="functiontext">Kinds::Interpreter::kind_command_error</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">, </span><span class="string">"unknown template name in kind command"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_11"></a><b>&#167;15.11. </b><code class="display">
&lt;<span class="cwebmacrodefn">Parse a macro name argument for a kind command</span> <span class="cwebmacronumber">15.11</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">stc</span><span class="element">.macro_argument</span><span class="plain"> = </span><span class="functiontext">Kinds::Interpreter::parse_kind_macro_name</span><span class="plain">(</span><span class="identifier">argument</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stc</span><span class="element">.macro_argument</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="functiontext">Kinds::Interpreter::kind_command_error</span><span class="plain">(</span><span class="identifier">command</span><span class="plain">, </span><span class="string">"unknown template name in kind command"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. Source text templates. </b>These are passages of I7 source text which can be inserted into the main
source text at the request of any kind. An example would be:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">*UNDERSTOOD-VARIABLE:</span>
<span class="plain">&lt;kind&gt; understood is a &lt;kind&gt; which varies.</span>
<span class="plain">*END</span>
</pre>
<p class="inwebparagraph">The template <code class="display"><span class="extract">*UNDERSTOOD-VARIABLE</span></code> contains only a single sentence of source
text, and the idea is to make a new global variable associated with a given
kind. Note that the text is not quite literal, because it can contain
wildcards like <code class="display"><span class="extract">&lt;kind&gt;</span></code>, which expands to the name of the kind of value in
question: for instance, we might get
</p>
<blockquote>
<p>number understood is a number which varies.</p>
</blockquote>
<p class="inwebparagraph">There are a few limitations on what template text can include. Firstly,
nothing with angle brackets in, except where a wildcard appears. Secondly,
each sentence must end at the end of a line, and similarly the colon for
any rule or other definition. Thus this template would fail:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">*UNDERSTOOD-VARIABLE:</span>
<span class="plain">&lt;kind&gt; understood is a &lt;kind&gt; which</span>
<span class="plain">varies. To judge &lt;kind&gt;: say "I judge [&lt;kind&gt; understood]."</span>
<span class="plain">*END</span>
</pre>
<p class="inwebparagraph">because the first sentence ends in the middle of the second line, and the
colon dividing the phrase header from its definition is also mid-line. The
template must be reformatted thus to work:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">*UNDERSTOOD-VARIABLE:</span>
<span class="plain">&lt;kind&gt; understood is a &lt;kind&gt; which varies.</span>
<span class="plain">To judge &lt;kind&gt;:</span>
<span class="plain"> say "I judge [&lt;kind&gt; understood]."</span>
<span class="plain">*END</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. </b>So, to begin:
</p>
<pre class="display">
<span class="reserved">kind_template_definition</span><span class="plain"> *</span><span class="functiontext">Kinds::Interpreter::new_kind_template</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">) {</span>
<span class="reserved">kind_template_definition</span><span class="plain"> *</span><span class="identifier">ttd</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">kind_template_definition</span><span class="plain">);</span>
<span class="identifier">ttd</span><span class="plain">-</span><span class="element">&gt;template_name</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">ttd</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">kind_template_definition</span><span class="plain"> *</span><span class="functiontext">Kinds::Interpreter::parse_kind_template_name</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">) {</span>
<span class="reserved">kind_template_definition</span><span class="plain"> *</span><span class="identifier">ttd</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ttd</span><span class="plain">, </span><span class="reserved">kind_template_definition</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">ttd</span><span class="plain">-</span><span class="element">&gt;template_name</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">ttd</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Interpreter::new_kind_template is used in <a href="#SP18">&#167;18</a>.</p>
<p class="endnote">The function Kinds::Interpreter::parse_kind_template_name is used in <a href="#SP15_10">&#167;15.10</a>, <a href="#SP18">&#167;18</a>.</p>
<p class="inwebparagraph"><a id="SP18"></a><b>&#167;18. </b>Here is the code which records templates, reading them as one line of plain
text at a time. (In the above example, <code class="display"><span class="extract">Kinds::Interpreter::record_into_kind_template</span></code> would be
called just once, with the single source text line.)
</p>
<pre class="display">
<span class="reserved">kind_template_definition</span><span class="plain"> *</span><span class="identifier">current_kind_template</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span> <span class="comment">the one now being recorded</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::recording_a_kind_template</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_kind_template</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::begin_kind_template</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_kind_template</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"first stt still recording"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Interpreter::parse_kind_template_name</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">))</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"duplicate definition of source text template"</span><span class="plain">);</span>
<span class="identifier">current_kind_template</span><span class="plain"> = </span><span class="functiontext">Kinds::Interpreter::new_kind_template</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">);</span>
<span class="identifier">current_kind_template</span><span class="plain">-</span><span class="element">&gt;template_text</span><span class="plain"> = </span><span class="functiontext">Kinds::Interpreter::begin_recording_kind_text</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::record_into_kind_template</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">line</span><span class="plain">) {</span>
<span class="functiontext">Kinds::Interpreter::record_kind_text</span><span class="plain">(</span><span class="identifier">line</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::end_kind_template</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_kind_template</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"no stt currently recording"</span><span class="plain">);</span>
<span class="functiontext">Kinds::Interpreter::end_recording_kind_text</span><span class="plain">();</span>
<span class="identifier">current_kind_template</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Interpreter::recording_a_kind_template is used in <a href="#SP14">&#167;14</a>.</p>
<p class="endnote">The function Kinds::Interpreter::begin_kind_template is used in <a href="#SP14_1">&#167;14.1</a>.</p>
<p class="endnote">The function Kinds::Interpreter::record_into_kind_template is used in <a href="#SP14">&#167;14</a>.</p>
<p class="endnote">The function Kinds::Interpreter::end_kind_template is used in <a href="#SP14">&#167;14</a>.</p>
<p class="inwebparagraph"><a id="SP19"></a><b>&#167;19. </b>So much for recording a template. To "play back", we need to take its text
and squeeze it into the main source text, but there's a timing issue: when
we read kind commands it is very early in Inform's run, and the lexer may not
even have started yet. So we simply remember our intention to insert the text:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">era_of_kind_template_transcription</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::remember_to_transcribe_spec_template</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">kind_template_definition</span><span class="plain"> *</span><span class="identifier">ttd</span><span class="plain">, </span><span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">era_of_kind_template_transcription</span><span class="plain">) {</span>
<span class="functiontext">Kinds::Interpreter::transcribe_kind_template</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">ttd</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">kind_template_obligation</span><span class="plain"> *</span><span class="identifier">tto</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">kind_template_obligation</span><span class="plain">);</span>
<span class="identifier">tto</span><span class="plain">-</span><span class="element">&gt;remembered_template</span><span class="plain"> = </span><span class="identifier">ttd</span><span class="plain">;</span>
<span class="identifier">tto</span><span class="plain">-</span><span class="element">&gt;remembered_constructor</span><span class="plain"> = </span><span class="identifier">C</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Interpreter::remember_to_transcribe_spec_template is used in <a href="#SP28_1">&#167;28.1</a>.</p>
<p class="inwebparagraph"><a id="SP20"></a><b>&#167;20. </b>...until now, when it's later on and the source text does indeed exist.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::include_templates_for_kinds</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">) {</span>
<span class="identifier">era_of_kind_template_transcription</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">kind_template_obligation</span><span class="plain"> *</span><span class="identifier">tto</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">tto</span><span class="plain">, </span><span class="reserved">kind_template_obligation</span><span class="plain">)</span>
<span class="functiontext">Kinds::Interpreter::transcribe_kind_template</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">,</span>
<span class="identifier">tto</span><span class="plain">-</span><span class="element">&gt;remembered_template</span><span class="plain">, </span><span class="identifier">tto</span><span class="plain">-</span><span class="element">&gt;remembered_constructor</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::transcribe_kind_template</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">,</span>
<span class="reserved">kind_template_definition</span><span class="plain"> *</span><span class="identifier">ttd</span><span class="plain">, </span><span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">con</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ttd</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to transcribe missing source text template"</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Plugins::Manage::plugged_in</span><span class="plain">(</span><span class="identifier">parsing_plugin</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">ttd</span><span class="plain">-</span><span class="element">&gt;template_name</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"*UNDERSTOOD-VARIABLE"</span><span class="plain">)))</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">ttd</span><span class="plain">-</span><span class="element">&gt;template_text</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = 0;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</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">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == </span><span class="character">'\</span><span class="plain">n</span><span class="character">'</span><span class="plain">) || (</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == </span><span class="character">' '</span><span class="plain">)) { </span><span class="identifier">i</span><span class="plain">++; </span><span class="reserved">continue</span><span class="plain">; }</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">template_line_buffer</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">terminator</span><span class="plain"> = 0;</span>
&lt;<span class="cwebmacro">Transcribe one line of the template into the line buffer</span> <span class="cwebmacronumber">20.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">template_line_buffer</span><span class="plain">) &gt; 0) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">XW</span><span class="plain"> = </span><span class="identifier">Feeds::feed_stream</span><span class="plain">(</span><span class="identifier">template_line_buffer</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">terminator</span><span class="plain"> != 0) </span><span class="identifier">Sentences::make_node</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">XW</span><span class="plain">, </span><span class="identifier">terminator</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">template_line_buffer</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="identifier">Sentences::Rearrangement::further_material</span><span class="plain">();</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Interpreter::include_templates_for_kinds appears nowhere else.</p>
<p class="endnote">The function Kinds::Interpreter::transcribe_kind_template is used in <a href="#SP19">&#167;19</a>.</p>
<p class="inwebparagraph"><a id="SP20_1"></a><b>&#167;20.1. </b>Inside template text, anything in angle brackets &lt;...&gt; is a wildcard.
These cannot be nested and cannot include newlines. All other material is
copied verbatim into the line buffer.
</p>
<p class="inwebparagraph">The only sentence terminators we recognise are full stop and colon; in
particular we wouldn't recognise a stop inside quoted matter. This does
not matter, since such things never come into kind definitions.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Transcribe one line of the template into the line buffer</span> <span class="cwebmacronumber">20.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) != 0) &amp;&amp; (</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) != </span><span class="character">'\</span><span class="plain">n</span><span class="character">'</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == </span><span class="character">'&lt;'</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">template_wildcard_buffer</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain">++;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) != 0) &amp;&amp; (</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) != </span><span class="character">'\</span><span class="plain">n</span><span class="character">'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) != </span><span class="character">'&gt;'</span><span class="plain">))</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">template_wildcard_buffer</span><span class="plain">, </span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">++));</span>
<span class="identifier">i</span><span class="plain">++;</span>
&lt;<span class="cwebmacro">Transcribe the template wildcard</span> <span class="cwebmacronumber">20.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">template_wildcard_buffer</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">template_line_buffer</span><span class="plain">, </span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">++));</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::get_last_char</span><span class="plain">(</span><span class="identifier">template_line_buffer</span><span class="plain">) == </span><span class="character">'.'</span><span class="plain">) {</span>
<span class="identifier">Str::delete_last_character</span><span class="plain">(</span><span class="identifier">template_line_buffer</span><span class="plain">); </span><span class="identifier">terminator</span><span class="plain"> = </span><span class="character">'.'</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::get_last_char</span><span class="plain">(</span><span class="identifier">template_line_buffer</span><span class="plain">) == </span><span class="character">':'</span><span class="plain">) {</span>
<span class="identifier">Str::delete_last_character</span><span class="plain">(</span><span class="identifier">template_line_buffer</span><span class="plain">); </span><span class="identifier">terminator</span><span class="plain"> = </span><span class="character">':'</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP20">&#167;20</a>.</p>
<p class="inwebparagraph"><a id="SP20_1_1"></a><b>&#167;20.1.1. </b>Only five wildcards are recognised:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Transcribe the template wildcard</span> <span class="cwebmacronumber">20.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">template_wildcard_buffer</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"kind"</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Transcribe the kind's name</span> <span class="cwebmacronumber">20.1.1.1</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">template_wildcard_buffer</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"lower-case-kind"</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Transcribe the kind's name in lower case</span> <span class="cwebmacronumber">20.1.1.2</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">template_wildcard_buffer</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"kind-weak-ID"</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Transcribe the kind's weak ID</span> <span class="cwebmacronumber">20.1.1.3</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">template_wildcard_buffer</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"printing-routine"</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Transcribe the kind's I6 printing routine</span> <span class="cwebmacronumber">20.1.1.4</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">template_wildcard_buffer</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"comparison-routine"</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Transcribe the kind's I6 comparison routine</span> <span class="cwebmacronumber">20.1.1.5</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"no such source text template wildcard"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP20_1">&#167;20.1</a>.</p>
<p class="inwebparagraph"><a id="SP20_1_1_1"></a><b>&#167;20.1.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Transcribe the kind's name</span> <span class="cwebmacronumber">20.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Kinds::Interpreter::transcribe_constructor_name</span><span class="plain">(</span><span class="identifier">template_line_buffer</span><span class="plain">, </span><span class="identifier">con</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP20_1_1">&#167;20.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP20_1_1_2"></a><b>&#167;20.1.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Transcribe the kind's name in lower case</span> <span class="cwebmacronumber">20.1.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Kinds::Interpreter::transcribe_constructor_name</span><span class="plain">(</span><span class="identifier">template_line_buffer</span><span class="plain">, </span><span class="identifier">con</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP20_1_1">&#167;20.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP20_1_1_3"></a><b>&#167;20.1.1.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Transcribe the kind's weak ID</span> <span class="cwebmacronumber">20.1.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">template_line_buffer</span><span class="plain">, </span><span class="string">"%d"</span><span class="plain">, </span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;weak_kind_ID</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP20_1_1">&#167;20.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP20_1_1_4"></a><b>&#167;20.1.1.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Transcribe the kind's I6 printing routine</span> <span class="cwebmacronumber">20.1.1.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">template_line_buffer</span><span class="plain">, </span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;dt_I6_identifier</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP20_1_1">&#167;20.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP20_1_1_5"></a><b>&#167;20.1.1.5. </b><code class="display">
&lt;<span class="cwebmacrodefn">Transcribe the kind's I6 comparison routine</span> <span class="cwebmacronumber">20.1.1.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">template_line_buffer</span><span class="plain">, </span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;comparison_routine</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP20_1_1">&#167;20.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP21"></a><b>&#167;21. </b>Where:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::transcribe_constructor_name</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">lower_case</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">EMPTY_WORDING</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="element">&gt;dt_tag</span><span class="plain">) </span><span class="identifier">W</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">FALSE</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="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; 0) {</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">W</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">w1</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">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="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">i</span><span class="plain"> &gt; 0) </span><span class="identifier">PUT</span><span class="plain">(</span><span class="character">' '</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">w1</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">STROKE_V</span><span class="plain">) </span><span class="reserved">break</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="identifier">WRITE</span><span class="plain">(</span><span class="string">"value"</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">ve</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lower_case</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">W</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">"%W"</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Interpreter::transcribe_constructor_name is used in <a href="#SP20_1_1_1">&#167;20.1.1.1</a>, <a href="#SP20_1_1_2">&#167;20.1.1.2</a>.</p>
<p class="inwebparagraph"><a id="SP22"></a><b>&#167;22. Type macros. </b>These are much simpler, and are just lists of kind commands grouped together
under names.
</p>
<pre class="display">
<span class="reserved">kind_macro_definition</span><span class="plain"> *</span><span class="identifier">current_kind_macro</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span> <span class="comment">the one now being recorded</span>
<span class="reserved">kind_macro_definition</span><span class="plain"> *</span><span class="functiontext">Kinds::Interpreter::new_kind_macro</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">) {</span>
<span class="reserved">kind_macro_definition</span><span class="plain"> *</span><span class="identifier">tmd</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">kind_macro_definition</span><span class="plain">);</span>
<span class="identifier">tmd</span><span class="plain">-</span><span class="element">&gt;kind_macro_line_count</span><span class="plain"> = 0;</span>
<span class="identifier">tmd</span><span class="plain">-</span><span class="element">&gt;kind_macro_name</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">tmd</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">kind_macro_definition</span><span class="plain"> *</span><span class="functiontext">Kinds::Interpreter::parse_kind_macro_name</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">) {</span>
<span class="reserved">kind_macro_definition</span><span class="plain"> *</span><span class="identifier">tmd</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">tmd</span><span class="plain">, </span><span class="reserved">kind_macro_definition</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">tmd</span><span class="plain">-</span><span class="element">&gt;kind_macro_name</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">tmd</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Interpreter::new_kind_macro is used in <a href="#SP23">&#167;23</a>.</p>
<p class="endnote">The function Kinds::Interpreter::parse_kind_macro_name is used in <a href="#SP15_11">&#167;15.11</a>, <a href="#SP23">&#167;23</a>, 2/kc2 (<a href="2-kc2.html#SP7_1">&#167;7.1</a>, <a href="2-kc2.html#SP11">&#167;11</a>, <a href="2-kc2.html#SP12">&#167;12</a>).</p>
<p class="inwebparagraph"><a id="SP23"></a><b>&#167;23. </b>And here once again is the code to record macros:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::recording_a_kind_macro</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_kind_macro</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::begin_kind_macro</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Interpreter::parse_kind_macro_name</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">))</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"duplicate definition of kind command macro"</span><span class="plain">);</span>
<span class="identifier">current_kind_macro</span><span class="plain"> = </span><span class="functiontext">Kinds::Interpreter::new_kind_macro</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::record_into_kind_macro</span><span class="plain">(</span><span class="reserved">single_kind_command</span><span class="plain"> </span><span class="identifier">stc</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_kind_macro</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"kind macro not being recorded"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_kind_macro</span><span class="plain">-</span><span class="element">&gt;kind_macro_line_count</span><span class="plain"> &gt;= </span><span class="constant">MAX_KIND_MACRO_LENGTH</span><span class="plain">)</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"kind macro contains too many lines"</span><span class="plain">);</span>
<span class="identifier">current_kind_macro</span><span class="plain">-</span><span class="element">&gt;kind_macro_line</span><span class="plain">[</span><span class="identifier">current_kind_macro</span><span class="plain">-</span><span class="element">&gt;kind_macro_line_count</span><span class="plain">++] = </span><span class="identifier">stc</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::end_kind_macro</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_kind_macro</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"ended kind macro outside one"</span><span class="plain">);</span>
<span class="identifier">current_kind_macro</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Interpreter::recording_a_kind_macro is used in <a href="#SP14">&#167;14</a>.</p>
<p class="endnote">The function Kinds::Interpreter::begin_kind_macro is used in <a href="#SP14_1">&#167;14.1</a>.</p>
<p class="endnote">The function Kinds::Interpreter::record_into_kind_macro is used in <a href="#SP14">&#167;14</a>.</p>
<p class="endnote">The function Kinds::Interpreter::end_kind_macro is used in <a href="#SP14">&#167;14</a>.</p>
<p class="inwebparagraph"><a id="SP24"></a><b>&#167;24. </b>Playing back is easier, since it's just a matter of despatching the stored
commands in sequence to the relevant kind.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::play_back_kind_macro</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">kind_macro_definition</span><span class="plain"> *</span><span class="identifier">macro</span><span class="plain">, </span><span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">con</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">macro</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"no such kind macro to play back"</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CREATIONS</span><span class="plain">, </span><span class="string">"Macro %S on %S (%d lines)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">macro</span><span class="plain">-</span><span class="element">&gt;kind_macro_name</span><span class="plain">, </span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;name_in_template_code</span><span class="plain">, </span><span class="identifier">macro</span><span class="plain">-</span><span class="element">&gt;kind_macro_line_count</span><span class="plain">);</span>
<span class="identifier">LOG_INDENT</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">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">macro</span><span class="plain">-</span><span class="element">&gt;kind_macro_line_count</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="functiontext">Kinds::Interpreter::apply_kind_command</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">macro</span><span class="plain">-</span><span class="element">&gt;kind_macro_line</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">con</span><span class="plain">);</span>
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CREATIONS</span><span class="plain">, </span><span class="string">"Macro %S ended\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">macro</span><span class="plain">-</span><span class="element">&gt;kind_macro_name</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Interpreter::play_back_kind_macro is used in <a href="#SP28_1">&#167;28.1</a>, 2/kc2 (<a href="2-kc2.html#SP7_1">&#167;7.1</a>, <a href="2-kc2.html#SP11">&#167;11</a>, <a href="2-kc2.html#SP12">&#167;12</a>).</p>
<p class="inwebparagraph"><a id="SP25"></a><b>&#167;25. The kind text archiver. </b>Large chunks of the text in the template will need to exist permanently in
memory, and we go into recording mode to accept a series of them,
concatenated with newlines dividing them, in a text stream.
</p>
<pre class="display">
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">kind_recording</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP26"></a><b>&#167;26. </b>And here is recording mode:
</p>
<pre class="display">
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="functiontext">Kinds::Interpreter::begin_recording_kind_text</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">kind_recording</span><span class="plain"> = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">kind_recording</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::record_kind_text</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">line</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kind_recording</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"can't record outside recording"</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">kind_recording</span><span class="plain">, </span><span class="string">"%S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">line</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::end_recording_kind_text</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">kind_recording</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Interpreter::begin_recording_kind_text is used in <a href="#SP18">&#167;18</a>.</p>
<p class="endnote">The function Kinds::Interpreter::record_kind_text is used in <a href="#SP18">&#167;18</a>.</p>
<p class="endnote">The function Kinds::Interpreter::end_recording_kind_text is used in <a href="#SP18">&#167;18</a>.</p>
<p class="inwebparagraph"><a id="SP27"></a><b>&#167;27. Error messages. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::kind_command_error</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">command</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">error</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Kind command error found at: %S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">command</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="identifier">error</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Interpreter::kind_command_error is used in <a href="#SP15_2">&#167;15.2</a>, <a href="#SP15_3">&#167;15.3</a>, <a href="#SP15_4">&#167;15.4</a>, <a href="#SP15_5">&#167;15.5</a>, <a href="#SP15_7">&#167;15.7</a>, <a href="#SP15_10">&#167;15.10</a>, <a href="#SP15_11">&#167;15.11</a>.</p>
<p class="inwebparagraph"><a id="SP28"></a><b>&#167;28. Applying kind commands. </b>We take a single kind command and apply it to a given kind.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">apply_macro_KCC</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">apply_template_KCC</span><span class="plain"> 2</span>
<span class="definitionkeyword">define</span> <span class="constant">can_coincide_with_property_KCC</span><span class="plain"> 5</span>
<span class="definitionkeyword">define</span> <span class="constant">can_exchange_KCC</span><span class="plain"> 6</span>
<span class="definitionkeyword">define</span> <span class="constant">cast_KCC</span><span class="plain"> 7</span>
<span class="definitionkeyword">define</span> <span class="constant">comparison_routine_KCC</span><span class="plain"> 8</span>
<span class="definitionkeyword">define</span> <span class="constant">comparison_schema_KCC</span><span class="plain"> 9</span>
<span class="definitionkeyword">define</span> <span class="constant">constant_compilation_method_KCC</span><span class="plain"> 10</span>
<span class="definitionkeyword">define</span> <span class="constant">constructor_arity_KCC</span><span class="plain"> 11</span>
<span class="definitionkeyword">define</span> <span class="constant">default_value_KCC</span><span class="plain"> 12</span>
<span class="definitionkeyword">define</span> <span class="constant">defined_in_source_text_KCC</span><span class="plain"> 13</span>
<span class="definitionkeyword">define</span> <span class="constant">description_KCC</span><span class="plain"> 14</span>
<span class="definitionkeyword">define</span> <span class="constant">distinguisher_KCC</span><span class="plain"> 15</span>
<span class="definitionkeyword">define</span> <span class="constant">documentation_reference_KCC</span><span class="plain"> 16</span>
<span class="definitionkeyword">define</span> <span class="constant">explicit_i6_GPR_KCC</span><span class="plain"> 17</span>
<span class="definitionkeyword">define</span> <span class="constant">group_KCC</span><span class="plain"> 18</span>
<span class="definitionkeyword">define</span> <span class="constant">has_i6_GPR_KCC</span><span class="plain"> 19</span>
<span class="definitionkeyword">define</span> <span class="constant">heap_size_estimate_KCC</span><span class="plain"> 20</span>
<span class="definitionkeyword">define</span> <span class="constant">i6_printing_routine_actions_KCC</span><span class="plain"> 21</span>
<span class="definitionkeyword">define</span> <span class="constant">i6_printing_routine_KCC</span><span class="plain"> 22</span>
<span class="definitionkeyword">define</span> <span class="constant">index_default_value_KCC</span><span class="plain"> 23</span>
<span class="definitionkeyword">define</span> <span class="constant">index_maximum_value_KCC</span><span class="plain"> 24</span>
<span class="definitionkeyword">define</span> <span class="constant">index_minimum_value_KCC</span><span class="plain"> 25</span>
<span class="definitionkeyword">define</span> <span class="constant">indexed_grey_if_empty_KCC</span><span class="plain"> 26</span>
<span class="definitionkeyword">define</span> <span class="constant">index_priority_KCC</span><span class="plain"> 27</span>
<span class="definitionkeyword">define</span> <span class="constant">instance_of_KCC</span><span class="plain"> 28</span>
<span class="definitionkeyword">define</span> <span class="constant">is_incompletely_defined_KCC</span><span class="plain"> 29</span>
<span class="definitionkeyword">define</span> <span class="constant">is_template_variable_KCC</span><span class="plain"> 30</span>
<span class="definitionkeyword">define</span> <span class="constant">loop_domain_schema_KCC</span><span class="plain"> 31</span>
<span class="definitionkeyword">define</span> <span class="constant">modifying_adjective_KCC</span><span class="plain"> 32</span>
<span class="definitionkeyword">define</span> <span class="constant">multiple_block_KCC</span><span class="plain"> 33</span>
<span class="definitionkeyword">define</span> <span class="constant">named_values_created_with_assertions_KCC</span><span class="plain"> 34</span>
<span class="definitionkeyword">define</span> <span class="constant">plural_KCC</span><span class="plain"> 35</span>
<span class="definitionkeyword">define</span> <span class="constant">recognition_only_GPR_KCC</span><span class="plain"> 36</span>
<span class="definitionkeyword">define</span> <span class="constant">singular_KCC</span><span class="plain"> 37</span>
<span class="definitionkeyword">define</span> <span class="constant">specification_text_KCC</span><span class="plain"> 38</span>
<span class="definitionkeyword">define</span> <span class="constant">small_block_size_KCC</span><span class="plain"> 39</span>
<span class="definitionkeyword">define</span> <span class="constant">template_variable_number_KCC</span><span class="plain"> 40</span>
</pre>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::apply_kind_command</span><span class="plain">(</span><span class="identifier">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">single_kind_command</span><span class="plain"> </span><span class="identifier">stc</span><span class="plain">, </span><span class="reserved">kind_constructor</span><span class="plain"> *</span><span class="identifier">con</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stc</span><span class="element">.which_kind_command</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"null STC command"</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CREATIONS</span><span class="plain">, </span><span class="string">"apply: %s (%d/%d/%S/%S) to %d/%S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">stc</span><span class="element">.which_kind_command</span><span class="plain">-</span><span class="element">&gt;text_of_command</span><span class="plain">,</span>
<span class="identifier">stc</span><span class="element">.boolean_argument</span><span class="plain">, </span><span class="identifier">stc</span><span class="element">.numeric_argument</span><span class="plain">,</span>
<span class="identifier">stc</span><span class="element">.textual_argument</span><span class="plain">, </span><span class="identifier">stc</span><span class="element">.constructor_argument</span><span class="plain">,</span>
<span class="identifier">con</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;name_in_template_code</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">tcc</span><span class="plain"> = </span><span class="identifier">stc</span><span class="element">.which_kind_command</span><span class="plain">-</span><span class="element">&gt;opcode_number</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Apply kind macros or transcribe kind templates on request</span> <span class="cwebmacronumber">28.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Most kind commands simply set a field in the constructor structure</span> <span class="cwebmacronumber">28.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">A few kind commands contribute to linked lists in the constructor structure</span> <span class="cwebmacronumber">28.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">And the rest fill in fields in the constructor structure in miscellaneous other ways</span> <span class="cwebmacronumber">28.4</span>&gt;<span class="plain">;</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"unimplemented kind command"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Interpreter::apply_kind_command is used in <a href="#SP14">&#167;14</a>, <a href="#SP24">&#167;24</a>.</p>
<p class="inwebparagraph"><a id="SP28_1"></a><b>&#167;28.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Apply kind macros or transcribe kind templates on request</span> <span class="cwebmacronumber">28.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">tcc</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">apply_template_KCC</span><span class="plain">:</span>
<span class="functiontext">Kinds::Interpreter::remember_to_transcribe_spec_template</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">stc</span><span class="element">.template_argument</span><span class="plain">, </span><span class="identifier">con</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">apply_macro_KCC</span><span class="plain">:</span>
<span class="functiontext">Kinds::Interpreter::play_back_kind_macro</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">stc</span><span class="element">.macro_argument</span><span class="plain">, </span><span class="identifier">con</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP28">&#167;28</a>.</p>
<p class="inwebparagraph"><a id="SP28_2"></a><b>&#167;28.2. </b></p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">SET_BOOLEAN_FIELD</span><span class="plain">(</span><span class="identifier">field</span><span class="plain">) </span><span class="reserved">case</span><span class="plain"> </span><span class="identifier">field</span><span class="plain">##</span><span class="identifier">_KCC</span><span class="plain">: </span><span class="identifier">con</span><span class="plain">-&gt;</span><span class="identifier">field</span><span class="plain"> = </span><span class="identifier">stc</span><span class="element">.boolean_argument</span><span class="plain">; </span><span class="reserved">return</span><span class="plain">;</span>
<span class="definitionkeyword">define</span> <span class="identifier">SET_INTEGER_FIELD</span><span class="plain">(</span><span class="identifier">field</span><span class="plain">) </span><span class="reserved">case</span><span class="plain"> </span><span class="identifier">field</span><span class="plain">##</span><span class="identifier">_KCC</span><span class="plain">: </span><span class="identifier">con</span><span class="plain">-&gt;</span><span class="identifier">field</span><span class="plain"> = </span><span class="identifier">stc</span><span class="element">.numeric_argument</span><span class="plain">; </span><span class="reserved">return</span><span class="plain">;</span>
<span class="definitionkeyword">define</span> <span class="identifier">SET_TEXTUAL_FIELD</span><span class="plain">(</span><span class="identifier">field</span><span class="plain">) </span><span class="reserved">case</span><span class="plain"> </span><span class="identifier">field</span><span class="plain">##</span><span class="identifier">_KCC</span><span class="plain">: </span><span class="identifier">con</span><span class="plain">-&gt;</span><span class="identifier">field</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.textual_argument</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">;</span>
<span class="definitionkeyword">define</span> <span class="identifier">SET_CCM_FIELD</span><span class="plain">(</span><span class="identifier">field</span><span class="plain">) </span><span class="reserved">case</span><span class="plain"> </span><span class="identifier">field</span><span class="plain">##</span><span class="identifier">_KCC</span><span class="plain">: </span><span class="identifier">con</span><span class="plain">-&gt;</span><span class="identifier">field</span><span class="plain"> = </span><span class="identifier">stc</span><span class="element">.ccm_argument</span><span class="plain">; </span><span class="reserved">return</span><span class="plain">;</span>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Most kind commands simply set a field in the constructor structure</span> <span class="cwebmacronumber">28.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">tcc</span><span class="plain">) {</span>
<span class="identifier">SET_BOOLEAN_FIELD</span><span class="plain">(</span><span class="identifier">can_coincide_with_property</span><span class="plain">)</span>
<span class="identifier">SET_BOOLEAN_FIELD</span><span class="plain">(</span><span class="identifier">can_exchange</span><span class="plain">)</span>
<span class="identifier">SET_BOOLEAN_FIELD</span><span class="plain">(</span><span class="identifier">defined_in_source_text</span><span class="plain">)</span>
<span class="identifier">SET_BOOLEAN_FIELD</span><span class="plain">(</span><span class="identifier">has_i6_GPR</span><span class="plain">)</span>
<span class="identifier">SET_BOOLEAN_FIELD</span><span class="plain">(</span><span class="identifier">indexed_grey_if_empty</span><span class="plain">)</span>
<span class="identifier">SET_BOOLEAN_FIELD</span><span class="plain">(</span><span class="identifier">is_incompletely_defined</span><span class="plain">)</span>
<span class="identifier">SET_BOOLEAN_FIELD</span><span class="plain">(</span><span class="identifier">multiple_block</span><span class="plain">)</span>
<span class="identifier">SET_BOOLEAN_FIELD</span><span class="plain">(</span><span class="identifier">named_values_created_with_assertions</span><span class="plain">)</span>
<span class="identifier">SET_INTEGER_FIELD</span><span class="plain">(</span><span class="identifier">group</span><span class="plain">)</span>
<span class="identifier">SET_INTEGER_FIELD</span><span class="plain">(</span><span class="identifier">heap_size_estimate</span><span class="plain">)</span>
<span class="identifier">SET_INTEGER_FIELD</span><span class="plain">(</span><span class="identifier">index_priority</span><span class="plain">)</span>
<span class="identifier">SET_INTEGER_FIELD</span><span class="plain">(</span><span class="identifier">small_block_size</span><span class="plain">)</span>
<span class="identifier">SET_CCM_FIELD</span><span class="plain">(</span><span class="identifier">constant_compilation_method</span><span class="plain">)</span>
<span class="identifier">SET_TEXTUAL_FIELD</span><span class="plain">(</span><span class="identifier">default_value</span><span class="plain">)</span>
<span class="identifier">SET_TEXTUAL_FIELD</span><span class="plain">(</span><span class="identifier">distinguisher</span><span class="plain">)</span>
<span class="identifier">SET_TEXTUAL_FIELD</span><span class="plain">(</span><span class="identifier">documentation_reference</span><span class="plain">)</span>
<span class="identifier">SET_TEXTUAL_FIELD</span><span class="plain">(</span><span class="identifier">explicit_i6_GPR</span><span class="plain">)</span>
<span class="identifier">SET_TEXTUAL_FIELD</span><span class="plain">(</span><span class="identifier">index_default_value</span><span class="plain">)</span>
<span class="identifier">SET_TEXTUAL_FIELD</span><span class="plain">(</span><span class="identifier">index_maximum_value</span><span class="plain">)</span>
<span class="identifier">SET_TEXTUAL_FIELD</span><span class="plain">(</span><span class="identifier">index_minimum_value</span><span class="plain">)</span>
<span class="identifier">SET_TEXTUAL_FIELD</span><span class="plain">(</span><span class="identifier">loop_domain_schema</span><span class="plain">)</span>
<span class="identifier">SET_TEXTUAL_FIELD</span><span class="plain">(</span><span class="identifier">recognition_only_GPR</span><span class="plain">)</span>
<span class="identifier">SET_TEXTUAL_FIELD</span><span class="plain">(</span><span class="identifier">specification_text</span><span class="plain">)</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP28">&#167;28</a>.</p>
<p class="inwebparagraph"><a id="SP28_3"></a><b>&#167;28.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">A few kind commands contribute to linked lists in the constructor structure</span> <span class="cwebmacronumber">28.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tcc</span><span class="plain"> == </span><span class="constant">cast_KCC</span><span class="plain">) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.constructor_argument</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"SNIPPET_TY"</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Plugins::Manage::plugged_in</span><span class="plain">(</span><span class="identifier">parsing_plugin</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><span class="identifier">endif</span>
<span class="reserved">kind_constructor_casting_rule</span><span class="plain"> *</span><span class="identifier">dtcr</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">kind_constructor_casting_rule</span><span class="plain">);</span>
<span class="identifier">dtcr</span><span class="plain">-</span><span class="element">&gt;next_casting_rule</span><span class="plain"> = </span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;first_casting_rule</span><span class="plain">;</span>
<span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;first_casting_rule</span><span class="plain"> = </span><span class="identifier">dtcr</span><span class="plain">;</span>
<span class="identifier">dtcr</span><span class="plain">-</span><span class="element">&gt;cast_from_kind_unparsed</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.constructor_argument</span><span class="plain">);</span>
<span class="identifier">dtcr</span><span class="plain">-</span><span class="element">&gt;cast_from_kind</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="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tcc</span><span class="plain"> == </span><span class="constant">instance_of_KCC</span><span class="plain">) {</span>
<span class="reserved">kind_constructor_instance</span><span class="plain"> *</span><span class="identifier">dti</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">kind_constructor_instance</span><span class="plain">);</span>
<span class="identifier">dti</span><span class="plain">-</span><span class="element">&gt;next_instance_rule</span><span class="plain"> = </span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;first_instance_rule</span><span class="plain">;</span>
<span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;first_instance_rule</span><span class="plain"> = </span><span class="identifier">dti</span><span class="plain">;</span>
<span class="identifier">dti</span><span class="plain">-</span><span class="element">&gt;instance_of_this_unparsed</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.constructor_argument</span><span class="plain">);</span>
<span class="identifier">dti</span><span class="plain">-</span><span class="element">&gt;instance_of_this</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="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tcc</span><span class="plain"> == </span><span class="constant">comparison_schema_KCC</span><span class="plain">) {</span>
<span class="reserved">kind_constructor_comparison_schema</span><span class="plain"> *</span><span class="identifier">dtcs</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">kind_constructor_comparison_schema</span><span class="plain">);</span>
<span class="identifier">dtcs</span><span class="plain">-</span><span class="element">&gt;next_comparison_schema</span><span class="plain"> = </span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;first_comparison_schema</span><span class="plain">;</span>
<span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;first_comparison_schema</span><span class="plain"> = </span><span class="identifier">dtcs</span><span class="plain">;</span>
<span class="identifier">dtcs</span><span class="plain">-</span><span class="element">&gt;comparator_unparsed</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.constructor_argument</span><span class="plain">);</span>
<span class="identifier">dtcs</span><span class="plain">-</span><span class="element">&gt;comparator</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">dtcs</span><span class="plain">-</span><span class="element">&gt;comparison_schema</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.textual_argument</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="#SP28">&#167;28</a>.</p>
<p class="inwebparagraph"><a id="SP28_4"></a><b>&#167;28.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">And the rest fill in fields in the constructor structure in miscellaneous other ways</span> <span class="cwebmacronumber">28.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">tcc</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">constructor_arity_KCC</span><span class="plain">:</span>
&lt;<span class="cwebmacro">Parse the constructor arity text</span> <span class="cwebmacronumber">28.4.1</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">description_KCC</span><span class="plain">:</span>
<span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;constructor_description</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.textual_argument</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">comparison_routine_KCC</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.textual_argument</span><span class="plain">) &gt; 31) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"overlong I6 identifier"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;comparison_routine</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.textual_argument</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">i6_printing_routine_KCC</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.textual_argument</span><span class="plain">) &gt; 31) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"overlong I6 identifier"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;dt_I6_identifier</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.textual_argument</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">i6_printing_routine_actions_KCC</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.textual_argument</span><span class="plain">) &gt; 31) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"overlong I6 identifier"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;name_of_printing_rule_ACTIONS</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.textual_argument</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">singular_KCC</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="constant">plural_KCC</span><span class="plain">: {</span>
<span class="identifier">vocabulary_entry</span><span class="plain"> **</span><span class="identifier">array</span><span class="plain">; </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">length</span><span class="plain">;</span>
<span class="identifier">WordAssemblages::as_array</span><span class="plain">(&amp;(</span><span class="identifier">stc</span><span class="element">.vocabulary_argument</span><span class="plain">), &amp;</span><span class="identifier">array</span><span class="plain">, &amp;</span><span class="identifier">length</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">length</span><span class="plain"> == 1) {</span>
<span class="functiontext">Kinds::mark_vocabulary_as_kind</span><span class="plain">(</span><span class="identifier">array</span><span class="plain">[0], </span><span class="functiontext">Kinds::base_construction</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">));</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">length</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="identifier">Vocabulary::set_flags</span><span class="plain">(</span><span class="identifier">array</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="constant">KIND_SLOW_MC</span><span class="plain">);</span>
<span class="identifier">Preform::mark_vocabulary</span><span class="plain">(</span><span class="identifier">array</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="reserved">kind</span><span class="plain">&gt;);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;group</span><span class="plain"> != </span><span class="constant">PROPER_CONSTRUCTOR_GRP</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">WordAssemblages::hyphenated</span><span class="plain">(&amp;(</span><span class="identifier">stc</span><span class="element">.vocabulary_argument</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="functiontext">Kinds::mark_vocabulary_as_kind</span><span class="plain">(</span><span class="identifier">ve</span><span class="plain">, </span><span class="functiontext">Kinds::base_construction</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">feed_t</span><span class="plain"> </span><span class="identifier">id</span><span class="plain"> = </span><span class="identifier">Feeds::begin</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">i</span><span class="plain">=0; </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">Feeds::feed_text</span><span class="plain">(</span><span class="identifier">Vocabulary::get_exemplar</span><span class="plain">(</span><span class="identifier">array</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">FALSE</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">Feeds::end</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tcc</span><span class="plain"> == </span><span class="constant">singular_KCC</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ro</span><span class="plain"> = 0;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;group</span><span class="plain"> != </span><span class="constant">PROPER_CONSTRUCTOR_GRP</span><span class="plain">) </span><span class="identifier">ro</span><span class="plain"> = </span><span class="identifier">REGISTER_SINGULAR_NTOPT</span><span class="plain"> + </span><span class="identifier">REGISTER_PLURAL_NTOPT</span><span class="plain">;</span>
<span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain"> =</span>
<span class="identifier">Nouns::new_common_noun</span><span class="plain">(</span><span class="identifier">LW</span><span class="plain">, </span><span class="identifier">NEUTER_GENDER</span><span class="plain">, </span><span class="identifier">PARSE_EXACTLY_NTOPT</span><span class="plain"> + </span><span class="identifier">ro</span><span class="plain">,</span>
<span class="constant">KIND_SLOW_MC</span><span class="plain">, </span><span class="identifier">STORE_POINTER_kind_constructor</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">));</span>
<span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;dt_tag</span><span class="plain"> = </span><span class="identifier">nt</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">Nouns::set_plural_name</span><span class="plain">(</span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;dt_tag</span><span class="plain">, </span><span class="identifier">LW</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">modifying_adjective_KCC</span><span class="plain">:</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"the modifying-adjective syntax has been withdrawn"</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="#SP28">&#167;28</a>.</p>
<p class="inwebparagraph"><a id="SP28_4_1"></a><b>&#167;28.4.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Parse the constructor arity text</span> <span class="cwebmacronumber">28.4.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = 0;</span>
<span class="identifier">string_position</span><span class="plain"> </span><span class="identifier">pos</span><span class="plain"> = </span><span class="identifier">Str::start</span><span class="plain">(</span><span class="identifier">stc</span><span class="element">.textual_argument</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">TRUE</span><span class="plain">) {</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">Characters::is_space_or_tab</span><span class="plain">(</span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">))) </span><span class="identifier">pos</span><span class="plain"> = </span><span class="identifier">Str::forward</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">) == 0) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">) == </span><span class="character">','</span><span class="plain">) { </span><span class="identifier">c</span><span class="plain">++; </span><span class="identifier">pos</span><span class="plain"> = </span><span class="identifier">Str::forward</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">); </span><span class="reserved">continue</span><span class="plain">; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &gt;= 2) { </span><span class="identifier">c</span><span class="plain">=1; </span><span class="reserved">break</span><span class="plain">; }</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">wd</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> ((!</span><span class="identifier">Characters::is_space_or_tab</span><span class="plain">(</span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">))) &amp;&amp; (</span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">) != </span><span class="character">','</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">) != 0)) {</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">wd</span><span class="plain">, </span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">)); </span><span class="identifier">pos</span><span class="plain"> = </span><span class="identifier">Str::forward</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">wd</span><span class="plain">) &gt; 0) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">wd</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"covariant"</span><span class="plain">)) </span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;variance</span><span class="plain">[</span><span class="identifier">c</span><span class="plain">] = </span><span class="constant">COVARIANT</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">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">wd</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"contravariant"</span><span class="plain">)) </span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;variance</span><span class="plain">[</span><span class="identifier">c</span><span class="plain">] = </span><span class="constant">CONTRAVARIANT</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">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">wd</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"optional"</span><span class="plain">)) </span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;tupling</span><span class="plain">[</span><span class="identifier">c</span><span class="plain">] = </span><span class="constant">ALLOW_NOTHING_TUPLING</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">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">wd</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"list"</span><span class="plain">)) </span><span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;tupling</span><span class="plain">[</span><span class="identifier">c</span><span class="plain">] = </span><span class="constant">ARBITRARY_TUPLING</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Word: &lt;%S&gt;\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">wd</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"illegal constructor-arity keyword"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">wd</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">con</span><span class="plain">-</span><span class="element">&gt;constructor_arity</span><span class="plain"> = </span><span class="identifier">c</span><span class="plain">+1;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP28_4">&#167;28.4</a>.</p>
<p class="inwebparagraph"><a id="SP29"></a><b>&#167;29. Completing a batch. </b>At one time it was useful to do some mopping-up work after a round of kind
commands, so the following hook was devised; but at present it's not needed.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Interpreter::batch_done</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Kinds::Interpreter::batch_done appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP30"></a><b>&#167;30. </b>And that completes the kind interpreter.
</p>
<hr class="tocbar">
<ul class="toc"><li><a href="2-kc2.html">Back to 'Kind Constructors'</a></li><li><a href="2-uk.html">Continue with 'Using Kinds'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>