mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 18:14:21 +03:00
507 lines
57 KiB
HTML
507 lines
57 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>14/lv</title>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<meta http-equiv="Content-Language" content="en-gb">
|
|
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
</head>
|
|
<body>
|
|
|
|
<!--Weave of '14/cn' generated by 7-->
|
|
<ul class="crumbs"><li><a href="../webs.html">★</a></li><li><a href="index.html">core</a></li><li><a href="index.html#14">Chapter 14: Specifications</a></li><li><b>Conditions</b></li></ul><p class="purpose">Utility functions for condition nodes.</p>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. Creation</a></li><li><a href="#SP12">§12. Pretty-printing</a></li><li><a href="#SP14">§14. Specificity</a></li><li><a href="#SP16">§16. Compiling</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. Creation. </b>In Inform, conditions are not values, nor can values be used directly as
|
|
conditions: we therefore need to provide the logical operations of AND, OR,
|
|
and NOT structurally via the SP rather than implementing them as phrases
|
|
like the arithmetic operators. (Conditions and values are kept separate
|
|
even though it does complicate the type system because this provides
|
|
cleaner resolution of ambiguities, and I don't repent of this, because the
|
|
mixture of the two is sometimes unclear enough even in C: in natural
|
|
language, it tends to look very odd indeed.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">So <code class="display"><span class="extract">LOGICAL_AND_NT</span></code> and <code class="display"><span class="extract">LOGICAL_OR_NT</span></code> imitate the effect of logical
|
|
operators. They have two arguments which must themselves be CONDITIONs;
|
|
and similarly for the unary <code class="display"><span class="extract">LOGICAL_NOT_NT</span></code>. A unique feature of Inform
|
|
among programming languages is that it has a fourth: <code class="display"><span class="extract">LOGICAL_TENSE_NT</span></code>,
|
|
which expresses that a condition holds at a different time from the present.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§2. </b><code class="display"><span class="extract">TEST_PROPOSITION_NT</span></code> contains a predicate calculus sentence in the
|
|
<code class="display"><span class="extract">proposition</span></code> field of its SP: there are no arguments.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. </b><code class="display"><span class="extract">TEST_PHRASE_OPTION_NT</span></code> tests the use of a phrase option, and is the
|
|
actual SP parsed for the second usage of the word "thoroughly" in
|
|
the following example:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>To prognosticate, swiftly or thoroughly: ...; if thoroughly, ...</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">It uses the SP's data field to refer to the option in question: its value is the
|
|
bitmap value of the option, which will usually be 2^n where the option
|
|
is the n-th in the list for this phrase, counting upwards from 0.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. </b><code class="display"><span class="extract">TEST_VALUE_NT</span></code> tests the value beneath it in a condition context. For
|
|
truth state values, this does the obvious thing: <code class="display"><span class="extract">true</span></code> passes and
|
|
<code class="display"><span class="extract">false</span></code> fails. For stored actions or descriptions of actions, the current
|
|
action is tested to see if it matches.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">For constant descriptions, whatever is currently being discussed (the I6 value
|
|
<code class="display"><span class="extract">self</span></code>, generally speaking) is tested to see if it matches. But in order to
|
|
make definitions like this one work, we also need to treat descriptions as
|
|
values:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>To decide which number is total (P - property) of (D - description):</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">The way this is done is that type-checking a description (say, "closed doors
|
|
in lighted rooms") against the expectation of finding the kind constructor
|
|
"description of K" forces Inform to convert it to a constant of that type,
|
|
compiling it as an iterator routine in I6 capable of (among other things)
|
|
supplying the members in turn, and then using the address of this routine as
|
|
the actual I6 value. (Constants with the kind "description of K" cannot arise
|
|
in any other way.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§5. </b>Now some creator routines.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Conditions::new</span><span class="plain">(</span><span class="identifier">time_period</span><span class="plain"> *</span><span class="identifier">tp</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">TEST_PROPOSITION_NT</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Occurrence::get_tense</span><span class="plain">(</span><span class="identifier">tp</span><span class="plain">) != </span><span class="identifier">IS_TENSE</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tense improperly applied"</span><span class="plain">);</span>
|
|
<span class="functiontext">Conditions::attach_historic_requirement</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">tp</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 Conditions::new appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§6. </b>So, some more specific creators. The operators are easy:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Conditions::new_LOGICAL_AND</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec1</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec2</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">LOGICAL_AND_NT</span><span class="plain">);</span>
|
|
<span class="identifier">spec</span><span class="plain">-</span><span class="element">>down</span><span class="plain"> = </span><span class="identifier">spec1</span><span class="plain">;</span>
|
|
<span class="identifier">spec</span><span class="plain">-</span><span class="element">>down</span><span class="plain">-</span><span class="element">>next</span><span class="plain"> = </span><span class="identifier">spec2</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">Conditions::new_LOGICAL_OR</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec1</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec2</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">LOGICAL_OR_NT</span><span class="plain">);</span>
|
|
<span class="identifier">spec</span><span class="plain">-</span><span class="element">>down</span><span class="plain"> = </span><span class="identifier">spec1</span><span class="plain">;</span>
|
|
<span class="identifier">spec</span><span class="plain">-</span><span class="element">>down</span><span class="plain">-</span><span class="element">>next</span><span class="plain"> = </span><span class="identifier">spec2</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 Conditions::new_LOGICAL_AND is used in 10/cap (<a href="10-cap.html#SP2">§2</a>).</p>
|
|
|
|
<p class="endnote">The function Conditions::new_LOGICAL_OR is used in 10/cap (<a href="10-cap.html#SP2">§2</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§7. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Conditions::negate</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">cond</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">cond</span><span class="plain">, </span><span class="constant">LOGICAL_NOT_NT</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">cond</span><span class="plain">-</span><span class="element">>down</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">LOGICAL_NOT_NT</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">cond</span><span class="plain">));</span>
|
|
<span class="identifier">spec</span><span class="plain">-</span><span class="element">>down</span><span class="plain"> = </span><span class="identifier">cond</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 Conditions::negate is used in 10/varc (<a href="10-varc.html#SP13_3">§13.3</a>), 10/cap (<a href="10-cap.html#SP4">§4</a>, <a href="10-cap.html#SP5">§5</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8"></a><b>§8. </b>Testing propositions is also straightforward. There's no creator for
|
|
<code class="display"><span class="extract">NOW_PREPOSITION_VNT</span></code>, since this is formed only by coercion of one of these.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Conditions::new_TEST_PROPOSITION</span><span class="plain">(</span><span class="reserved">pcalc_prop</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">spec</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">TEST_PROPOSITION_NT</span><span class="plain">);</span>
|
|
<span class="identifier">ParseTree::set_proposition</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">prop</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 Conditions::new_TEST_PROPOSITION is used in 10/varc (<a href="10-varc.html#SP13_3">§13.3</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§9. </b>The option number here is actually 2^i, where 0<= i<15. This is just
|
|
exactly feasible, since the specification data field is 16 bits wide.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Conditions::new_TEST_PHRASE_OPTION</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">opt_num</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">TEST_PHRASE_OPTION_NT</span><span class="plain">);</span>
|
|
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="constant">phrase_option_ANNOT</span><span class="plain">, </span><span class="identifier">opt_num</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 Conditions::new_TEST_PHRASE_OPTION is used in 10/cap (<a href="10-cap.html#SP6">§6</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§10. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Conditions::new_TEST_ACTION</span><span class="plain">(</span><span class="identifier">action_pattern</span><span class="plain"> *</span><span class="identifier">ap</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">if</span><span class="plain"> (</span><span class="identifier">ap</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"null action pattern"</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">TEST_VALUE_NT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
|
|
<span class="identifier">spec</span><span class="plain">-</span><span class="element">>down</span><span class="plain"> = </span><span class="functiontext">Rvalues::from_action_pattern</span><span class="plain">(</span><span class="identifier">ap</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="element">>down</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>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="plain">#</span><span class="identifier">ifndef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Conditions::new_TEST_ACTION</span><span class="plain">(</span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">ap</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">internal_error</span><span class="plain">(</span><span class="string">"can't make test action without IF module"</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="plain">#</span><span class="identifier">endif</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Conditions::is_TEST_ACTION</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="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="constant">TEST_VALUE_NT</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Rvalues::to_action_pattern</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-</span><span class="element">>down</span><span class="plain">))) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">#</span><span class="identifier">endif</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="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Conditions::action_tested</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="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Conditions::is_TEST_ACTION</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"action improperly extracted"</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="element">>down</span><span class="plain">;</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="plain">#</span><span class="identifier">ifndef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"can't perform action_tested without IF module"</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="identifier">endif</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Conditions::new_TEST_ACTION is used in 10/teav (<a href="10-teav.html#SP23">§23</a>), 10/cap (<a href="10-cap.html#SP3">§3</a>, <a href="10-cap.html#SP7">§7</a>, <a href="10-cap.html#SP8_1">§8.1</a>), 25/pi (<a href="25-pi.html#SP5_1">§5.1</a>).</p>
|
|
|
|
<p class="endnote">The function Conditions::new_TEST_ACTION is used in 10/teav (<a href="10-teav.html#SP23">§23</a>), 10/cap (<a href="10-cap.html#SP3">§3</a>, <a href="10-cap.html#SP7">§7</a>, <a href="10-cap.html#SP8_1">§8.1</a>), 25/pi (<a href="25-pi.html#SP5_1">§5.1</a>).</p>
|
|
|
|
<p class="endnote">The function Conditions::is_TEST_ACTION is used in <a href="#SP16">§16</a>, 10/aots (<a href="10-aots.html#SP10">§10</a>), 11/sm (<a href="11-sm.html#SP16">§16</a>), 14/ds2 (<a href="14-ds2.html#SP19_5_1">§19.5.1</a>), 18/lc (<a href="18-lc.html#SP8">§8</a>).</p>
|
|
|
|
<p class="endnote">The function Conditions::action_tested is used in <a href="#SP16">§16</a>, 11/sm (<a href="11-sm.html#SP16">§16</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§11. </b>Since, in principle, any condition might also have a time period attached
|
|
to it, we need a follow-up routine to attach this as necessary to a newly
|
|
created condition:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Conditions::attach_tense</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">cond</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</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">NULL</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">cond</span><span class="plain">, </span><span class="constant">LOGICAL_TENSE_NT</span><span class="plain">)) {</span>
|
|
<span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">cond</span><span class="plain">;</span>
|
|
<span class="identifier">Occurrence::set_tense</span><span class="plain">(</span><span class="identifier">ParseTree::get_condition_tense</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">), </span><span class="identifier">t</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</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">LOGICAL_TENSE_NT</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">cond</span><span class="plain">));</span>
|
|
<span class="identifier">ParseTree::set_condition_tense</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">Occurrence::store</span><span class="plain">(</span><span class="identifier">Occurrence::new_tense_marker</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">)));</span>
|
|
<span class="identifier">spec</span><span class="plain">-</span><span class="element">>down</span><span class="plain"> = </span><span class="identifier">cond</span><span class="plain">;</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">Conditions::attach_historic_requirement</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">cond</span><span class="plain">, </span><span class="identifier">time_period</span><span class="plain"> *</span><span class="identifier">tp</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">cond</span><span class="plain">, </span><span class="identifier">AMBIGUITY_NT</span><span class="plain">)) {</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">amb</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">cond</span><span class="plain"> = </span><span class="identifier">cond</span><span class="plain">-</span><span class="element">>down</span><span class="plain">; </span><span class="identifier">cond</span><span class="plain">; </span><span class="identifier">cond</span><span class="plain"> = </span><span class="identifier">cond</span><span class="plain">-></span><span class="identifier">next_alternative</span><span class="plain">) {</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">reading</span><span class="plain"> = </span><span class="identifier">ParseTree::duplicate</span><span class="plain">(</span><span class="identifier">cond</span><span class="plain">);</span>
|
|
<span class="identifier">reading</span><span class="plain">-></span><span class="identifier">next_alternative</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">reading</span><span class="plain"> = </span><span class="functiontext">Conditions::attach_historic_requirement</span><span class="plain">(</span><span class="identifier">reading</span><span class="plain">, </span><span class="identifier">tp</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">reading</span><span class="plain">, </span><span class="constant">UNKNOWN_NT</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="identifier">amb</span><span class="plain"> = </span><span class="identifier">ParseTree::add_possible_reading</span><span class="plain">(</span><span class="identifier">amb</span><span class="plain">,</span>
|
|
<span class="identifier">reading</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">cond</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">amb</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain"> = </span><span class="identifier">IS_TENSE</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">NULL</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">cond</span><span class="plain">, </span><span class="constant">LOGICAL_TENSE_NT</span><span class="plain">)) {</span>
|
|
<span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">cond</span><span class="plain">;</span>
|
|
<span class="identifier">t</span><span class="plain"> = </span><span class="identifier">Occurrence::get_tense</span><span class="plain">(</span><span class="identifier">ParseTree::get_condition_tense</span><span class="plain">(</span><span class="identifier">cond</span><span class="plain">));</span>
|
|
<span class="plain">} </span><span class="reserved">else</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">LOGICAL_TENSE_NT</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">cond</span><span class="plain">));</span>
|
|
<span class="identifier">spec</span><span class="plain">-</span><span class="element">>down</span><span class="plain"> = </span><span class="identifier">cond</span><span class="plain">;</span>
|
|
<span class="identifier">t</span><span class="plain"> = </span><span class="identifier">IS_TENSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">ParseTree::set_condition_tense</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">tp</span><span class="plain">);</span>
|
|
<span class="identifier">Occurrence::set_tense</span><span class="plain">(</span><span class="identifier">ParseTree::get_condition_tense</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">), </span><span class="identifier">t</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 Conditions::attach_tense is used in 10/varc (<a href="10-varc.html#SP13_3">§13.3</a>), 10/cap (<a href="10-cap.html#SP8_1">§8.1</a>).</p>
|
|
|
|
<p class="endnote">The function Conditions::attach_historic_requirement is used in <a href="#SP5">§5</a>, 10/cap (<a href="10-cap.html#SP3">§3</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12"></a><b>§12. Pretty-printing. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Conditions::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">if</span><span class="plain"> (</span><span class="functiontext">Specifications::is_description</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">)) {</span>
|
|
<span class="functiontext">Descriptions::write_out_in_English</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">spec</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">ParseTree::is</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="constant">TEST_VALUE_NT</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="element">>down</span><span class="plain">, </span><span class="constant">CONSTANT_NT</span><span class="plain">))) {</span>
|
|
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-</span><span class="element">>down</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">) {</span>
|
|
<span class="identifier">Kinds::Textual::write_articled</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain">;</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 condition"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Conditions::write_out_in_English is used in 14/sp (<a href="14-sp.html#SP6">§6</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13"></a><b>§13. </b>And the log:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Conditions::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">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_condition_tense</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">))</span>
|
|
<span class="identifier">Occurrence::log</span><span class="plain">(</span><span class="identifier">DL</span><span class="plain">, </span><span class="identifier">ParseTree::get_condition_tense</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">TEST_PROPOSITION_NT</span><span class="plain">))</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"(test: $D)"</span><span class="plain">, </span><span class="functiontext">Specifications::to_proposition</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">Specifications::is_description</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">"(st: $D)"</span><span class="plain">, </span><span class="functiontext">Descriptions::to_proposition</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Conditions::log is used in 7/ptu (<a href="7-ptu.html#SP17_1">§17.1</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14"></a><b>§14. Specificity. </b>We will need a way of determining which of two conditions is more complex,
|
|
so that action-based rules with "when..." clauses tacked on can be sorted:
|
|
the following is used to compare such "when..." conditions.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">This is essentially a counting argument. Long conditions, with many clauses,
|
|
beat shorter ones.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Conditions::compare_specificity_of_CONDITIONs</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec1</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec2</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">spec1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) && (</span><span class="identifier">spec2</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">count1</span><span class="plain"> = </span><span class="functiontext">Conditions::count</span><span class="plain">(</span><span class="identifier">spec1</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">count2</span><span class="plain"> = </span><span class="functiontext">Conditions::count</span><span class="plain">(</span><span class="identifier">spec2</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">count1</span><span class="plain"> > </span><span class="identifier">count2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> 1;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">count1</span><span class="plain"> < </span><span class="identifier">count2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -1;</span>
|
|
<span class="reserved">return</span><span class="plain"> 0;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Conditions::compare_specificity_of_CONDITIONs appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15"></a><b>§15. </b>The only justification for the following complexity score is that it does
|
|
seem to accord well with what people expect. (There's clearly no theoretically
|
|
perfect way to define complexity of conditions in a language as complex as
|
|
Inform; this bit of scruffy, rather than neat, logic will have to do.)
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Conditions::count</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="reserved">return</span><span class="plain"> 0;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTreeUsage::is_condition</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> 1;</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="constant">LOGICAL_AND_NT</span><span class="plain">:</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Conditions::count</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-</span><span class="element">>down</span><span class="plain">)</span>
|
|
<span class="plain">+ </span><span class="functiontext">Conditions::count</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-</span><span class="element">>down</span><span class="plain">-</span><span class="element">>next</span><span class="plain">);</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">LOGICAL_OR_NT</span><span class="plain">:</span>
|
|
<span class="reserved">return</span><span class="plain"> -1;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">LOGICAL_NOT_NT</span><span class="plain">:</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Conditions::count</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-</span><span class="element">>down</span><span class="plain">);</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">LOGICAL_TENSE_NT</span><span class="plain">:</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Conditions::count</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-</span><span class="element">>down</span><span class="plain">);</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">TEST_PROPOSITION_NT</span><span class="plain">:</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Calculus::Propositions::length</span><span class="plain">(</span><span class="functiontext">Specifications::to_proposition</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="constant">TEST_PHRASE_OPTION_NT</span><span class="plain">:</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">TEST_VALUE_NT</span><span class="plain">:</span>
|
|
<span class="reserved">return</span><span class="plain"> 1;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> 0;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Conditions::count is used in <a href="#SP14">§14</a>, 21/ac (<a href="21-ac.html#SP9">§9</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16"></a><b>§16. Compiling. </b>We clear two oddball cases out of the way, and then for the most part we
|
|
delegate to potent routines elsewhere. Note that in some situations a valid
|
|
I6 condition must be enclosed in round brackets, and that a redundant pair
|
|
of brackets never does any harm; so we always compile one.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Conditions::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="constant">TEST_PROPOSITION_NT</span><span class="plain">:</span>
|
|
<span class="functiontext">Calculus::Deferrals::emit_test_of_proposition</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">,</span>
|
|
<span class="functiontext">Specifications::to_proposition</span><span class="plain">(</span><span class="identifier">spec_found</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">LOGICAL_TENSE_NT</span><span class="plain">:</span>
|
|
<span class="functiontext">Chronology::compile_past_tense_condition</span><span class="plain">(</span><span class="identifier">VH</span><span class="plain">, </span><span class="identifier">spec_found</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">LOGICAL_NOT_NT</span><span class="plain">: </span><<span class="cwebmacro">Compile a logical negation</span> <span class="cwebmacronumber">16.1</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">LOGICAL_AND_NT</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="constant">LOGICAL_OR_NT</span><span class="plain">: </span><<span class="cwebmacro">Compile a logical operator</span> <span class="cwebmacronumber">16.2</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">TEST_VALUE_NT</span><span class="plain">: {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Conditions::is_TEST_ACTION</span><span class="plain">(</span><span class="identifier">spec_found</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">action_pattern</span><span class="plain"> *</span><span class="identifier">ap</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_action_pattern</span><span class="plain">(</span>
|
|
<span class="functiontext">Conditions::action_tested</span><span class="plain">(</span><span class="identifier">spec_found</span><span class="plain">));</span>
|
|
<span class="identifier">PL::Actions::Patterns::compile_pattern_match</span><span class="plain">(</span><span class="identifier">VH</span><span class="plain">, *</span><span class="identifier">ap</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Specifications::is_description</span><span class="plain">(</span><span class="identifier">spec_found</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">, 1); </span> <span class="comment">purely for problem recovery</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">spec_found</span><span class="plain">-</span><span class="element">>down</span><span class="plain">);</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="constant">TEST_PHRASE_OPTION_NT</span><span class="plain">: </span><<span class="cwebmacro">Compile a phrase option test</span> <span class="cwebmacronumber">16.3</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 Conditions::compile is used in 14/cfs (<a href="14-cfs.html#SP7">§7</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16_1"></a><b>§16.1. </b>An easy case, running straight out to I6 operators:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Compile a logical negation</span> <span class="cwebmacronumber">16.1</span>> =
|
|
</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">) != 1)</span>
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Compiled malformed LOGICAL_NOT_NT"</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">NOT_BIP</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="functiontext">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">-</span><span class="element">>down</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>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP16">§16</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16_2"></a><b>§16.2. </b>An easy case, running straight out to I6 operators:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Compile a logical operator</span> <span class="cwebmacronumber">16.2</span>> =
|
|
</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">) != 2)</span>
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Compiled malformed logical operator"</span><span class="plain">);</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">left_operand</span><span class="plain"> = </span><span class="identifier">spec_found</span><span class="plain">-</span><span class="element">>down</span><span class="plain">;</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">right_operand</span><span class="plain"> = </span><span class="identifier">spec_found</span><span class="plain">-</span><span class="element">>down</span><span class="plain">-</span><span class="element">>next</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">left_operand</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">right_operand</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">"Compiled CONDITION/AND with LHS operands"</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_found</span><span class="plain">, </span><span class="constant">LOGICAL_AND_NT</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">AND_BIP</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_found</span><span class="plain">, </span><span class="constant">LOGICAL_OR_NT</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">OR_BIP</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">());</span>
|
|
<span class="functiontext">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">left_operand</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">right_operand</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>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP16">§16</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16_3"></a><b>§16.3. </b>Phrase options are stored as bits in a 16-bit map, so that each individual
|
|
option is a power of two from 2^0 to 2^15. We test if this is valid by
|
|
performing logical-and against the I6 local variable <code class="display"><span class="extract">phrase_options</span></code>, which
|
|
exists if and only if the enclosing I6 routine takes phrase options. The
|
|
type-checker won't allow these specifications to be compiled anywhere else.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Compile a phrase option test</span> <span class="cwebmacronumber">16.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">BITWISEAND_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="reserved">local_variable</span><span class="plain"> *</span><span class="identifier">po</span><span class="plain"> = </span><span class="functiontext">LocalVariables::phrase_options</span><span class="plain">();</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">po</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"no phrase options exist in this frame"</span><span class="plain">);</span>
|
|
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">po_s</span><span class="plain"> = </span><span class="functiontext">LocalVariables::declare_this</span><span class="plain">(</span><span class="identifier">po</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, 8);</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">po_s</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="identifier">inter_t</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">phrase_option_ANNOT</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>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP16">§16</a>.</p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="14-lv.html">Back to 'Lvalues'</a></li><li><a href="14-ds.html">Continue with 'Descriptions'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
</body>
|
|
</html>
|
|
|