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

941 lines
116 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>14/rv</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 '14/lv' 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#14">Chapter 14: Specifications</a></li><li><b>Lvalues</b></li></ul><p class="purpose">Utility functions for specifications representing lvalues, that is, storage locations for values at run-time.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Creation</a></li><li><a href="#SP7">&#167;7. Testing</a></li><li><a href="#SP10">&#167;10. Pretty-printing</a></li><li><a href="#SP12">&#167;12. Compilation</a></li><li><a href="#SP14">&#167;14. Rvalue compilation</a></li><li><a href="#SP15">&#167;15. Lvalue compilation</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Creation. </b>"Lvalues" can occur on the left of an assignment sign: they are values
which can be written to.
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">LOCAL_VARIABLE_NT</span></code> refers to a specific local variable, so it has meaning
only within the routine currently being compiled. A <code class="display"><span class="extract">local_variable</span></code> pointer
is attached. There are no references or arguments.
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">NONLOCAL_VARIABLE_NT</span></code> refers to a variable of any other scope: that is, a
global variable, or perhaps a rulebook, action or activity variable. The
important distinction between these other scopes and local scope is
essentially that local variables live on the I6 call-stack and have only a
local namespace, whereas others correspond to array entries or global I6
variables and share a global namespace. (It is basically a matter of
implementation convenience which makes us divide the stock of variables
into two different species this way.) A <code class="display"><span class="extract">instance *</span></code> pointer is attached,
identifying the name of the variable in question. There are no
arguments.
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">PROPERTY_VALUE_NT</span></code> represents a given (value-)property of a given object,
not the name of a property in abstract. Thus "description of the Police
Commissioner" qualifies, but "description" does not. There are two arguments:
the property and the object which possesses it, respectively.
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">TABLE_ENTRY_NT</span></code> represents a given entry to a table, which can be referred
to in several different ways. There are four different kinds of table reference,
distinguished by the number of arguments found:
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(1) 1 argument. By column name only, the table and row to be understood from
context because we have selected a row in the surrounding source text.
</li><li>(2) 2 arguments. Used as a condition to see if a value is listed in a
given column of a given table. Argument 0 must be a constant of kind
"table column", argument 1 any value of kind "table". (Argument 0
has to be a constant because it is not type-safe to allow looping through
columns, say: different columns have different kinds, and the compiler
would be unable to tell the kind of the result of such a lookup. The
same doesn't apply to argument 1, perhaps oddly, because Inform requires
that every column name have the same kind in every table using it. So
the choice of table does not have to be a constant, and this allows
for some interesting data structures to be built.)
</li><li>(3) 3 arguments. An explicitly specified entry. The arguments are the
table column, row number, and table respectively.
</li><li>(4) 4 arguments. A reference to the X corresponding to a Y value of Z in table T.
The arguments are X, Y, Z, T respectively.
</li></ul>
<p class="inwebparagraph"><code class="display"><span class="extract">LIST_ENTRY_NT</span></code> represents a given entry in a list, which is much simpler:
there are two arguments, the list and the numerical index, which counts from 1.
</p>
<p class="inwebparagraph">Note that property names, table names, and lists themselves are not storage
items as such &mdash; they are places where storage items are found. They are
all in the <code class="display"><span class="extract">VALUE</span></code> family.
</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>And here are some convenient creators. Variables:
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Lvalues::new_LOCAL_VARIABLE</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">local_variable</span><span class="plain"> *</span><span class="identifier">lvar</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">LOCAL_VARIABLE_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_constant_local_variable</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">lvar</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lvar</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad local variable"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">spec</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Lvalues::new_actual_NONLOCAL_VARIABLE</span><span class="plain">(</span><span class="reserved">nonlocal_variable</span><span class="plain"> *</span><span class="identifier">nlv</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">NONLOCAL_VARIABLE_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_constant_nonlocal_variable</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">nlv</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">nlv</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">spec</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Lvalues::new_LOCAL_VARIABLE is used in 4/am (<a href="4-am.html#SP38_1">&#167;38.1</a>), 10/teav (<a href="10-teav.html#SP10_1">&#167;10.1</a>, <a href="10-teav.html#SP15">&#167;15</a>), 12/is (<a href="12-is.html#SP6">&#167;6</a>), 12/dtd (<a href="12-dtd.html#SP23">&#167;23</a>), 12/cdp (<a href="12-cdp.html#SP5">&#167;5</a>), 15/ma (<a href="15-ma.html#SP13">&#167;13</a>), 25/cii (<a href="25-cii.html#SP1_2_1">&#167;1.2.1</a>, <a href="25-cii.html#SP6">&#167;6</a>), 25/cp (<a href="25-cp.html#SP5_3_5_3">&#167;5.3.5.3</a>).</p>
<p class="endnote">The function Lvalues::new_actual_NONLOCAL_VARIABLE is used in 5/nv (<a href="5-nv.html#SP7_3">&#167;7.3</a>), 9/tc (<a href="9-tc.html#SP5_4_2_2">&#167;5.4.2.2</a>), 9/pk (<a href="9-pk.html#SP2">&#167;2</a>), 10/teav (<a href="10-teav.html#SP16">&#167;16</a>), 11/sm (<a href="11-sm.html#SP15">&#167;15</a>), 12/ap (<a href="12-ap.html#SP9_5_2">&#167;9.5.2</a>), 25/ci (<a href="25-ci.html#SP3_2_3_3_1_1">&#167;3.2.3.3.1.1</a>, <a href="25-ci.html#SP3_2_3_4_1_1">&#167;3.2.3.4.1.1</a>, <a href="25-ci.html#SP3_2_3_3_1_2_1">&#167;3.2.3.3.1.2.1</a>).</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Table entries have their arguments filled in by the relevant routines in
"Meaning List Conversion":
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Lvalues::new_TABLE_ENTRY</span><span class="plain">(</span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">ParseTree::new_with_words</span><span class="plain">(</span><span class="constant">TABLE_ENTRY_NT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">spec</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Lvalues::new_TABLE_ENTRY is used in 10/teav (<a href="10-teav.html#SP21_1">&#167;21.1</a>, <a href="10-teav.html#SP21_2">&#167;21.2</a>, <a href="10-teav.html#SP21_3">&#167;21.3</a>, <a href="10-teav.html#SP21_4">&#167;21.4</a>, <a href="10-teav.html#SP21_5">&#167;21.5</a>).</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>List entries:
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Lvalues::new_LIST_ENTRY</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">owner</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">index</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">LIST_ENTRY_NT</span><span class="plain">);</span>
<span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="identifier">owner</span><span class="plain">;</span>
<span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">index</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">spec</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Lvalues::new_LIST_ENTRY is used in 10/teav (<a href="10-teav.html#SP10_3">&#167;10.3</a>).</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>Property values are constructed out of what's often only implied text:
for instance, "description" sometimes means "the description [of the
<code class="display"><span class="extract">self</span></code> object]". We give them a word range which is minimal such that it
must contain word ranges of both property and owner, if given. Thus
"carrying capacity of the trunk" will result from "carrying capacity"
and "trunk". This is not very scientific, perhaps, but it's done only to
make problem messages more readable.
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Lvalues::new_PROPERTY_VALUE</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">prop</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">owner</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">PROPERTY_VALUE_NT</span><span class="plain">);</span>
<span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="identifier">prop</span><span class="plain">;</span>
<span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">owner</span><span class="plain">;</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">,</span>
<span class="identifier">Wordings::union</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">), </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">owner</span><span class="plain">)));</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">spec</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Lvalues::new_PROPERTY_VALUE is used in 10/teav (<a href="10-teav.html#SP13">&#167;13</a>), 11/sm (<a href="11-sm.html#SP17_1">&#167;17.1</a>), 12/is (<a href="12-is.html#SP8">&#167;8</a>), 14/ds2 (<a href="14-ds2.html#SP19_3_1_1">&#167;19.3.1.1</a>), 15/ma (<a href="15-ma.html#SP13">&#167;13</a>).</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>On the other hand we sometimes want to refer to the property in abstract.
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Lvalues::underlying_property</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="constant">PROPERTY_VALUE_NT</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Rvalues::is_self_object_constant</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">spec</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"no underlying property"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Lvalues::underlying_property is used in 26/ts (<a href="26-ts.html#SP12">&#167;12</a>).</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Testing. </b></p>
<pre class="display">
<span class="identifier">node_type_t</span><span class="plain"> </span><span class="functiontext">Lvalues::get_storage_form</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTreeUsage::is_lvalue</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">UNKNOWN_NT</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Lvalues::get_storage_form is used in 5/nv (<a href="5-nv.html#SP25">&#167;25</a>), 9/ma (<a href="9-ma.html#SP3_3_39">&#167;3.3.39</a>, <a href="9-ma.html#SP3_3_41_3">&#167;3.3.41.3</a>), 10/varc (<a href="10-varc.html#SP13_4_1">&#167;13.4.1</a>), 11/bas (<a href="11-bas.html#SP19">&#167;19</a>), 11/sm (<a href="11-sm.html#SP4">&#167;4</a>), 12/ter (<a href="12-ter.html#SP8">&#167;8</a>), 12/dtd (<a href="12-dtd.html#SP10">&#167;10</a>), 14/sp (<a href="14-sp.html#SP7_5">&#167;7.5</a>), 14/ds2 (<a href="14-ds2.html#SP11_9_1_1_5_2">&#167;11.9.1.1.5.2</a>, <a href="14-ds2.html#SP11_9_1_1_8">&#167;11.9.1.1.8</a>), 22/ptd (<a href="22-ptd.html#SP18">&#167;18</a>), 25/cii (<a href="25-cii.html#SP3_5_4">&#167;3.5.4</a>).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>More specifically:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Lvalues::is_actual_NONLOCAL_VARIABLE</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="constant">NONLOCAL_VARIABLE_NT</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">nonlocal_variable</span><span class="plain"> *</span><span class="functiontext">Lvalues::get_nonlocal_variable_if_any</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="constant">NONLOCAL_VARIABLE_NT</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">ParseTree::get_constant_nonlocal_variable</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Lvalues::is_constant_NONLOCAL_VARIABLE</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain">) {</span>
<span class="reserved">nonlocal_variable</span><span class="plain"> *</span><span class="identifier">nlv</span><span class="plain"> = </span><span class="functiontext">Lvalues::get_nonlocal_variable_if_any</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nlv</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">NonlocalVariables::is_constant</span><span class="plain">(</span><span class="identifier">nlv</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Lvalues::is_actual_NONLOCAL_VARIABLE is used in 9/ma (<a href="9-ma.html#SP3_2">&#167;3.2</a>), 9/pd (<a href="9-pd.html#SP5_6">&#167;5.6</a>), 12/ter (<a href="12-ter.html#SP7">&#167;7</a>).</p>
<p class="endnote">The function Lvalues::get_nonlocal_variable_if_any is used in <a href="#SP9">&#167;9</a>, 5/nv (<a href="5-nv.html#SP23">&#167;23</a>), 10/cad (<a href="10-cad.html#SP3">&#167;3</a>, <a href="10-cad.html#SP4">&#167;4</a>), 12/ter (<a href="12-ter.html#SP8_3">&#167;8.3</a>), 19/tb (<a href="19-tb.html#SP24_5">&#167;24.5</a>), 25/cii (<a href="25-cii.html#SP3_1_1_2">&#167;3.1.1.2</a>, <a href="25-cii.html#SP3_5_4_2">&#167;3.5.4.2</a>).</p>
<p class="endnote">The function Lvalues::is_constant_NONLOCAL_VARIABLE is used in 9/tc (<a href="9-tc.html#SP4_4">&#167;4.4</a>), 18/lc (<a href="18-lc.html#SP8_1">&#167;8.1</a>).</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>Not all non-local variables are global &mdash; some have scope local to rulebooks,
actions and the like:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Lvalues::is_global_variable</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Lvalues::get_nonlocal_variable_if_any</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Lvalues::is_global_variable is used in 12/cad (<a href="12-cad.html#SP4">&#167;4</a>).</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. Pretty-printing. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Lvalues::write_out_in_English</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">)) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"a temporary named value"</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">NONLOCAL_VARIABLE_NT:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_kind_of_value</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">)) {</span>
<span class="identifier">Kinds::Textual::write_articled</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">ParseTree::get_kind_of_value</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">));</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" that varies"</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"a non-temporary variable"</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">TABLE_ENTRY_NT:</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"a table entry"</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">LIST_ENTRY_NT:</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"a list entry"</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">PROPERTY_VALUE_NT:</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTree::no_children</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">) == </span><span class="constant">2</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Rvalues::is_CONSTANT_construction</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">CON_property</span><span class="plain">))) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_property</span><span class="plain">(</span>
<span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"a property whose value is "</span><span class="plain">);</span>
<span class="identifier">Kinds::Textual::write_articled</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="functiontext">Properties::Valued::kind</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">));</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"a property belonging to something"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"a stored value"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Lvalues::write_out_in_English is used in 14/sp (<a href="14-sp.html#SP6">&#167;6</a>).</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>And the log.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Lvalues::log</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">)) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LOCAL_VARIABLE_NT:</span><span class="plain"> {</span>
<span class="reserved">local_variable</span><span class="plain"> *</span><span class="identifier">lvar</span><span class="plain"> = </span><span class="identifier">ParseTree::get_constant_local_variable</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"(%~L;$u)"</span><span class="plain">, </span><span class="identifier">lvar</span><span class="plain">, </span><span class="functiontext">LocalVariables::unproblematic_kind</span><span class="plain">(</span><span class="identifier">lvar</span><span class="plain">));</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NONLOCAL_VARIABLE_NT:</span><span class="plain"> {</span>
<span class="reserved">nonlocal_variable</span><span class="plain"> *</span><span class="identifier">q</span><span class="plain"> = </span><span class="identifier">ParseTree::get_constant_nonlocal_variable</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"($Z)"</span><span class="plain">, </span><span class="identifier">q</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Lvalues::log is used in 7/ptu (<a href="7-ptu.html#SP14_1">&#167;14.1</a>).</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. Compilation. </b></p>
<pre class="display">
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">Lvalues::to_kind</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">spec</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">"Rvalues::to_kind on NULL"</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">)) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LOCAL_VARIABLE_NT:</span><span class="plain"> </span>&lt;<span class="cwebmacro">Return the kind of a local variable</span> <span class="cwebmacronumber">12.1</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NONLOCAL_VARIABLE_NT:</span><span class="plain"> </span>&lt;<span class="cwebmacro">Return the kind of a non-local variable</span> <span class="cwebmacronumber">12.2</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TABLE_ENTRY_NT:</span><span class="plain"> </span>&lt;<span class="cwebmacro">Return the kind of a table entry</span> <span class="cwebmacronumber">12.3</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LIST_ENTRY_NT:</span><span class="plain"> </span>&lt;<span class="cwebmacro">Return the kind of a list entry</span> <span class="cwebmacronumber">12.4</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PROPERTY_VALUE_NT:</span><span class="plain"> </span>&lt;<span class="cwebmacro">Return the kind of a property value</span> <span class="cwebmacronumber">12.5</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K_value</span><span class="plain">; </span><span class="comment">a generic answer for storage of an unknown sort</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Lvalues::to_kind is used in 14/sp (<a href="14-sp.html#SP1">&#167;1</a>).</p>
<p class="inwebparagraph"><a id="SP12_1"></a><b>&#167;12.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Return the kind of a local variable</span> <span class="cwebmacronumber">12.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">local_variable</span><span class="plain"> *</span><span class="identifier">lvar</span><span class="plain"> = </span><span class="identifier">ParseTree::get_constant_local_variable</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lvar</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K_value</span><span class="plain">; </span><span class="comment">for "existing"</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">LocalVariables::unproblematic_kind</span><span class="plain">(</span><span class="identifier">lvar</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP12_2"></a><b>&#167;12.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Return the kind of a non-local variable</span> <span class="cwebmacronumber">12.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">nonlocal_variable</span><span class="plain"> *</span><span class="identifier">nlv</span><span class="plain"> = </span><span class="identifier">ParseTree::get_constant_nonlocal_variable</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">NonlocalVariables::kind</span><span class="plain">(</span><span class="identifier">nlv</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP12_3"></a><b>&#167;12.3. </b>In every form of table entry, argument 0 is the column, and the column
is enough to determine the kind:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Return the kind of a table entry</span> <span class="cwebmacronumber">12.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::no_children</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) { </span><span class="comment">i.e., always, for actual table entry specifications</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">fts</span><span class="plain"> = </span><span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</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">Rvalues::to_table_column</span><span class="plain">(</span><span class="identifier">fts</span><span class="plain">);</span>
<span class="reserved">return</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="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">; </span><span class="comment">can happen when scanning phrase arguments, which are generic</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP12_4"></a><b>&#167;12.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Return the kind of a list entry</span> <span class="cwebmacronumber">12.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::no_children</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">) == </span><span class="constant">2</span><span class="plain">) { </span><span class="comment">i.e., always, for actual list entry specifications</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K1</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::unary_construction_material</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">Kinds::unary_construction_material</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K_value</span><span class="plain">; </span><span class="comment">to help the type-checker produce better problem messages</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="comment">can happen when scanning phrase arguments, which are generic</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP12_5"></a><b>&#167;12.5. </b><code class="display">
&lt;<span class="cwebmacrodefn">Return the kind of a property value</span> <span class="cwebmacronumber">12.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::no_children</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">) == </span><span class="constant">2</span><span class="plain">) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_property</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prn</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Properties::is_either_or</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Properties::Valued::kind</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K_value</span><span class="plain">; </span><span class="comment">to help the type-checker produce better problem messages</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="comment">can happen when scanning phrase arguments, which are generic</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b></p>
<pre class="display">
<span class="reserved">local_variable</span><span class="plain"> *</span><span class="functiontext">Lvalues::get_local_variable_if_any</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="constant">LOCAL_VARIABLE_NT</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">ParseTree::get_constant_local_variable</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Lvalues::get_local_variable_if_any is used in 14/ds2 (<a href="14-ds2.html#SP11_9_1_1_5">&#167;11.9.1.1.5</a>), 25/cii (<a href="25-cii.html#SP3_5_2">&#167;3.5.2</a>, <a href="25-cii.html#SP3_5_3">&#167;3.5.3</a>, <a href="25-cii.html#SP3_5_4_2">&#167;3.5.4.2</a>, <a href="25-cii.html#SP3_7">&#167;3.7</a>).</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. Rvalue compilation. </b>We finally reach the compilation routine which produces an I6 expression
evaluating to the contents of the storage item specified.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Lvalues::compile</span><span class="plain">(</span><span class="identifier">value_holster</span><span class="plain"> *</span><span class="identifier">VH</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec_found</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">spec_found</span><span class="plain">)) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LOCAL_VARIABLE_NT:</span><span class="plain"> </span>&lt;<span class="cwebmacro">Compile a local variable specification</span> <span class="cwebmacronumber">14.1</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NONLOCAL_VARIABLE_NT:</span><span class="plain"> </span>&lt;<span class="cwebmacro">Compile a non-local variable specification</span> <span class="cwebmacronumber">14.2</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PROPERTY_VALUE_NT:</span><span class="plain"> </span>&lt;<span class="cwebmacro">Compile a property value specification</span> <span class="cwebmacronumber">14.3</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LIST_ENTRY_NT:</span><span class="plain"> </span>&lt;<span class="cwebmacro">Compile a list entry specification</span> <span class="cwebmacronumber">14.4</span>&gt;<span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TABLE_ENTRY_NT:</span><span class="plain"> </span>&lt;<span class="cwebmacro">Compile a table entry specification</span> <span class="cwebmacronumber">14.5</span>&gt;<span class="plain">;</span>
<span class="identifier">default:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Offender: $P\n"</span><span class="plain">, </span><span class="identifier">spec_found</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"unable to compile this STORAGE species"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Lvalues::compile is used in 14/cfs (<a href="14-cfs.html#SP7">&#167;7</a>).</p>
<p class="inwebparagraph"><a id="SP14_1"></a><b>&#167;14.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Compile a local variable specification</span> <span class="cwebmacronumber">14.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">local_variable</span><span class="plain"> *</span><span class="identifier">lvar</span><span class="plain"> = </span><span class="identifier">ParseTree::get_constant_local_variable</span><span class="plain">(</span><span class="identifier">spec_found</span><span class="plain">);</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">lvar_s</span><span class="plain"> = </span><span class="functiontext">LocalVariables::declare_this</span><span class="plain">(</span><span class="identifier">lvar</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="constant">8</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lvar</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">"Bad: %08x\n"</span><span class="plain">, </span><span class="identifier">spec_found</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Compiled never-specified LOCAL VARIABLE SP"</span><span class="plain">);</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">lvar_s</span><span class="plain">);</span>
<span class="reserved">return</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">Compile a non-local variable specification</span> <span class="cwebmacronumber">14.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">nonlocal_variable</span><span class="plain"> *</span><span class="identifier">nlv</span><span class="plain"> = </span><span class="identifier">ParseTree::get_constant_nonlocal_variable</span><span class="plain">(</span><span class="identifier">spec_found</span><span class="plain">);</span>
<span class="functiontext">NonlocalVariables::emit_lvalue</span><span class="plain">(</span><span class="identifier">nlv</span><span class="plain">);</span>
<span class="reserved">return</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_3"></a><b>&#167;14.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Compile a property value specification</span> <span class="cwebmacronumber">14.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::no_children</span><span class="plain">(</span><span class="identifier">spec_found</span><span class="plain">) != </span><span class="constant">2</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"malformed PROPERTY_OF SP"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</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">"PROPERTY_OF with null arg 0"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">next</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">"PROPERTY_OF with null arg 1"</span><span class="plain">);</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_property</span><span class="plain">(</span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prn</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">"PROPERTY_OF with null property"</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">prop_spec</span><span class="plain"> = </span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">owner</span><span class="plain"> = </span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">owner_kind</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">owner</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Reinterpret the "self" for what are unambiguously conditions of single things</span> <span class="cwebmacronumber">14.3.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">JUST_ROUTINE_CMODE</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="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">GPROPERTY_HL</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">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">TREAT_AS_LVALUE_CMODE</span><span class="plain">))) {</span>
<span class="identifier">Produce::inv_call_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">GPROPERTY_HL</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="plain">}</span>
<span class="functiontext">Kinds::RunTime::emit_weak_id_as_val</span><span class="plain">(</span><span class="identifier">owner_kind</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Emit the property's owner</span> <span class="cwebmacronumber">14.3.2</span>&gt;<span class="character">;</span>
<span class="functiontext">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">prop_spec</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (!(</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">TREAT_AS_LVALUE_CMODE</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="plain">}</span>
<span class="reserved">return</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_3_1"></a><b>&#167;14.3.1. </b>When Inform reads a text with a substitution like so:
</p>
<blockquote>
<p>if the signpost is visible, say "The signpost is still [signpost condition]."</p>
</blockquote>
<p class="inwebparagraph">...it has to decide which object is meant as the owner of the property
"signpost condition". Ordinarily, missing property owners are the self object,
which works nicely because <code class="display"><span class="extract">self</span></code> always has the right value at run-time when
we're, e.g., printing names of things. But what if, as here, there is no
formal indication of the owner? If we compile with the self object as owner,
the code may fail at run-time, complaining about using a property of nothing.
</p>
<p class="inwebparagraph">The author who wrote the source text above, though, felt able to write
"[signpost condition]" without any indication of its owner because there
could only be one possible owner: the signpost. And so that's the convention
we use here. We replace "self" as a default owner by the only possible owner.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Reinterpret the "self" for what are unambiguously conditions of single things</span> <span class="cwebmacronumber">14.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Rvalues::is_self_object_constant</span><span class="plain">(</span><span class="identifier">owner</span><span class="plain">)) {</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain"> = </span><span class="functiontext">Properties::Conditions::of_what</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">);</span>
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::as_object_instance</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">I</span><span class="plain">) </span><span class="identifier">owner</span><span class="plain"> = </span><span class="functiontext">Rvalues::from_instance</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP14_3">&#167;14.3</a>.</p>
<p class="inwebparagraph"><a id="SP14_3_2"></a><b>&#167;14.3.2. </b>During type-checking, a small number of <code class="display"><span class="extract">PROPERTY_VALUE_NT</span></code> SPs are marked
with the <code class="display"><span class="extract">record_as_self_ANNOT</span></code> flag. Such a SP compiles not only to code
performing the property lookup, but also setting the <code class="display"><span class="extract">self</span></code> I6 variable at
run-time to the object whose property is being looked up. The point of this
is to change the context used for implicit property lookups involved in the
actual property: e.g., if the value of this property turns out to be text
which contains a substitution referring vaguely to another property, then
we need to make sure that this other property is looked up from the same
object as produced the original text containing the substitution.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Emit the property's owner</span> <span class="cwebmacronumber">14.3.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">spec_found</span><span class="plain">, </span><span class="constant">record_as_self_ANNOT</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">STORE_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::ref_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="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">SELF_HL</span><span class="plain">));</span>
<span class="functiontext">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">owner</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="reserved">else</span><span class="plain"> {</span>
<span class="functiontext">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">owner</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP14_3">&#167;14.3</a>.</p>
<p class="inwebparagraph"><a id="SP14_4"></a><b>&#167;14.4. </b>List entries are blessedly simpler.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile a list entry specification</span> <span class="cwebmacronumber">14.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::no_children</span><span class="plain">(</span><span class="identifier">spec_found</span><span class="plain">) != </span><span class="constant">2</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"malformed LIST_OF SP"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</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">"LIST_OF with null arg 0"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">next</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">"LIST_OF with null arg 1"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">JUST_ROUTINE_CMODE</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="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">LIST_OF_TY_GETITEM_HL</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">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">TREAT_AS_LVALUE_CMODE</span><span class="plain">))) {</span>
<span class="identifier">Produce::inv_call_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">LIST_OF_TY_GETITEM_HL</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="plain">}</span>
<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="functiontext">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">);</span>
<span class="constant">END_COMPILATION_MODE</span><span class="plain">;</span>
<span class="functiontext">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (!(</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">TREAT_AS_LVALUE_CMODE</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="plain">}</span>
<span class="reserved">return</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_5"></a><b>&#167;14.5. </b>Table entries are simple too, but come in four variant forms:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile a table entry specification</span> <span class="cwebmacronumber">14.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">lookup</span><span class="plain"> = </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">TABLELOOKUPENTRY_HL</span><span class="plain">);</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">lookup_corr</span><span class="plain"> = </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">TABLELOOKUPCORR_HL</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="identifier">TABLE_EXISTENCE_CMODE_ISSBM</span><span class="plain">)) {</span>
<span class="identifier">lookup</span><span class="plain"> = </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">EXISTSTABLELOOKUPENTRY_HL</span><span class="plain">);</span>
<span class="identifier">lookup_corr</span><span class="plain"> = </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="constant">EXISTSTABLELOOKUPCORR_HL</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">ParseTree::no_children</span><span class="plain">(</span><span class="identifier">spec_found</span><span class="plain">)) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">1</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">JUST_ROUTINE_CMODE</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">lookup</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="functiontext">LocalVariables::used_stack_selection</span><span class="plain">();</span>
<span class="functiontext">LocalVariables::add_table_lookup</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (!(</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">TREAT_AS_LVALUE_CMODE</span><span class="plain">))) {</span>
<span class="identifier">Produce::inv_call_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">lookup</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="plain">}</span>
<span class="reserved">local_variable</span><span class="plain"> *</span><span class="identifier">ct_0_lv</span><span class="plain"> = </span><span class="functiontext">LocalVariables::by_name</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"ct_0"</span><span class="plain">);</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">ct_0_s</span><span class="plain"> = </span><span class="functiontext">LocalVariables::declare_this</span><span class="plain">(</span><span class="identifier">ct_0_lv</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="constant">8</span><span class="plain">);</span>
<span class="reserved">local_variable</span><span class="plain"> *</span><span class="identifier">ct_1_lv</span><span class="plain"> = </span><span class="functiontext">LocalVariables::by_name</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"ct_1"</span><span class="plain">);</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">ct_1_s</span><span class="plain"> = </span><span class="functiontext">LocalVariables::declare_this</span><span class="plain">(</span><span class="identifier">ct_1_lv</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="constant">8</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">ct_0_s</span><span class="plain">);</span>
<span class="functiontext">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</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">ct_1_s</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">BLANK_OUT_CMODE</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_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, </span><span class="constant">4</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (!(</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">TREAT_AS_LVALUE_CMODE</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="plain">}</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">2</span><span class="plain">: </span><span class="comment">never here except when printing debugging code</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_truth_state</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, </span><span class="constant">0</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="constant">3</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">JUST_ROUTINE_CMODE</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">lookup</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">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">TREAT_AS_LVALUE_CMODE</span><span class="plain">))) {</span>
<span class="identifier">Produce::inv_call_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">lookup</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="plain">}</span>
<span class="functiontext">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">);</span>
<span class="functiontext">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">);</span>
<span class="functiontext">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">BLANK_OUT_CMODE</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_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, </span><span class="constant">4</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (!(</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">TREAT_AS_LVALUE_CMODE</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="plain">}</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">4</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">JUST_ROUTINE_CMODE</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">lookup_corr</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">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">TREAT_AS_LVALUE_CMODE</span><span class="plain">))) {</span>
<span class="identifier">Produce::inv_call_iname</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">lookup_corr</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="plain">}</span>
<span class="functiontext">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">);</span>
<span class="functiontext">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">);</span>
<span class="functiontext">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">);</span>
<span class="functiontext">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">spec_found</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">BLANK_OUT_CMODE</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_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, </span><span class="constant">4</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (!(</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="constant">TREAT_AS_LVALUE_CMODE</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="plain">}</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"TABLE REFERENCE with bad number of args"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</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. Lvalue compilation. </b>To recap, if an assignment takes the form "now X is Y" then X is the lvalue,
Y is the rvalue. We only need to read Y, but we need to write X. Compilation
applied to a STORAGE item produces code suitable for reading it, i.e., suitable
for use in position Y &mdash; but not in general suitable for X.
</p>
<p class="inwebparagraph">To compile the lvalue form of a storage item, we use the following schemas.
These in effect take the rvalue form and modify it. There are three
versions, according to the nature of the data being moved; then two
variations for incrementing, and two for decrementing, where Y's value is
added to X's rather than replacing it. In these schemas, <code class="display"><span class="extract">*1</span></code> expands to
the storage item's rvalue form, and <code class="display"><span class="extract">*2</span></code> to the value being assigned to it.
</p>
<p class="inwebparagraph">At present no arithmetic values are stored in pointer values, but that might
change if arbitrary-precision integers are ever added to Inform, for instance.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">STORE_WORD_TO_WORD</span><span class="plain"> </span><span class="constant">1</span>
<span class="definitionkeyword">define</span> <span class="constant">STORE_WORD_TO_POINTER</span><span class="plain"> </span><span class="constant">2</span>
<span class="definitionkeyword">define</span> <span class="constant">STORE_POINTER_TO_POINTER</span><span class="plain"> </span><span class="constant">3</span>
<span class="definitionkeyword">define</span> <span class="constant">INCREASE_BY_WORD</span><span class="plain"> </span><span class="constant">4</span>
<span class="definitionkeyword">define</span> <span class="constant">INCREASE_BY_REAL</span><span class="plain"> </span><span class="constant">5</span>
<span class="definitionkeyword">define</span> <span class="constant">INCREASE_BY_POINTER</span><span class="plain"> </span><span class="constant">6</span>
<span class="definitionkeyword">define</span> <span class="constant">DECREASE_BY_WORD</span><span class="plain"> </span><span class="constant">7</span>
<span class="definitionkeyword">define</span> <span class="constant">DECREASE_BY_REAL</span><span class="plain"> </span><span class="constant">8</span>
<span class="definitionkeyword">define</span> <span class="constant">DECREASE_BY_POINTER</span><span class="plain"> </span><span class="constant">9</span>
</pre>
<pre class="display">
<span class="reserved">char</span><span class="plain"> *</span><span class="functiontext">Lvalues::storage_class_schema</span><span class="plain">(</span><span class="identifier">node_type_t</span><span class="plain"> </span><span class="identifier">storage_class</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">kind_of_store</span><span class="plain">,</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">reducing_modulo_1440</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">kind_of_store</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">STORE_WORD_TO_WORD:</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">storage_class</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*1 = *&lt;2"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NONLOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*1 = *&lt;2"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TABLE_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*$1(*%1,1,*&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PROPERTY_VALUE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-WriteGProperty(*|1,*&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LIST_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-WriteLIST_OF_TY_GetItem(*%1,*&lt;2)"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="string">""</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">STORE_WORD_TO_POINTER:</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">storage_class</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-BlkValueCast(*1, *#2, *!2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NONLOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-BlkValueCast(*1, *#2, *!2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TABLE_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-BlkValueCast(*$1(*%1, 5), *#2, *!2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PROPERTY_VALUE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-BlkValueCast(*+1, *#2, *!2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LIST_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-BlkValueCast(*1, *#2, *!2)"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="string">""</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">STORE_POINTER_TO_POINTER:</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">storage_class</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-BlkValueCopy(*1, *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NONLOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-BlkValueCopy(*1, *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TABLE_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-BlkValueCopy(*$1(*%1, 5), *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PROPERTY_VALUE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-BlkValueCopy(*+1, *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LIST_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-BlkValueCopy(*1, *&lt;2)"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="string">""</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">INCREASE_BY_WORD:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">reducing_modulo_1440</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">storage_class</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*1 = NUMBER_TY_to_TIME_TY(*1 + *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NONLOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*1 = NUMBER_TY_to_TIME_TY(*1 + *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TABLE_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*$1(*%1,1,NUMBER_TY_to_TIME_TY(*1 + *&lt;2))"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PROPERTY_VALUE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-WriteGProperty(*|1,NUMBER_TY_to_TIME_TY(*+1 + *&lt;2))"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LIST_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-WriteLIST_OF_TY_GetItem(*%1,NUMBER_TY_to_TIME_TY(*1 + *&lt;2))"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">storage_class</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*1 = *1 + *&lt;2"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NONLOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*1 = *1 + *&lt;2"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TABLE_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*$1(*%1, 1, *1 + *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PROPERTY_VALUE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-WriteGProperty(*|1,*+1 + *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LIST_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-WriteLIST_OF_TY_GetItem(*%1,*1 + *&lt;2)"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="string">""</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">INCREASE_BY_REAL:</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">storage_class</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*1 = REAL_NUMBER_TY_Plus(*1, *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NONLOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*1 = REAL_NUMBER_TY_Plus(*1, *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TABLE_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*$1(*%1,1,REAL_NUMBER_TY_Plus(*1, *&lt;2))"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PROPERTY_VALUE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-WriteGProperty(*|1,REAL_NUMBER_TY_Plus(*+1, *&lt;2))"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LIST_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-WriteLIST_OF_TY_GetItem(*%1,REAL_NUMBER_TY_Plus(*1, *&lt;2))"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="string">""</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">INCREASE_BY_POINTER:</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"pointer value increments not implemented"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="string">""</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">DECREASE_BY_WORD:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">reducing_modulo_1440</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">storage_class</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*1 = NUMBER_TY_to_TIME_TY(*1 - *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NONLOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*1 = NUMBER_TY_to_TIME_TY(*1 - *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TABLE_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*$1(*%1,1,NUMBER_TY_to_TIME_TY(*1 - *&lt;2))"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PROPERTY_VALUE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-WriteGProperty(*|1,NUMBER_TY_to_TIME_TY(*+1 - *&lt;2))"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LIST_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-WriteLIST_OF_TY_GetItem(*%1,NUMBER_TY_to_TIME_TY(*1 - *&lt;2))"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">storage_class</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*1 = *1 - *&lt;2"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NONLOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*1 = *1 - *&lt;2"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TABLE_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*$1(*%1,1,*1 - *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PROPERTY_VALUE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-WriteGProperty(*|1,*+1 - *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LIST_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-WriteLIST_OF_TY_GetItem(*%1,*1 - *&lt;2)"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="string">""</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">DECREASE_BY_REAL:</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">storage_class</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*1 = REAL_NUMBER_TY_Minus(*1, *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NONLOCAL_VARIABLE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*1 = REAL_NUMBER_TY_Minus(*1, *&lt;2)"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TABLE_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-*$1(*%1,1,REAL_NUMBER_TY_Minus(*1, *&lt;2))"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PROPERTY_VALUE_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-WriteGProperty(*|1,REAL_NUMBER_TY_Minus(*+1, *&lt;2))"</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LIST_ENTRY_NT:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"*=-WriteLIST_OF_TY_GetItem(*%1,REAL_NUMBER_TY_Minus(*1, *&lt;2))"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="string">""</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">DECREASE_BY_POINTER:</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"pointer value decrements not implemented"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="string">""</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="string">""</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Lvalues::storage_class_schema is used in <a href="#SP16">&#167;16</a>.</p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. </b>Here we supply advice on whether shallow or deep copies are needed. <code class="display"><span class="extract">inc</span></code> is
positive if we're incrementing what's there, negative if decrementing, zero
if simply setting.
</p>
<pre class="display">
<span class="reserved">char</span><span class="plain"> *</span><span class="functiontext">Lvalues::interpret_store</span><span class="plain">(</span><span class="identifier">node_type_t</span><span class="plain"> </span><span class="identifier">storage_class</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">left</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">right</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">inc</span><span class="plain">) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CHECKING</span><span class="plain">, </span><span class="string">"Interpreting assignment of kinds $u, $u\n"</span><span class="plain">, </span><span class="identifier">left</span><span class="plain">, </span><span class="identifier">right</span><span class="plain">);</span>
<span class="identifier">kind_constructor</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">R</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">left</span><span class="plain">) &amp;&amp; (</span><span class="identifier">right</span><span class="plain">)) { </span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">left</span><span class="plain">-&gt;</span><span class="element">construct</span><span class="plain">; </span><span class="identifier">R</span><span class="plain"> = </span><span class="identifier">right</span><span class="plain">-&gt;</span><span class="element">construct</span><span class="plain">; }</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">form</span><span class="plain"> = </span><span class="constant">STORE_WORD_TO_WORD</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">inc</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">form</span><span class="plain"> = </span><span class="constant">INCREASE_BY_WORD</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">left</span><span class="plain">)) </span><span class="identifier">form</span><span class="plain"> = </span><span class="constant">INCREASE_BY_REAL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">inc</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">form</span><span class="plain"> = </span><span class="constant">DECREASE_BY_WORD</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">left</span><span class="plain">)) </span><span class="identifier">form</span><span class="plain"> = </span><span class="constant">DECREASE_BY_REAL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Constructors::uses_pointer_values</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Constructors::allow_word_as_pointer</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)) {</span>
<span class="identifier">form</span><span class="plain"> = </span><span class="constant">STORE_WORD_TO_POINTER</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">inc</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">form</span><span class="plain"> = </span><span class="constant">INCREASE_BY_POINTER</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">inc</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">form</span><span class="plain"> = </span><span class="constant">DECREASE_BY_POINTER</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">form</span><span class="plain"> = </span><span class="constant">STORE_POINTER_TO_POINTER</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">inc</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">form</span><span class="plain"> = </span><span class="constant">INCREASE_BY_POINTER</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">inc</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">form</span><span class="plain"> = </span><span class="constant">DECREASE_BY_POINTER</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">reduce</span><span class="plain"> = </span><span class="identifier">FALSE</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="identifier">kind</span><span class="plain"> *</span><span class="identifier">KT</span><span class="plain"> = </span><span class="functiontext">PL::TimesOfDay::kind</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">KT</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">left</span><span class="plain">, </span><span class="identifier">KT</span><span class="plain">))) </span><span class="identifier">reduce</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Lvalues::storage_class_schema</span><span class="plain">(</span><span class="identifier">storage_class</span><span class="plain">, </span><span class="identifier">form</span><span class="plain">, </span><span class="identifier">reduce</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Lvalues::interpret_store is used in 12/ter (<a href="12-ter.html#SP8">&#167;8</a>), 25/cii (<a href="25-cii.html#SP3_5_4">&#167;3.5.4</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="14-rv.html">Back to 'RValues'</a></li><li><a href="14-cn.html">Continue with 'Conditions'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>