1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/core-module/19-tc.html
2020-04-07 01:06:09 +01:00

843 lines
99 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>18/lc</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../compiler.html"><b>compiler tools</b></a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul>
<h2>Compiler Webs</h2>
<ul>
<li><a href="../inbuild/index.html">inbuild</a></li>
<li><a href="../inform7/index.html">inform7</a></li>
<li><a href="../inter/index.html">inter</a></li>
</ul>
<h2>Inbuild Modules</h2>
<ul>
<li><a href="../inbuild-module/index.html">inbuild</a></li>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../syntax-module/index.html">syntax</a></li>
<li><a href="../html-module/index.html">html</a></li>
</ul>
<h2>Inform7 Modules</h2>
<ul>
<li><a href="../core-module/index.html">core</a></li>
<li><a href="../problems-module/index.html">problems</a></li>
<li><a href="../inflections-module/index.html">inflections</a></li>
<li><a href="../linguistics-module/index.html">linguistics</a></li>
<li><a href="../kinds-module/index.html">kinds</a></li>
<li><a href="../if-module/index.html">if</a></li>
<li><a href="../multimedia-module/index.html">multimedia</a></li>
<li><a href="../index-module/index.html">index</a></li>
</ul>
<h2>Inter Modules</h2>
<ul>
<li><a href="../inter-module/index.html">inter</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../codegen-module/index.html">codegen</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '19/tc' 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">core</a></li><li><a href="index.html#19">Chapter 19: Table Data</a></li><li><b>Table Columns</b></li></ul><p class="purpose">To manage the named columns which appear in tables.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP4">&#167;4. Managing columns</a></li><li><a href="#SP8">&#167;8. Run-time support</a></li><li><a href="#SP9">&#167;9. Discovering columns</a></li><li><a href="#SP14">&#167;14. Checking kind consistency</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>Tables are the most important data structure in Inform. They imitate
printed tables in books or scientific papers, and the data inside them is
arranged in columns, each of which is headed by a name.
</p>
<p class="inwebparagraph">Table columns are required to be consistently typed even across different
tables: if Table A and Table B each have a column called "topmost point",
then the contents must have a consistent kind in both tables. (This enables
the name alone to guarantee the kind, and also allows for the tables to be
linked, as in a relational database.)
</p>
<p class="inwebparagraph">The predicate calculus engine often finds conditions equivalent to "if A
is a C listed in T": it is efficient to rewrite this in a special predicate
listed-in-C(A, T), and to do this we need to have a binary
predicate associated with each possible table column C.
</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">table_column</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">; </span><span class="comment">name of column (without "entry" suffix)</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">kind_stored_in_column</span><span class="plain">; </span><span class="comment">what kind of value is stored in this column</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">table</span><span class="plain"> *</span><span class="identifier">table_from_which_kind_inferred</span><span class="plain">; </span><span class="comment">usually the earliest use</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">binary_predicate</span><span class="plain"> *</span><span class="identifier">listed_in_predicate</span><span class="plain">; </span><span class="comment">see above</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">table_column</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure table_column is accessed in 2/sq, 2/si, 5/ins, 5/nv, 8/ef, 9/ma, 9/pk, 11/sm, 14/lv, 14/ds2, 15/pr, 15/ep, 15/vp, 15/spr, 16/in, 16/cmw, 17/rs, 19/tb, 19/tod, 20/eq, 21/rl, 21/rl2, 21/fao, 21/rps, 21/sv, 21/ac, 22/pu, 22/dptd, 22/po, 22/pav, 25/cii, 26/uo, 26/ts and here.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>When a column appears in a particular table, this is recorded with the
following structure. Note that it's possible for a kind to be named explicitly,
as when a column has a heading like:
</p>
<blockquote>
<p>average population (a number)</p>
</blockquote>
<p class="inwebparagraph">The name "average population" identifies the TC, and "a number" will be
the explicit kind declaration. (This may or may not be consistent with other
uses of the same TC, so that's something we'll have to check on.)
</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">table_column_usage</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">table_column</span><span class="plain"> *</span><span class="identifier">column_identity</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">entries</span><span class="plain">; </span><span class="comment">initial contents of this column in the table</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">kind_declaration_text</span><span class="plain">; </span><span class="comment">if specified</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">actual_constant_entries</span><span class="plain">; </span><span class="comment">how many entries have explicitly been given</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">observed_constant_cell</span><span class="plain">; </span><span class="comment">first one spotted</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">kind_name_entries</span><span class="plain">; </span><span class="comment">how many entries read, say, "a rulebook"</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">observed_kind_cell</span><span class="plain">; </span><span class="comment">first one spotted</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">tcu_iname</span><span class="plain">; </span><span class="comment">for the array holding this at run-time</span>
<span class="plain">} </span><span class="reserved">table_column_usage</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure table_column_usage is accessed in 19/tb, 19/rsft, 19/tod and here.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Managing columns. </b>Columns are created with a name, which is assumed here to be not the name
of any existing column.
</p>
<pre class="display">
<span class="reserved">table_column</span><span class="plain"> *</span><span class="functiontext">Tables::Columns::new_table_column</span><span class="plain">(</span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">table_column</span><span class="plain"> *</span><span class="identifier">tc</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">table_column</span><span class="plain">);</span>
<span class="identifier">tc</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">tc</span><span class="plain">-&gt;</span><span class="element">kind_stored_in_column</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">tc</span><span class="plain">-&gt;</span><span class="element">table_from_which_kind_inferred</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">tc</span><span class="plain">-&gt;</span><span class="element">listed_in_predicate</span><span class="plain"> = </span><span class="functiontext">Tables::Relations::make_listed_in_predicate</span><span class="plain">(</span><span class="identifier">tc</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="comment">as always happens except when recovering from a problem</span>
<span class="identifier">tc</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain"> = </span><span class="identifier">Nouns::new_proper_noun</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">NEUTER_GENDER</span><span class="plain">,</span>
<span class="identifier">REGISTER_SINGULAR_NTOPT</span><span class="plain"> + </span><span class="identifier">PARSE_EXACTLY_NTOPT</span><span class="plain">,</span>
<span class="constant">TABLE_COLUMN_MC</span><span class="plain">, </span><span class="functiontext">Rvalues::from_table_column</span><span class="plain">(</span><span class="identifier">tc</span><span class="plain">));</span>
<span class="identifier">word_assemblage</span><span class="plain"> </span><span class="identifier">wa</span><span class="plain"> =</span>
<span class="identifier">Preform::Nonparsing::merge</span><span class="plain">(&lt;</span><span class="reserved">table</span><span class="plain">-</span><span class="identifier">column</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">-</span><span class="identifier">construction</span><span class="plain">&gt;, </span><span class="constant">0</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>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">AW</span><span class="plain"> = </span><span class="identifier">WordAssemblages::to_wording</span><span class="plain">(&amp;</span><span class="identifier">wa</span><span class="plain">);</span>
<span class="identifier">Nouns::new_proper_noun</span><span class="plain">(</span><span class="identifier">AW</span><span class="plain">, </span><span class="identifier">NEUTER_GENDER</span><span class="plain">,</span>
<span class="identifier">REGISTER_SINGULAR_NTOPT</span><span class="plain"> + </span><span class="identifier">PARSE_EXACTLY_NTOPT</span><span class="plain">,</span>
<span class="constant">TABLE_COLUMN_MC</span><span class="plain">, </span><span class="functiontext">Rvalues::from_table_column</span><span class="plain">(</span><span class="identifier">tc</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">tc</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Tables::Columns::new_table_column is used in <a href="#SP13_2">&#167;13.2</a>.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Tables::Columns::log</span><span class="plain">(</span><span class="reserved">table_column</span><span class="plain"> *</span><span class="identifier">tc</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"'%W'/"</span><span class="plain">, </span><span class="identifier">Nouns::nominative</span><span class="plain">(</span><span class="identifier">tc</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tc</span><span class="plain">-&gt;</span><span class="element">kind_stored_in_column</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"unknown"</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">"$u"</span><span class="plain">, </span><span class="identifier">tc</span><span class="plain">-&gt;</span><span class="element">kind_stored_in_column</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Tables::Columns::log is used in 1/cm (<a href="1-cm.html#SP5">&#167;5</a>, <a href="1-cm.html#SP6_6">&#167;6.6</a>).</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>Keeping track of the kind of the entries in a column is a little tricky.
Columns are created early in Inform's run, before the full hierarchy of kinds
is in place; so TC structures tend to record a <code class="display"><span class="extract">NULL</span></code> kind for a while, and
are then corrected later. Moreover, they're sometimes revised in the light
of evidence, if the kind has to be inferred from the table's initial entries.
So we can't just set the kind once at creation time.
</p>
<p class="inwebparagraph">This has a knock-on effect on the predicate associated with the column,
because the kind of term A in listed-in-C(A, T) must match the kind
of entry in the column.
</p>
<pre class="display">
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">Tables::Columns::get_kind</span><span class="plain">(</span><span class="reserved">table_column</span><span class="plain"> *</span><span class="identifier">tc</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">tc</span><span class="plain">-&gt;</span><span class="identifier">kind_stored_in_column</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">Tables::Columns::to_kind</span><span class="plain">(</span><span class="reserved">table_column</span><span class="plain"> *</span><span class="identifier">tc</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Kinds::unary_construction</span><span class="plain">(</span><span class="identifier">CON_table_column</span><span class="plain">, </span><span class="identifier">tc</span><span class="plain">-&gt;</span><span class="element">kind_stored_in_column</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Tables::Columns::set_kind</span><span class="plain">(</span><span class="reserved">table_column</span><span class="plain"> *</span><span class="identifier">tc</span><span class="plain">, </span><span class="reserved">table</span><span class="plain"> *</span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) == </span><span class="identifier">CON_description</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Issue a problem message for a description heading</span> <span class="cwebmacronumber">6.1</span>&gt;<span class="plain">;</span>
<span class="identifier">tc</span><span class="plain">-&gt;</span><span class="element">kind_stored_in_column</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">;</span>
<span class="identifier">tc</span><span class="plain">-&gt;</span><span class="element">table_from_which_kind_inferred</span><span class="plain"> = </span><span class="identifier">t</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">TABLES</span><span class="plain">, </span><span class="string">"Table column $C contains kind $u, according to $B\n"</span><span class="plain">,</span>
<span class="identifier">tc</span><span class="plain">, </span><span class="identifier">tc</span><span class="plain">-&gt;</span><span class="element">kind_stored_in_column</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K_understanding</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_understanding</span><span class="plain">)))</span>
<span class="functiontext">Tables::Relations::supply_kind_for_listed_in_tc</span><span class="plain">(</span><span class="identifier">tc</span><span class="plain">-&gt;</span><span class="element">listed_in_predicate</span><span class="plain">, </span><span class="identifier">K_snippet</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Tables::Relations::supply_kind_for_listed_in_tc</span><span class="plain">(</span><span class="identifier">tc</span><span class="plain">-&gt;</span><span class="element">listed_in_predicate</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Tables::Columns::get_kind is used in <a href="#SP8">&#167;8</a>, <a href="#SP14">&#167;14</a>, <a href="#SP15">&#167;15</a>, <a href="#SP16">&#167;16</a>, 11/sm (<a href="11-sm.html#SP4">&#167;4</a>), 14/rv (<a href="14-rv.html#SP23_5">&#167;23.5</a>), 14/lv (<a href="14-lv.html#SP12_3">&#167;12.3</a>), 19/tb (<a href="19-tb.html#SP13">&#167;13</a>, <a href="19-tb.html#SP30_1">&#167;30.1</a>), 19/rsft (<a href="19-rsft.html#SP1_1_1_1_1">&#167;1.1.1.1.1</a>, <a href="19-rsft.html#SP1_2">&#167;1.2</a>), 19/tod (<a href="19-tod.html#SP6_4_1">&#167;6.4.1</a>).</p>
<p class="endnote">The function Tables::Columns::to_kind is used in 14/rv (<a href="14-rv.html#SP1">&#167;1</a>).</p>
<p class="endnote">The function Tables::Columns::set_kind is used in <a href="#SP13">&#167;13</a>, <a href="#SP14">&#167;14</a>, <a href="#SP15">&#167;15</a>, <a href="#SP16">&#167;16</a>, 19/tod (<a href="19-tod.html#SP6">&#167;6</a>, <a href="19-tod.html#SP6_4_1">&#167;6.4.1</a>).</p>
<p class="inwebparagraph"><a id="SP6_1"></a><b>&#167;6.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem message for a description heading</span> <span class="cwebmacronumber">6.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(5, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_table</span><span class="plain">(6, </span><span class="identifier">t</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::table_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TableColumnDescription</span><span class="plain">),</span>
<span class="identifier">t</span><span class="plain">, </span><span class="identifier">tc</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="string">"In %1, you've written the heading of the column '%2' to say that each entry "</span>
<span class="string">"should be %4. But descriptions aren't allowed as table entries - tables "</span>
<span class="string">"have to hold values, not descriptions of values."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>And here's the predicate:
</p>
<pre class="display">
<span class="reserved">binary_predicate</span><span class="plain"> *</span><span class="functiontext">Tables::Columns::get_listed_in_predicate</span><span class="plain">(</span><span class="reserved">table_column</span><span class="plain"> *</span><span class="identifier">tc</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">tc</span><span class="plain">-&gt;</span><span class="identifier">listed_in_predicate</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Tables::Columns::get_listed_in_predicate is used in 11/sm (<a href="11-sm.html#SP4">&#167;4</a>).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. Run-time support. </b>The run-time code needs a range of unique ID numbers to represent table columns;
these can't simply be addresses of the data because two uses of columns called
"population" in different tables need to have the same ID in each context.
(They need to run from 100 upward because numbers 0 to 99 refer to columns
by index within the current table.)
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Tables::Columns::get_id</span><span class="plain">(</span><span class="reserved">table_column</span><span class="plain"> *</span><span class="identifier">tc</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">100</span><span class="plain"> + </span><span class="identifier">tc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Tables::Columns::compile_run_time_support</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">iname</span><span class="plain"> = </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">TC_KOV_HL</span><span class="plain">);</span>
<span class="identifier">packaging_state</span><span class="plain"> </span><span class="identifier">save</span><span class="plain"> = </span><span class="functiontext">Routines::begin</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">);</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">tcv_s</span><span class="plain"> = </span><span class="functiontext">LocalVariables::add_named_call_as_symbol</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"tc"</span><span class="plain">);</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">SWITCH_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">tcv_s</span><span class="plain">);</span>
<span class="identifier">Produce::code</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="reserved">table_column</span><span class="plain"> *</span><span class="identifier">tc</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">tc</span><span class="plain">, </span><span class="reserved">table_column</span><span class="plain">) {</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">CASE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="functiontext">Tables::Columns::get_id</span><span class="plain">(</span><span class="identifier">tc</span><span class="plain">));</span>
<span class="identifier">Produce::code</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">RETURN_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="functiontext">Kinds::RunTime::emit_strong_id_as_val</span><span class="plain">(</span><span class="functiontext">Tables::Columns::get_kind</span><span class="plain">(</span><span class="identifier">tc</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="plain">}</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">RETURN_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Kinds::Constructors::UNKNOWN_iname</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
<span class="functiontext">Routines::end</span><span class="plain">(</span><span class="identifier">save</span><span class="plain">);</span>
<span class="functiontext">Hierarchy::make_available</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">iname</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Tables::Columns::get_id is used in 14/rv (<a href="14-rv.html#SP24_3">&#167;24.3</a>), 19/rsft (<a href="19-rsft.html#SP1_1_1_1_1_3">&#167;1.1.1.1.1.3</a>), 19/lr (<a href="19-lr.html#SP2">&#167;2</a>).</p>
<p class="endnote">The function Tables::Columns::compile_run_time_support is used in 19/rsft (<a href="19-rsft.html#SP1">&#167;1</a>).</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. Discovering columns. </b>New TCs aren't declared ("Density is a table column."): they are discovered
by looking through the column-heading lines of tables. Each piece of heading
text is passed to the following routine in turn:
</p>
<pre class="display">
<span class="reserved">table_column_usage</span><span class="plain"> </span><span class="functiontext">Tables::Columns::add_to_table</span><span class="plain">(</span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">table</span><span class="plain"> *</span><span class="identifier">t</span><span class="plain">) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">EXPW</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="reserved">table_column_usage</span><span class="plain"> </span><span class="identifier">tcu</span><span class="plain">;</span>
<span class="reserved">table_column</span><span class="plain"> *</span><span class="identifier">tc</span><span class="plain"> = </span><span class="functiontext">Tables::Columns::find_table_column</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">, &amp;</span><span class="identifier">EXPW</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">t</span><span class="plain">-&gt;</span><span class="element">no_columns</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">t</span><span class="plain">-&gt;</span><span class="element">columns</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">].</span><span class="element">column_identity</span><span class="plain"> == </span><span class="identifier">tc</span><span class="plain">) {</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(4, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::table_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_DuplicateColumnName</span><span class="plain">),</span>
<span class="identifier">t</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="string">"In %1, the column name %4 cannot be used, because there's already "</span>
<span class="string">"a column of the same name. (You can't have two columns with the "</span>
<span class="string">"same name in the same table.)"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">tcu</span><span class="plain">.</span><span class="element">column_identity</span><span class="plain"> = </span><span class="identifier">tc</span><span class="plain">;</span>
<span class="identifier">tcu</span><span class="plain">.</span><span class="element">entries</span><span class="plain"> = </span><span class="identifier">NounPhrases::new_raw</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">tcu</span><span class="plain">.</span><span class="element">kind_declaration_text</span><span class="plain"> = </span><span class="identifier">EXPW</span><span class="plain">;</span>
<span class="identifier">tcu</span><span class="plain">.</span><span class="element">actual_constant_entries</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">tcu</span><span class="plain">.</span><span class="element">observed_constant_cell</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">tcu</span><span class="plain">.</span><span class="element">kind_name_entries</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">tcu</span><span class="plain">.</span><span class="element">observed_kind_cell</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">package_request</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="functiontext">Hierarchy::package_within</span><span class="plain">(</span><span class="constant">TABLE_COLUMNS_HAP</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">-&gt;</span><span class="element">table_package</span><span class="plain">);</span>
<span class="identifier">tcu</span><span class="plain">.</span><span class="element">tcu_iname</span><span class="plain"> = </span><span class="functiontext">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="constant">COLUMN_DATA_HL</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">tcu</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Tables::Columns::add_to_table is used in 19/tb (<a href="19-tb.html#SP20_9_1">&#167;20.9.1</a>).</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>The syntax for table column headings is little complicated:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">EXISTING_TC</span><span class="plain"> </span><span class="constant">1</span><span class="plain"> </span><span class="comment">one seen before in another table</span>
<span class="definitionkeyword">define</span> <span class="constant">NEW_TC_WITH_KIND</span><span class="plain"> </span><span class="constant">2</span><span class="plain"> </span><span class="comment">never seen before, with a kind explicitly given</span>
<span class="definitionkeyword">define</span> <span class="constant">NEW_TC_WITHOUT_KIND</span><span class="plain"> </span><span class="constant">3</span><span class="plain"> </span><span class="comment">never seen before, with no specified kind</span>
<span class="definitionkeyword">define</span> <span class="constant">NEW_TC_TOPIC</span><span class="plain"> </span><span class="constant">4</span><span class="plain"> </span><span class="comment">a topic column, a specialised form of text</span>
<span class="definitionkeyword">define</span> <span class="constant">NEW_TC_PROBLEM</span><span class="plain"> </span><span class="constant">5</span><span class="plain"> </span><span class="comment">(something went wrong, so Inform can ignore this)</span>
</pre>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>The heading of a table column is the text in its entry in the first
(titling-only) row of the table. Usually that consists only of the column's
name, but optionally the kind can also be supplied in brackets &mdash; Inform
otherwise infers the kind from the contents below. The kind will subsequently
be parsed using <code class="display"><span class="extract">&lt;k-kind-articled&gt;</span></code>, but for timing reasons that happens later,
so the grammar below allows any text in the brackets. A "topic" column
needs special handling since it also overrides kind inference, making
what looks like text into grammar for parsing.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">table</span><span class="plain">-</span><span class="identifier">column</span><span class="plain">-</span><span class="identifier">heading</span><span class="plain">&gt; ::=</span>
<span class="plain">( *** ) | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_TableColumnBracketed problem</span> <span class="cwebmacronumber">11.3</span>&gt;
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="reserved">table</span><span class="plain">-</span><span class="identifier">column</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt; ( ... ) | ==&gt; </span><span class="constant">EXISTING_TC</span><span class="plain">; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">RP</span><span class="plain">[1]; &lt;&lt;</span><span class="identifier">k1</span><span class="plain">&gt;&gt; = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">WR</span><span class="plain">[1]); &lt;&lt;</span><span class="identifier">k2</span><span class="plain">&gt;&gt; = </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">WR</span><span class="plain">[1]);</span>
<span class="plain">&lt;</span><span class="reserved">table</span><span class="plain">-</span><span class="identifier">column</span><span class="plain">-</span><span class="identifier">heading</span><span class="plain">-</span><span class="identifier">unbracketed</span><span class="plain">&gt; ( ... ) | ==&gt; </span><span class="identifier">R</span><span class="plain">[1]; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">R</span><span class="plain">[1] != </span><span class="constant">NEW_TC_PROBLEM</span><span class="plain">) *</span><span class="identifier">X</span><span class="plain"> = </span><span class="constant">NEW_TC_WITH_KIND</span><span class="plain">; &lt;&lt;</span><span class="identifier">k1</span><span class="plain">&gt;&gt; = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">WR</span><span class="plain">[1]); &lt;&lt;</span><span class="identifier">k2</span><span class="plain">&gt;&gt; = </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">WR</span><span class="plain">[1]);</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="reserved">table</span><span class="plain">-</span><span class="identifier">column</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt; | ==&gt; </span><span class="constant">EXISTING_TC</span><span class="plain">; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">RP</span><span class="plain">[1]; &lt;&lt;</span><span class="identifier">k1</span><span class="plain">&gt;&gt; = -1; &lt;&lt;</span><span class="identifier">k2</span><span class="plain">&gt;&gt; = -1;</span>
<span class="plain">&lt;</span><span class="reserved">table</span><span class="plain">-</span><span class="identifier">column</span><span class="plain">-</span><span class="identifier">heading</span><span class="plain">-</span><span class="identifier">unbracketed</span><span class="plain">&gt; ==&gt; </span><span class="identifier">R</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="reserved">table</span><span class="plain">-</span><span class="identifier">column</span><span class="plain">-</span><span class="identifier">heading</span><span class="plain">-</span><span class="identifier">unbracketed</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">article</span><span class="plain">&gt; | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_TableColumnArticle problem</span> <span class="cwebmacronumber">11.1</span>&gt;
<span class="plain">{</span><span class="identifier">topic</span><span class="plain">} | ==&gt; </span><span class="constant">NEW_TC_TOPIC</span>
<span class="plain">{&lt;</span><span class="reserved">property</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt;} | ==&gt; </span><span class="constant">NEW_TC_WITHOUT_KIND</span>
<span class="plain">{&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">constant</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">&gt;} | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_TableColumnAlready problem</span> <span class="cwebmacronumber">11.2</span>&gt;
<span class="plain">... ==&gt; </span><span class="constant">NEW_TC_WITHOUT_KIND</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP11_1"></a><b>&#167;11.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_TableColumnArticle problem</span> <span class="cwebmacronumber">11.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = </span><span class="constant">NEW_TC_PROBLEM</span><span class="plain">;</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(4, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::table_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TableColumnArticle</span><span class="plain">),</span>
<span class="identifier">table_being_examined</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">table_cell_node</span><span class="plain">,</span>
<span class="string">"In %1, the column name %3 cannot be used, because there would be too "</span>
<span class="string">"much ambiguity arising from its ordinary meaning as an article. (It "</span>
<span class="string">"would be quite awkward talking about the '%4 entry', for example.)"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11_2"></a><b>&#167;11.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_TableColumnAlready problem</span> <span class="cwebmacronumber">11.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = </span><span class="constant">NEW_TC_PROBLEM</span><span class="plain">;</span>
<span class="functiontext">Problems::Issue::table_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TableColumnAlready</span><span class="plain">),</span>
<span class="identifier">table_being_examined</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">table_cell_node</span><span class="plain">,</span>
<span class="string">"In %1, the column name %3 cannot be used, because it already means "</span>
<span class="string">"something else."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11_3"></a><b>&#167;11.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_TableColumnBracketed problem</span> <span class="cwebmacronumber">11.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = </span><span class="constant">NEW_TC_PROBLEM</span><span class="plain">;</span>
<span class="functiontext">Problems::Issue::table_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TableColumnBracketed</span><span class="plain">),</span>
<span class="identifier">table_being_examined</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">table_cell_node</span><span class="plain">,</span>
<span class="string">"In %1, the column name %3 cannot be used, because it is in brackets. "</span>
<span class="string">"(Perhaps you intended to use the brackets to give the kind of the "</span>
<span class="string">"entries, but forgot to put a name before the opening bracket.)"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>When a column is found with a name not seen before &mdash; say, "merit points"
&mdash; the following grammar is used to construct a proper noun to refer to this
column; thus, "merit points column".
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">table</span><span class="plain">-</span><span class="identifier">column</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">-</span><span class="identifier">construction</span><span class="plain">&gt; ::=</span>
<span class="plain">... </span><span class="identifier">column</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b>And here's where we use the grammar above. We parse the heading text and
return the TC it refers to, creating it if necessary; and we also return the
text of any explicit kind declaration used within it.
</p>
<pre class="display">
<span class="reserved">table_column</span><span class="plain"> *</span><span class="functiontext">Tables::Columns::find_table_column</span><span class="plain">(</span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">table</span><span class="plain"> *</span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> *</span><span class="identifier">EXPW</span><span class="plain">) {</span>
<span class="identifier">table_cell_node</span><span class="plain"> = </span><span class="identifier">NounPhrases::new_raw</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">table_cell_row</span><span class="plain"> = -1;</span>
<span class="identifier">table_cell_col</span><span class="plain"> = -1;</span>
<span class="identifier">table_being_examined</span><span class="plain"> = </span><span class="identifier">t</span><span class="plain">;</span>
<span class="plain">*</span><span class="identifier">EXPW</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="plain">&lt;</span><span class="reserved">table</span><span class="plain">-</span><span class="identifier">column</span><span class="plain">-</span><span class="identifier">heading</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="reserved">table_column</span><span class="plain"> *</span><span class="identifier">tc</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain"> (&lt;&lt;</span><span class="identifier">r</span><span class="plain">&gt;&gt;) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">EXISTING_TC:</span>
<span class="plain">*</span><span class="identifier">EXPW</span><span class="plain"> = </span><span class="identifier">Wordings::new</span><span class="plain">(&lt;&lt;</span><span class="identifier">k1</span><span class="plain">&gt;&gt;, &lt;&lt;</span><span class="identifier">k2</span><span class="plain">&gt;&gt;);</span>
<span class="identifier">tc</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_table_column</span><span class="plain">(&lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEW_TC_TOPIC:</span><span class="plain"> </span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">K_understanding</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEW_TC_WITH_KIND:</span><span class="plain"> *</span><span class="identifier">EXPW</span><span class="plain"> = </span><span class="identifier">Wordings::new</span><span class="plain">(&lt;&lt;</span><span class="identifier">k1</span><span class="plain">&gt;&gt;, &lt;&lt;</span><span class="identifier">k2</span><span class="plain">&gt;&gt;); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEW_TC_WITHOUT_KIND:</span><span class="plain"> </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEW_TC_PROBLEM:</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>
&lt;<span class="cwebmacro">Make a try at identifying the any named kind, even though it probably won't work</span> <span class="cwebmacronumber">13.1</span>&gt;<span class="character">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tc</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span>&lt;<span class="cwebmacro">Create a new table column with this name</span> <span class="cwebmacronumber">13.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">) </span><span class="functiontext">Tables::Columns::set_kind</span><span class="plain">(</span><span class="identifier">tc</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">tc</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Tables::Columns::find_table_column is used in <a href="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP13_1"></a><b>&#167;13.1. </b>If the heading is something like "population (number)", the following will
correctly identify "number", because that's a kind which exists very early in
Inform's run. Something like "lucky charm (thing)" won't work, because "thing"
hasn't been created yet; but we'll catch it later.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Make a try at identifying the any named kind, even though it probably won't work</span> <span class="cwebmacronumber">13.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(*</span><span class="identifier">EXPW</span><span class="plain">)) &amp;&amp; (&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">kind</span><span class="plain">-</span><span class="identifier">articled</span><span class="plain">&gt;(*</span><span class="identifier">EXPW</span><span class="plain">))) {</span>
<span class="identifier">K</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;; *</span><span class="identifier">EXPW</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP13">&#167;13</a>.</p>
<p class="inwebparagraph"><a id="SP13_2"></a><b>&#167;13.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Create a new table column with this name</span> <span class="cwebmacronumber">13.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">W</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">table</span><span class="plain">-</span><span class="identifier">column</span><span class="plain">-</span><span class="identifier">heading</span><span class="plain">-</span><span class="identifier">unbracketed</span><span class="plain">&gt;, </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Assertions::Creator::vet_name</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) </span><span class="identifier">tc</span><span class="plain"> = </span><span class="functiontext">Tables::Columns::new_table_column</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="reserved">return</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="#SP13">&#167;13</a>.</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. Checking kind consistency. </b>Well, and now it's later. First, the following is called on each usage of a
column in turn:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Tables::Columns::check_explicit_headings</span><span class="plain">(</span><span class="reserved">table</span><span class="plain"> *</span><span class="identifier">t</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">table_column_usage</span><span class="plain"> *</span><span class="identifier">tcu</span><span class="plain">) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Tables::Columns::get_kind</span><span class="plain">(</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</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">tcu</span><span class="plain">-&gt;</span><span class="element">kind_declaration_text</span><span class="plain">)) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">EK</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">kind</span><span class="plain">-</span><span class="identifier">articled</span><span class="plain">&gt;(</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">kind_declaration_text</span><span class="plain">)) {</span>
<span class="identifier">EK</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">TABLES</span><span class="plain">, </span><span class="string">"$B col %d '%W' claims $u\n"</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">kind_declaration_text</span><span class="plain">, </span><span class="identifier">EK</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="functiontext">Tables::Columns::set_kind</span><span class="plain">(</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">EK</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">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">EK</span><span class="plain">)))</span>
&lt;<span class="cwebmacro">Issue a problem message for a heading inconsistency</span> <span class="cwebmacronumber">14.1</span>&gt;<span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Issue a problem message for an incomprehensible column heading</span> <span class="cwebmacronumber">14.2</span>&gt;<span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">TABLES</span><span class="plain">, </span><span class="string">"Column %d has no explicit kind named in $B\n"</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Tables::Columns::check_explicit_headings is used in 19/tb (<a href="19-tb.html#SP22">&#167;22</a>).</p>
<p class="inwebparagraph"><a id="SP14_1"></a><b>&#167;14.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem message for a heading inconsistency</span> <span class="cwebmacronumber">14.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">EK</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(5, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_table</span><span class="plain">(6, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">-&gt;</span><span class="element">table_from_which_kind_inferred</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::table_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TableColumnInconsistent</span><span class="plain">),</span>
<span class="identifier">t</span><span class="plain">, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">entries</span><span class="plain">,</span>
<span class="string">"In %1, you've written the heading of the column %3 to say that each entry "</span>
<span class="string">"should be %4. But a column with the same name also appears in %6, and each "</span>
<span class="string">"entry there is %5. Inform doesn't allow this - the same column name always "</span>
<span class="string">"has to have the same kind of entry, whichever tables it appears in."</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="SP14_2"></a><b>&#167;14.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem message for an incomprehensible column heading</span> <span class="cwebmacronumber">14.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Problems::Issue::table_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TableColumnBrackets</span><span class="plain">),</span>
<span class="identifier">t</span><span class="plain">, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">entries</span><span class="plain">,</span>
<span class="string">"In %1, I can't use the column heading %3. Brackets are only allowed in "</span>
<span class="string">"table column names when giving the kind of value which will be stored in "</span>
<span class="string">"the column. So 'poems (text)' is legal, but not 'poems (chiefly lyrical)'."</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. </b>Secondly, the actual entries are checked in turn, and their kinds passed
to the following routine. Again, "topic" columns are a complication, since
their kind is ostensibly <code class="display"><span class="extract">K_understanding</span></code> but the actual entries must be
<code class="display"><span class="extract">K_text</span></code>.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Tables::Columns::note_kind</span><span class="plain">(</span><span class="reserved">table</span><span class="plain"> *</span><span class="identifier">t</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">table_column_usage</span><span class="plain"> *</span><span class="identifier">tcu</span><span class="plain">,</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">cell</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">generic</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">generic</span><span class="plain">) {</span>
<span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">kind_name_entries</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">observed_kind_cell</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">observed_kind_cell</span><span class="plain"> = </span><span class="identifier">cell</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">kind_name_entries</span><span class="plain"> == </span><span class="constant">2</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Issue a problem for a second kind name in the column</span> <span class="cwebmacronumber">15.2</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">actual_constant_entries</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Issue a problem for a kind name lower in the column than a value</span> <span class="cwebmacronumber">15.1</span>&gt;
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">CK</span><span class="plain"> = </span><span class="functiontext">Tables::Columns::get_kind</span><span class="plain">(</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">CK</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="functiontext">Tables::Columns::set_kind</span><span class="plain">(</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">CK</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Issue a problem for an inconsistent kind for this column</span> <span class="cwebmacronumber">15.6</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">actual_constant_entries</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">observed_constant_cell</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">observed_constant_cell</span><span class="plain"> = </span><span class="identifier">cell</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">kind_name_entries</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Issue a problem for a value lower in the column than a kind name</span> <span class="cwebmacronumber">15.3</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">CK</span><span class="plain"> = </span><span class="identifier">Kinds::weaken</span><span class="plain">(</span><span class="functiontext">Tables::Columns::get_kind</span><span class="plain">(</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">));</span>
<span class="identifier">K</span><span class="plain"> = </span><span class="identifier">Kinds::weaken</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">CK</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="functiontext">Tables::Columns::set_kind</span><span class="plain">(</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">K</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">allow_refinement</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K_understanding</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">CK</span><span class="plain">, </span><span class="identifier">K_understanding</span><span class="plain">))) {</span>
<span class="identifier">CK</span><span class="plain"> = </span><span class="identifier">K_text</span><span class="plain">; </span><span class="comment">make sure the entries are texts...</span>
<span class="identifier">allow_refinement</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="comment">...and don't allow any change to the kind</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">CK</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">max_K</span><span class="plain"> = </span><span class="identifier">Kinds::Compare::accumulative_max</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">CK</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Behaviour::definite</span><span class="plain">(</span><span class="identifier">max_K</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(5, </span><span class="identifier">CK</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">t</span><span class="plain"> == </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">-&gt;</span><span class="element">table_from_which_kind_inferred</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Issue a problem for kind mismatch within column</span> <span class="cwebmacronumber">15.4</span>&gt;
<span class="reserved">else</span>
&lt;<span class="cwebmacro">Issue a problem for kind mismatch between columns of the same name</span> <span class="cwebmacronumber">15.5</span>&gt;<span class="plain">;</span>
<span class="identifier">allow_refinement</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">allow_refinement</span><span class="plain">)</span>
<span class="functiontext">Tables::Columns::set_kind</span><span class="plain">(</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">max_K</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 Tables::Columns::note_kind is used in 19/tb (<a href="19-tb.html#SP25">&#167;25</a>, <a href="19-tb.html#SP25_1">&#167;25.1</a>).</p>
<p class="inwebparagraph"><a id="SP15_1"></a><b>&#167;15.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem for a kind name lower in the column than a value</span> <span class="cwebmacronumber">15.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">quoted_col</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">; </span><span class="comment">i.e., counting from 1</span>
<span class="identifier">Problems::quote_number</span><span class="plain">(4, &amp;</span><span class="identifier">quoted_col</span><span class="plain">);</span>
<span class="identifier">Problems::quote_number</span><span class="plain">(5, &amp;</span><span class="identifier">table_cell_row</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(6, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">observed_constant_cell</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::table_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TableKindBelowValue</span><span class="plain">),</span>
<span class="identifier">t</span><span class="plain">, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">, </span><span class="identifier">cell</span><span class="plain">,</span>
<span class="string">"In %1, column %4 (%2), the entry %3 (row %5) is the name of a kind. "</span>
<span class="string">"This isn't a specific value. You're allowed to write in the name "</span>
<span class="string">"of a kind like this if the column otherwise has blank entries - to "</span>
<span class="string">"tell Inform what might eventually go there - but here the column "</span>
<span class="string">"already contains a genuine value higher up: %6. %P"</span>
<span class="string">"So the kind name has to go. You can either let me deduce the kind by "</span>
<span class="string">"myself, working it out from the actual values in the column, or you "</span>
<span class="string">"can put the kind in brackets after the column's name, at the top.)"</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><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem for a second kind name in the column</span> <span class="cwebmacronumber">15.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">quoted_col</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">; </span><span class="comment">i.e., counting from 1</span>
<span class="identifier">Problems::quote_number</span><span class="plain">(4, &amp;</span><span class="identifier">quoted_col</span><span class="plain">);</span>
<span class="identifier">Problems::quote_number</span><span class="plain">(5, &amp;</span><span class="identifier">table_cell_row</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(6, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">observed_kind_cell</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::table_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TableKindTwice</span><span class="plain">),</span>
<span class="identifier">t</span><span class="plain">, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">, </span><span class="identifier">cell</span><span class="plain">,</span>
<span class="string">"In %1, column %4 (%2), the entry %3 (row %5) is the name of a kind. "</span>
<span class="string">"This isn't a specific value. You're allowed to write in the name "</span>
<span class="string">"of a kind like this if the column starts out with blank entries - to "</span>
<span class="string">"tell me what might eventually go there - but only once; and "</span>
<span class="string">"this is the second time. (The first was %6.)"</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><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem for a value lower in the column than a kind name</span> <span class="cwebmacronumber">15.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">quoted_col</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">; </span><span class="comment">i.e., counting from 1</span>
<span class="identifier">Problems::quote_number</span><span class="plain">(4, &amp;</span><span class="identifier">quoted_col</span><span class="plain">);</span>
<span class="identifier">Problems::quote_number</span><span class="plain">(5, &amp;</span><span class="identifier">table_cell_row</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(6, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">observed_kind_cell</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::table_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TableValueBelowKind</span><span class="plain">),</span>
<span class="identifier">t</span><span class="plain">, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">, </span><span class="identifier">cell</span><span class="plain">,</span>
<span class="string">"In %1, column %4 (%2), the entry %3 (row %5) is a genuine, non-blank "</span>
<span class="string">"entry: it's a specific value. That's fine, of course - the whole "</span>
<span class="string">"idea of a table is to contain values - but this is a column which "</span>
<span class="string">"already contains a name of a kind: %6. %P"</span>
<span class="string">"Names of kinds are only allowed at the top of otherwise blank columns: "</span>
<span class="string">"they tell me what might eventually go there. So the kind name has to go. "</span>
<span class="string">"You can replace it with a blank '--', and then either let me deduce the "</span>
<span class="string">"kind by myself, working it out from the actual values in the column, or "</span>
<span class="string">"you can put the kind in brackets after the column's name, at the top.)"</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">Issue a problem for kind mismatch within column</span> <span class="cwebmacronumber">15.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">quoted_col</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">; </span><span class="comment">i.e., counting from 1</span>
<span class="identifier">Problems::quote_number</span><span class="plain">(6, &amp;</span><span class="identifier">quoted_col</span><span class="plain">);</span>
<span class="identifier">Problems::quote_number</span><span class="plain">(7, &amp;</span><span class="identifier">table_cell_row</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::table_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TableIncompatibleEntry</span><span class="plain">),</span>
<span class="identifier">t</span><span class="plain">, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">, </span><span class="identifier">cell</span><span class="plain">,</span>
<span class="string">"In %1, column %6 (%2), the entry %3 (row %7) doesn't fit what I know "</span>
<span class="string">"about '%2' - it's %4, whereas I think every entry ought to be %5."</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">Issue a problem for kind mismatch between columns of the same name</span> <span class="cwebmacronumber">15.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">quoted_col</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">; </span><span class="comment">i.e., counting from 1</span>
<span class="functiontext">Problems::quote_table</span><span class="plain">(6, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">-&gt;</span><span class="element">table_from_which_kind_inferred</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(7, </span><span class="identifier">Nouns::nominative</span><span class="plain">(</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">));</span>
<span class="identifier">Problems::quote_number</span><span class="plain">(8, &amp;</span><span class="identifier">quoted_col</span><span class="plain">);</span>
<span class="identifier">Problems::quote_number</span><span class="plain">(9, &amp;</span><span class="identifier">table_cell_row</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::table_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TableIncompatibleEntry2</span><span class="plain">),</span>
<span class="identifier">t</span><span class="plain">, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">, </span><span class="identifier">cell</span><span class="plain">,</span>
<span class="string">"In %1, column %8 (%2), the entry %3 (row %9) has the wrong kind to be in "</span>
<span class="string">"the '%2' column - it's %4, whereas I think every entry ought to be %5. %P"</span>
<span class="string">"The entries under a given column name must be blanks or values of the same "</span>
<span class="string">"kind as each other, and this applies even to columns in different tables "</span>
<span class="string">"if they have the same name. Compare the table %6, where there's also a "</span>
<span class="string">"column called '%7'."</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>Relatedly, but visible only if there are no entries so that the above never
happens:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem for an inconsistent kind for this column</span> <span class="cwebmacronumber">15.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Problems::quote_table</span><span class="plain">(6, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">-&gt;</span><span class="element">table_from_which_kind_inferred</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(7, </span><span class="identifier">Nouns::nominative</span><span class="plain">(</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">));</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(5, </span><span class="identifier">CK</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::table_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TableColumnIncompatible</span><span class="plain">),</span>
<span class="identifier">t</span><span class="plain">, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">, </span><span class="identifier">cell</span><span class="plain">,</span>
<span class="string">"In %1, the column '%2' is declared as holding %4, but when the same "</span>
<span class="string">"column appeared in table %6, the contents were said there to be %5. %P"</span>
<span class="string">"The entries under a given column name must be values of the same "</span>
<span class="string">"kind as each other, and this applies even to columns in different tables "</span>
<span class="string">"if they have the same name."</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. </b>Thirdly and lastly:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Tables::Columns::approve_kind</span><span class="plain">(</span><span class="reserved">table</span><span class="plain"> *</span><span class="identifier">t</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">table_column_usage</span><span class="plain"> *</span><span class="identifier">tcu</span><span class="plain">) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Tables::Columns::get_kind</span><span class="plain">(</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">TABLES</span><span class="plain">, </span><span class="string">"Column %d '%W' has kind $u with data:\n$T"</span><span class="plain">,</span>
<span class="identifier">i</span><span class="plain">, </span><span class="identifier">Nouns::nominative</span><span class="plain">(</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">), </span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">entries</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) == </span><span class="identifier">CON_list_of</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">Kinds::unary_construction_material</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">), </span><span class="identifier">K_value</span><span class="plain">))) {</span>
<span class="functiontext">Problems::Issue::table_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TableColumnEmptyLists</span><span class="plain">),</span>
<span class="identifier">t</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">entries</span><span class="plain">,</span>
<span class="string">"In %1, the column %3 seems to consist only of empty lists. "</span>
<span class="string">"This means that I can't tell what kind of value it should hold - "</span>
<span class="string">"are they to be lists of numbers, for instance, or lists of texts, "</span>
<span class="string">"or some other possibility? Either one of the entries must contain a "</span>
<span class="string">"non-empty list - so that I can deduce the answer by looking at what "</span>
<span class="string">"is in it - or else the column heading must say, e.g., by calling it "</span>
<span class="string">"'exceptions (list of texts)' with the kind of value in brackets after "</span>
<span class="string">"the name."</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">quoted_col</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">; </span><span class="comment">i.e., counting from 1</span>
<span class="identifier">Problems::quote_number</span><span class="plain">(4, &amp;</span><span class="identifier">quoted_col</span><span class="plain">);</span>
<span class="functiontext">Problems::Issue::table_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TableKindlessColumn</span><span class="plain">),</span>
<span class="identifier">t</span><span class="plain">, </span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="string">"Column %4 (%2) of %1 contains no values and doesn't tell me "</span>
<span class="string">"anything about its kind%|, "</span>
<span class="string">"which means that I don't know how to deal with it. You should "</span>
<span class="string">"either put a value into the column somewhere, or else write "</span>
<span class="string">"the kind in as part of the heading: '%2 (a number)', say."</span><span class="plain">);</span>
<span class="functiontext">Tables::Columns::set_kind</span><span class="plain">(</span><span class="identifier">tcu</span><span class="plain">-&gt;</span><span class="element">column_identity</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">K_number</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Tables::Columns::approve_kind is used in 19/tb (<a href="19-tb.html#SP22">&#167;22</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><i>(This section begins Chapter 19: Table Data.)</i></li><li><a href="19-tb.html">Continue with 'Tables'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>