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-rsft.html
2019-09-01 11:50:12 +01:00

526 lines
57 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>19/tb</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<!--Weave of '19/rsft' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">core</a></li><li><a href="index.html#19">Chapter 19: Table Data</a></li><li><b>Runtime Support for Tables</b></li></ul><p class="purpose">To compile run-time data structures holding tables.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Compiling tables</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Compiling tables. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Tables::Support::compile</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Compile the data structures for entry storage</span> <span class="cwebmacronumber">1.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compile the blanks bitmap table</span> <span class="cwebmacronumber">1.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compile the Table of Tables</span> <span class="cwebmacronumber">1.3</span>&gt;<span class="plain">;</span>
<span class="functiontext">Tables::Columns::compile_run_time_support</span><span class="plain">();</span>
&lt;<span class="cwebmacro">Note the usage of run-time memory for tables</span> <span class="cwebmacronumber">1.4</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Tables::Support::compile is used in 1/mr (<a href="1-mr.html#SP4_14">&#167;4.14</a>).</p>
<p class="inwebparagraph"><a id="SP1_1"></a><b>&#167;1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Compile the data structures for entry storage</span> <span class="cwebmacronumber">1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">BEGIN_COMPILATION_MODE</span><span class="plain">;</span>
<span class="identifier">COMPILATION_MODE_EXIT</span><span class="plain">(</span><span class="constant">DEREFERENCE_POINTERS_CMODE</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">blanks_array_hwm</span><span class="plain"> = 0; </span> <span class="comment">the high water mark of storage used in the blanks array</span>
<span class="reserved">table</span><span class="plain"> *</span><span class="identifier">t</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="reserved">table</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="element">&gt;amendment_of</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Compile the run-time storage for the table</span> <span class="cwebmacronumber">1.1.1</span>&gt;<span class="plain">;</span>
<span class="constant">END_COMPILATION_MODE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP1_1_1"></a><b>&#167;1.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Compile the run-time storage for the table</span> <span class="cwebmacronumber">1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">words_used</span><span class="plain"> = 0;</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;table_created_at</span><span class="plain">-</span><span class="element">&gt;source_table</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Compile the outer table array</span> <span class="cwebmacronumber">1.1.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;approximate_array_space_needed</span><span class="plain"> = </span><span class="identifier">words_used</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_1">&#167;1.1</a>.</p>
<p class="inwebparagraph"><a id="SP1_1_1_1"></a><b>&#167;1.1.1.1. </b>At run time, the data in T is essentially stored as a table of column
tables, one for each column. A column table begins with a word identifying
the table column number (so that two columns both called "price" in
different tables will have the same identifying value heading their column
tables), together with special bits set to indicate that exotic types of
data are stored inside. Thus if T has C columns, the column tables are
found at <code class="display"><span class="extract">T--&gt;1</span></code>, <code class="display"><span class="extract">T--&gt;2</span></code>, ..., <code class="display"><span class="extract">T--&gt;C</span></code>.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile the outer table array</span> <span class="cwebmacronumber">1.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;</span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;no_columns</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++) {</span>
&lt;<span class="cwebmacro">Compile the inner table array for column j</span> <span class="cwebmacronumber">1.1.1.1.1</span>&gt;<span class="plain">;</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">Emit::named_table_array_begin</span><span class="plain">(</span><span class="functiontext">Tables::identifier</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">), </span><span class="identifier">K_value</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">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;</span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;no_columns</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++) {</span>
<span class="functiontext">Emit::array_iname_entry</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;columns</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]</span><span class="element">.tcu_iname</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="functiontext">Emit::array_end</span><span class="plain">(</span><span class="identifier">save</span><span class="plain">);</span>
<span class="identifier">words_used</span><span class="plain"> += </span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;no_columns</span><span class="plain"> + 1;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_1_1">&#167;1.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP1_1_1_1_1"></a><b>&#167;1.1.1.1.1. </b>Each column table <code class="display"><span class="extract">C</span></code> has its identifying number and bitmap combined in
<code class="display"><span class="extract">C--&gt;1</span></code> (the ID occupies the lower bits), a pointer to its blanks storage
in <code class="display"><span class="extract">C--&gt;2</span></code>, and its actual data in <code class="display"><span class="extract">C--&gt;3</span></code>, <code class="display"><span class="extract">C--&gt;4</span></code>, ..., <code class="display"><span class="extract">C--&gt;(R+2)</span></code>,
where R is the number of rows.
</p>
<p class="inwebparagraph">The contents of a cell are not just its value but also an indication of
whether or not it is formally blank, which often makes it impossible to
store in a single virtual machine word. In those situations we also store
a single bit in the "blanks array" which records whether the cell is blank
or not.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile the inner table array for column j</span> <span class="cwebmacronumber">1.1.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">packaging_state</span><span class="plain"> </span><span class="identifier">save</span><span class="plain"> = </span><span class="functiontext">Emit::named_table_array_begin</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;columns</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]</span><span class="element">.tcu_iname</span><span class="plain">, </span><span class="identifier">K_value</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">t</span><span class="plain">-</span><span class="element">&gt;columns</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]</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">"Compiling column: $C\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">tc</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">tc</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">bits</span><span class="plain"> = 0; </span> <span class="comment">bitmap of some properties of the column</span>
&lt;<span class="cwebmacro">Write the bitmap and blank-offset words</span> <span class="cwebmacronumber">1.1.1.1.1.3</span>&gt;<span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">e</span><span class="plain"> = 0; </span> <span class="comment">which bit we're up to within the current byte of the blanks array</span>
<span class="reserved">for</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">t</span><span class="plain">-</span><span class="element">&gt;columns</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]</span><span class="element">.entries</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">; </span><span class="identifier">cell</span><span class="plain">; </span><span class="identifier">cell</span><span class="plain"> = </span><span class="identifier">cell</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Write a cell value for the initial contents of this cell</span> <span class="cwebmacronumber">1.1.1.1.1.4</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Allocate one bit in the blanks array, if needed</span> <span class="cwebmacronumber">1.1.1.1.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">words_used</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">blank_count</span><span class="plain"> = </span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;blank_rows</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">blank_count</span><span class="plain"> == 0) &amp;&amp; (</span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;columns</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]</span><span class="element">.entries</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="identifier">blank_count</span><span class="plain"> = 1;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">br</span><span class="plain"> = 0; </span><span class="identifier">br</span><span class="plain"> &lt; </span><span class="identifier">blank_count</span><span class="plain">; </span><span class="identifier">br</span><span class="plain">++) {</span>
&lt;<span class="cwebmacro">Write a cell value for a blank cell</span> <span class="cwebmacronumber">1.1.1.1.1.5</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Allocate one bit in the blanks array, if needed</span> <span class="cwebmacronumber">1.1.1.1.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">words_used</span><span class="plain">++;</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Pad out the blanks array as needed</span> <span class="cwebmacronumber">1.1.1.1.1.2</span>&gt;<span class="plain">;</span>
<span class="functiontext">Emit::array_end</span><span class="plain">(</span><span class="identifier">save</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">"Done column: $C\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">tc</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_1_1_1">&#167;1.1.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP1_1_1_1_1_1"></a><b>&#167;1.1.1.1.1.1. </b>In this part of the code we're carefully keeping track of how much blank
array storage we need (perhaps none!), but not compiling it. The sole aim
is to make sure <code class="display"><span class="extract">blanks_array_hwm</span></code> has the correct value at the beginning of
each column needing blank bits.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Allocate one bit in the blanks array, if needed</span> <span class="cwebmacronumber">1.1.1.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">bits</span><span class="plain"> &amp; </span><span class="constant">TB_COLUMN_NOBLANKBITS</span><span class="plain">) == 0) {</span>
<span class="identifier">e</span><span class="plain">++; </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">e</span><span class="plain"> % 8) == 0) </span><span class="identifier">blanks_array_hwm</span><span class="plain">++;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_1_1_1_1">&#167;1.1.1.1.1</a> (twice).</p>
<p class="inwebparagraph"><a id="SP1_1_1_1_1_2"></a><b>&#167;1.1.1.1.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Pad out the blanks array as needed</span> <span class="cwebmacronumber">1.1.1.1.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">bits</span><span class="plain"> &amp; </span><span class="constant">TB_COLUMN_NOBLANKBITS</span><span class="plain">) == 0) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">e</span><span class="plain"> % 8) != 0) </span><span class="identifier">blanks_array_hwm</span><span class="plain">++; </span> <span class="comment">pad out a partial byte with zero bits</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_1_1_1_1">&#167;1.1.1.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP1_1_1_1_1_3"></a><b>&#167;1.1.1.1.1.3. </b>The table column array begins with two words: a bitmap giving some minimal
idea of what can safely be done with values, and then an address within the
blanks bitmap array (if this is needed).
</p>
<p class="inwebparagraph">A weakness of this scheme occurs if column ID numbers ever grow large enough
to collide with the bits used here: at present, that would need 412 different
table column names, which is dangerously plausible. We should fix this.
</p>
<p class="inwebparagraph">The following flags are also defined in <code class="display"><span class="extract">Tables.i6t</span></code> and must agree with
the values given there.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">TB_COLUMN_REAL</span><span class="plain"> 0</span><span class="identifier">x8000</span>
<span class="definitionkeyword">define</span> <span class="constant">TB_COLUMN_SIGNED</span><span class="plain"> 0</span><span class="identifier">x4000</span>
<span class="definitionkeyword">define</span> <span class="constant">TB_COLUMN_TOPIC</span><span class="plain"> 0</span><span class="identifier">x2000</span>
<span class="definitionkeyword">define</span> <span class="constant">TB_COLUMN_DONTSORTME</span><span class="plain"> 0</span><span class="identifier">x1000</span>
<span class="definitionkeyword">define</span> <span class="constant">TB_COLUMN_NOBLANKBITS</span><span class="plain"> 0</span><span class="identifier">x0800</span>
<span class="definitionkeyword">define</span> <span class="constant">TB_COLUMN_CANEXCHANGE</span><span class="plain"> 0</span><span class="identifier">x0400</span>
<span class="definitionkeyword">define</span> <span class="constant">TB_COLUMN_ALLOCATED</span><span class="plain"> 0</span><span class="identifier">x0200</span>
</pre>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Write the bitmap and blank-offset words</span> <span class="cwebmacronumber">1.1.1.1.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Behaviour::can_exchange</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)) </span><span class="identifier">bits</span><span class="plain"> += </span><span class="constant">TB_COLUMN_CANEXCHANGE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Kinds::Behaviour::uses_signed_comparisons</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)) ||</span>
<span class="plain">(</span><span class="identifier">Kinds::FloatingPoint::uses_floating_point</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">))) </span><span class="identifier">bits</span><span class="plain"> += </span><span class="constant">TB_COLUMN_SIGNED</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::FloatingPoint::uses_floating_point</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)) </span><span class="identifier">bits</span><span class="plain"> += </span><span class="constant">TB_COLUMN_REAL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Behaviour::uses_pointer_values</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)) </span><span class="identifier">bits</span><span class="plain"> += </span><span class="constant">TB_COLUMN_ALLOCATED</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">K_understanding</span><span class="plain">)) </span><span class="identifier">bits</span><span class="plain"> = </span><span class="constant">TB_COLUMN_TOPIC</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Behaviour::requires_blanks_bitmap</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="identifier">bits</span><span class="plain"> += </span><span class="constant">TB_COLUMN_NOBLANKBITS</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="element">&gt;preserve_row_order_at_run_time</span><span class="plain">) </span><span class="identifier">bits</span><span class="plain"> += </span><span class="constant">TB_COLUMN_DONTSORTME</span><span class="plain">;</span>
<span class="functiontext">Emit::array_numeric_entry</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">bits</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">bits</span><span class="plain"> &amp; </span><span class="constant">TB_COLUMN_NOBLANKBITS</span><span class="plain">)</span>
<span class="functiontext">Emit::array_null_entry</span><span class="plain">();</span>
<span class="reserved">else</span>
<span class="functiontext">Emit::array_numeric_entry</span><span class="plain">((</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">blanks_array_hwm</span><span class="plain">);</span>
<span class="identifier">words_used</span><span class="plain"> += 2;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_1_1_1_1">&#167;1.1.1.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP1_1_1_1_1_4"></a><b>&#167;1.1.1.1.1.4. </b>The cell can only contain a generic value in the case of column 1 of a table
used to define new kinds; in this case it doesn't matter what we write, but
<code class="display"><span class="extract">nothing</span></code> has the virtue of being typesafe.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Write a cell value for the initial contents of this cell</span> <span class="cwebmacronumber">1.1.1.1.1.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">current_sentence</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">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">cell</span><span class="plain">, </span><span class="constant">table_cell_unspecified_ANNOT</span><span class="plain">)) {</span>
&lt;<span class="cwebmacro">Write a cell value for a blank cell</span> <span class="cwebmacronumber">1.1.1.1.1.5</span>&gt;<span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">bits</span><span class="plain"> &amp; </span><span class="constant">TB_COLUMN_TOPIC</span><span class="plain">) {</span>
<span class="identifier">inter_t</span><span class="plain"> </span><span class="identifier">v1</span><span class="plain"> = 0, </span><span class="identifier">v2</span><span class="plain"> = 0;</span>
<span class="identifier">PL::Parsing::compile_understanding</span><span class="plain">(&amp;</span><span class="identifier">v1</span><span class="plain">, &amp;</span><span class="identifier">v2</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">cell</span><span class="plain">), </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="functiontext">Emit::array_generic_entry</span><span class="plain">(</span><span class="identifier">v1</span><span class="plain">, </span><span class="identifier">v2</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">val</span><span class="plain"> = </span><span class="identifier">ParseTree::get_evaluation</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="functiontext">Specifications::is_kind_like</span><span class="plain">(</span><span class="identifier">val</span><span class="plain">)) </span><span class="functiontext">Emit::array_numeric_entry</span><span class="plain">(0);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">val</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Valueless cell"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Specifications::Compiler::emit_constant_to_kind</span><span class="plain">(</span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">}</span>
<span class="identifier">words_used</span><span class="plain">++;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_1_1_1_1">&#167;1.1.1.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP1_1_1_1_1_5"></a><b>&#167;1.1.1.1.1.5. </b>As we've noted, our storage for a cell is both the array value we write here
and also a separate bit in the blanks array. In practice, though, it's inefficient
to look up two parallel structures each time we want to access the cell. So a
blank cell is represented as both the value <code class="display"><span class="extract">TABLE_NOVALUE</span></code>, chosen so that it
is very unlikely ever to occur as a genuine table value (currently it's the
picturesque hexadecimal value <code class="display"><span class="extract">0xDEADCE11</span></code>), and also as a blank bit set in
the blanks array. This makes a negative check &mdash; that something is not blank
&mdash; very quick, since only in the very rare case when the value does coincide
with <code class="display"><span class="extract">TABLE_NOVALUE</span></code> do we need to check the blanks array. A positive check
necessarily takes longer, but this cannot be helped.
</p>
<p class="inwebparagraph">With some kinds it is possible to prove that <code class="display"><span class="extract">TABLE_NOVALUE</span></code> cannot be a legal
value, and then space in the blanks array isn't needed: this is when the
<code class="display"><span class="extract">TB_COLUMN_NOBLANKBITS</span></code> flag is set. These kinds include all enumerated kinds
and also object numbers. (The latter are enumerated in the Z-machine but not
in Glulx: however, <code class="display"><span class="extract">TABLE_NOVALUE</span></code> is so large a number that it can never be
an object reference value in any story file smaller than 3.5 GB, and in
practice I6 and I7 are not capable of generating story files above 2 GB in any
case.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Write a cell value for a blank cell</span> <span class="cwebmacronumber">1.1.1.1.1.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;fill_in_blanks</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="functiontext">Emit::array_iname_entry</span><span class="plain">(</span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">TABLE_NOVALUE_HL</span><span class="plain">));</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Kinds::RunTime::emit_default_value</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">EMPTY_WORDING</span><span class="plain">, </span><span class="string">"table entry"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_1_1_1_1">&#167;1.1.1.1.1</a>, <a href="#SP1_1_1_1_1_4">&#167;1.1.1.1.1.4</a>.</p>
<p class="inwebparagraph"><a id="SP1_2"></a><b>&#167;1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Compile the blanks bitmap table</span> <span class="cwebmacronumber">1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<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">TB_BLANKS_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">Emit::named_byte_array_begin</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">, </span><span class="identifier">K_number</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">LOOP_OVER</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="reserved">table</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="element">&gt;amendment_of</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;table_created_at</span><span class="plain">-</span><span class="element">&gt;source_table</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">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;</span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;no_columns</span><span class="plain">; </span><span class="identifier">j</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">t</span><span class="plain">-</span><span class="element">&gt;columns</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]</span><span class="element">.column_identity</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Behaviour::requires_blanks_bitmap</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">FALSE</span><span class="plain">)</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">current_bit</span><span class="plain"> = 1, </span><span class="identifier">byte_so_far</span><span class="plain"> = 0;</span>
&lt;<span class="cwebmacro">Compile blank bits for entries from the source text</span> <span class="cwebmacronumber">1.2.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compile blank bits for additional blank rows</span> <span class="cwebmacronumber">1.2.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_bit</span><span class="plain"> != 1) </span>&lt;<span class="cwebmacro">Ship the current byte of the blanks table</span> <span class="cwebmacronumber">1.2.3</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="functiontext">Emit::array_null_entry</span><span class="plain">();</span>
<span class="functiontext">Emit::array_null_entry</span><span class="plain">();</span>
<span class="functiontext">Emit::array_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>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP1_2_1"></a><b>&#167;1.2.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Compile blank bits for entries from the source text</span> <span class="cwebmacronumber">1.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">cell</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">cell</span><span class="plain"> = </span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;columns</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]</span><span class="element">.entries</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">; </span><span class="identifier">cell</span><span class="plain">; </span><span class="identifier">cell</span><span class="plain"> = </span><span class="identifier">cell</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">cell</span><span class="plain">, </span><span class="constant">table_cell_unspecified_ANNOT</span><span class="plain">))</span>
<span class="plain">&amp;&amp; (</span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;fill_in_blanks</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">))</span>
<span class="identifier">byte_so_far</span><span class="plain"> += </span><span class="identifier">current_bit</span><span class="plain">;</span>
<span class="identifier">current_bit</span><span class="plain"> = </span><span class="identifier">current_bit</span><span class="plain">*2;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_bit</span><span class="plain"> == 256) </span>&lt;<span class="cwebmacro">Ship the current byte of the blanks table</span> <span class="cwebmacronumber">1.2.3</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_2">&#167;1.2</a>.</p>
<p class="inwebparagraph"><a id="SP1_2_2"></a><b>&#167;1.2.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Compile blank bits for additional blank rows</span> <span class="cwebmacronumber">1.2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain"> = 0; </span><span class="identifier">k</span><span class="plain"> &lt; </span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;blank_rows</span><span class="plain">; </span><span class="identifier">k</span><span class="plain">++) {</span>
<span class="identifier">byte_so_far</span><span class="plain"> += </span><span class="identifier">current_bit</span><span class="plain">;</span>
<span class="identifier">current_bit</span><span class="plain"> = </span><span class="identifier">current_bit</span><span class="plain">*2;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_bit</span><span class="plain"> == 256) </span>&lt;<span class="cwebmacro">Ship the current byte of the blanks table</span> <span class="cwebmacronumber">1.2.3</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_2">&#167;1.2</a>.</p>
<p class="inwebparagraph"><a id="SP1_2_3"></a><b>&#167;1.2.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Ship the current byte of the blanks table</span> <span class="cwebmacronumber">1.2.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Emit::array_numeric_entry</span><span class="plain">((</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">byte_so_far</span><span class="plain">);</span>
<span class="identifier">byte_so_far</span><span class="plain"> = 0; </span><span class="identifier">current_bit</span><span class="plain"> = 1;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_2">&#167;1.2</a>, <a href="#SP1_2_1">&#167;1.2.1</a>, <a href="#SP1_2_2">&#167;1.2.2</a>.</p>
<p class="inwebparagraph"><a id="SP1_3"></a><b>&#167;1.3. </b>We need a default value for the "table" kind, but it's not obvious what
it should be. So <code class="display"><span class="extract">TheEmptyTable</span></code> is a stunted form of the above data
structure: a table with no columns and no rows, which would otherwise be
against the rules. (The Template file "Tables.i6t" defines it.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile the Table of Tables</span> <span class="cwebmacronumber">1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<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">TABLEOFTABLES_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">Emit::named_array_begin</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">);</span>
<span class="functiontext">Emit::array_iname_entry</span><span class="plain">(</span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">EMPTY_TABLE_HL</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">LOOP_OVER</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="reserved">table</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="element">&gt;amendment_of</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="functiontext">Emit::array_iname_entry</span><span class="plain">(</span><span class="functiontext">Tables::identifier</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="functiontext">Emit::array_numeric_entry</span><span class="plain">(0);</span>
<span class="functiontext">Emit::array_numeric_entry</span><span class="plain">(0);</span>
<span class="functiontext">Emit::array_end</span><span class="plain">(</span><span class="identifier">save</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP1_4"></a><b>&#167;1.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Note the usage of run-time memory for tables</span> <span class="cwebmacronumber">1.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">table</span><span class="plain"> *</span><span class="identifier">t</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="reserved">table</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="element">&gt;amendment_of</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)</span>
<span class="functiontext">VirtualMachines::note_usage</span><span class="plain">(</span><span class="string">"table"</span><span class="plain">,</span>
<span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;headline_fragment</span><span class="plain">),</span>
<span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;approximate_array_space_needed</span><span class="plain">, 0, </span><span class="identifier">FALSE</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>The following allows tables to be said: it's a routine which switches on
table values and prints the (title-cased) name of the one which matches.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Tables::Support::compile_print_table_names</span><span class="plain">(</span><span class="reserved">void</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">inter_name</span><span class="plain"> *</span><span class="identifier">iname</span><span class="plain"> = </span><span class="identifier">Kinds::Behaviour::get_iname</span><span class="plain">(</span><span class="identifier">K_table</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">T_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">"T"</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">T_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="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_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_table</span><span class="plain">, </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">THEEMPTYTABLE_HL</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">PRINT_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_text</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">I</span><span class="string">"(the empty table)"</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::rtrue</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="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="reserved">table</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="element">&gt;amendment_of</span><span class="plain"> == </span><span class="identifier">FALSE</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_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_table</span><span class="plain">, </span><span class="functiontext">Tables::identifier</span><span class="plain">(</span><span class="identifier">t</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">PRINT_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">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">-</span><span class="element">&gt;headline_fragment</span><span class="plain">));</span>
<span class="identifier">Produce::val_text</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">S</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">S</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::rtrue</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::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">DEFAULT_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::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">PRINT_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_text</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">I</span><span class="string">"** No such table **"</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::rtrue</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="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="functiontext">Routines::end</span><span class="plain">(</span><span class="identifier">save</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Tables::Support::compile_print_table_names is used in 1/mr (<a href="1-mr.html#SP4_12">&#167;4.12</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="19-tb.html">Back to 'Tables'</a></li><li><a href="19-tod.html">Continue with 'Tables of Definitions'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>