1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/core-module/11-bas.html
2019-04-22 15:42:10 +01:00

667 lines
83 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>11/pr</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 '11/bas' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">core</a></li><li><a href="index.html#11">Chapter 11: Predicate Calculus</a></li><li><b>Binding and Substitution</b></li></ul><p class="purpose">To substitute constants into propositions in place of variables, and to apply quantifiers to bind any unbound variables.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP4">&#167;4. Well-formedness</a></li><li><a href="#SP9">&#167;9. Renumbering</a></li><li><a href="#SP12">&#167;12. Binding</a></li><li><a href="#SP13">&#167;13. Substitution</a></li><li><a href="#SP16">&#167;16. A footnote on variable 0</a></li><li><a href="#SP19">&#167;19. Detect locals</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Definitions. </b></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>In any given proposition:
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(a) a variable is unused if it is never mentioned as, or in, any term,
and is not the variable of any quantifier;
</li></ul>
<ul class="items"><li>(b) a variable is bound if it appears as the variable of any <code class="display"><span class="extract">QUANTIFIER_ATOM</span></code>;
</li></ul>
<ul class="items"><li>(c) a variable is free if it is used but not bound.
</li></ul>
<p class="inwebparagraph">These are mutually exclusive (no two can be true at the same time), and in
any given proposition, each of the 26 variables is always either unused, bound
or free.
</p>
<p class="inwebparagraph">In this section we are concerned with three operations applied to propositions:
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(a) substitution means replacing each mention of a given variable
with a given constant: for instance, changing x to 3 throughout
("substituting x=3"). This has no effect if x is unused, and is
illegal if x is bound, since it could produce nonsense like "for all 3,
3 is odd".
</li></ul>
<ul class="items"><li>(b) binding means adding a new quantifier to a proposition, ranging
some variable v. If v were unused this would be unlikely to be sensible
(it would just make an inefficient way to test the size of the domain set),
whereas if v were already a bound variable then the result would be a
proposition which is no longer well-formed. So binding can only be done to
free variables.
</li></ul>
<ul class="items"><li>(c) renumbering means replacing each mention of a given variable v
with another variable w. Clearly w needs to be initially unused, or we
could accidentally change "v is greater than w" into "w is greater
than w". But provided w is unused, the proposition's truth or otherwise
remains unchanged.
</li></ul>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Propositions with free variables are vague, and we would like to get rid
of them. It can be very difficult to guess their values, just as subtle
human understanding seems to be needed to interpret pronouns like "it"
(see the enormous literature on the donkey anaphora problem in
linguistics). So we aim to translate excerpts of source text into just two
kinds of proposition:
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(a) an S-proposition which has no free variables &mdash; such as the result
of translating "The tree is in the Courtyard" or "Every door is open";
</li></ul>
<ul class="items"><li>(b) an SN-proposition in which only variable 0 (x) is free &mdash; such
as the result of translating "open containers which are in lighted rooms",
which comes out to a proposition φ(x) testing whether x is one.
</li></ul>
<p class="inwebparagraph">Whole English sentences or conditions make S-propositions, but
descriptions make SN-propositions. (By renumbering, any proposition with one
free variable can be made into an SN-proposition.)
</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Well-formedness. </b>It might seem logical to have a routine which takes a proposition φ
and a variable v and returns its status &mdash; unused, free or bound. But this
would be inefficient, since we want to work with all 26 at once, so instead
we take a pointer to an array of <code class="display"><span class="extract">int</span></code> which needs to have (at least, but
probably exactly) 26 entries, and on exit each entry is set to one of the
following. In the course of doing that, it's easy to test whether variables
are used properly &mdash; a bound variable should occur for the first time in
its quantification, and should not reoccur once the subexpression holding
the quantifier has finished. We set the <code class="display"><span class="extract">valid</span></code> flag if all is well.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">UNUSED_VST</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">FREE_VST</span><span class="plain"> 2</span>
<span class="definitionkeyword">define</span> <span class="constant">BOUND_VST</span><span class="plain"> 3</span>
</pre>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::determine_status</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="reserved">int</span><span class="plain"> *</span><span class="identifier">var_states</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">valid</span><span class="plain">) {</span>
<span class="identifier">TRAVERSE_VARIABLE</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">, </span><span class="identifier">unavailable</span><span class="plain">[26], </span><span class="identifier">blevel</span><span class="plain"> = 0, </span><span class="identifier">dummy</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">valid</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">valid</span><span class="plain"> = &amp;</span><span class="identifier">dummy</span><span class="plain">;</span>
<span class="plain">*</span><span class="identifier">valid</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;26; </span><span class="identifier">j</span><span class="plain">++) { </span><span class="identifier">var_states</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] = </span><span class="constant">UNUSED_VST</span><span class="plain">; </span><span class="identifier">unavailable</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] = 0; }</span>
<span class="identifier">TRAVERSE_PROPOSITION</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Calculus::Atoms::element_get_group</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;element</span><span class="plain">) == </span><span class="constant">OPEN_OPERATORS_GROUP</span><span class="plain">) </span><span class="identifier">blevel</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Calculus::Atoms::element_get_group</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;element</span><span class="plain">) == </span><span class="constant">CLOSE_OPERATORS_GROUP</span><span class="plain">) {</span>
<span class="identifier">blevel</span><span class="plain">--;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;26; </span><span class="identifier">j</span><span class="plain">++) </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">unavailable</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] &gt; </span><span class="identifier">blevel</span><span class="plain">) </span><span class="identifier">unavailable</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] = -1;</span>
<span class="plain">}</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;arity</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">v</span><span class="plain"> = </span><span class="functiontext">Calculus::Terms::variable_underlying</span><span class="plain">(&amp;(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;terms</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">v</span><span class="plain"> &gt;= 26) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"corrupted variable term"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">v</span><span class="plain"> &gt;= 0) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">unavailable</span><span class="plain">[</span><span class="identifier">v</span><span class="plain">] == -1) {</span>
<span class="plain">*</span><span class="identifier">valid</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$o invalid because of %c unavailable\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">pcalc_vars</span><span class="plain">[</span><span class="identifier">v</span><span class="plain">]);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;element</span><span class="plain"> == </span><span class="constant">QUANTIFIER_ATOM</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">var_states</span><span class="plain">[</span><span class="identifier">v</span><span class="plain">] != </span><span class="constant">UNUSED_VST</span><span class="plain">) {</span>
<span class="plain">*</span><span class="identifier">valid</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$D: $o invalid because of %c Q for F\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">pcalc_vars</span><span class="plain">[</span><span class="identifier">v</span><span class="plain">]);</span>
<span class="plain">}</span>
<span class="identifier">var_states</span><span class="plain">[</span><span class="identifier">v</span><span class="plain">] = </span><span class="constant">BOUND_VST</span><span class="plain">; </span><span class="identifier">unavailable</span><span class="plain">[</span><span class="identifier">v</span><span class="plain">] = </span><span class="identifier">blevel</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">var_states</span><span class="plain">[</span><span class="identifier">v</span><span class="plain">] == </span><span class="constant">UNUSED_VST</span><span class="plain">) </span><span class="identifier">var_states</span><span class="plain">[</span><span class="identifier">v</span><span class="plain">] = </span><span class="constant">FREE_VST</span><span class="plain">;</span>
<span class="plain">}</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 Calculus::Variables::determine_status is used in <a href="#SP5">&#167;5</a>, <a href="#SP6">&#167;6</a>, <a href="#SP7">&#167;7</a>, <a href="#SP8">&#167;8</a>, <a href="#SP11">&#167;11</a>, <a href="#SP12">&#167;12</a>, 11/tcp (<a href="11-tcp.html#SP6_12">&#167;6.12</a>), 12/ap (<a href="12-ap.html#SP9_4">&#167;9.4</a>), 12/cdp (<a href="12-cdp.html#SP2_1_5">&#167;2.1.5</a>).</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>With just a little wrapping, this gives us the test of well-formedness.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::is_well_formed</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="reserved">int</span><span class="plain"> </span><span class="identifier">status</span><span class="plain">, </span><span class="identifier">var_states</span><span class="plain">[26];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Calculus::Propositions::is_syntactically_valid</span><span class="plain">(</span><span class="identifier">prop</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="identifier">FALSE</span><span class="plain">;</span>
<span class="functiontext">Calculus::Variables::determine_status</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">, </span><span class="identifier">var_states</span><span class="plain">, &amp;</span><span class="identifier">status</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">status</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Variable usage malformed\</span><span class="plain">n</span><span class="string">"</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="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Variables::is_well_formed is used in <a href="#SP15">&#167;15</a>, 11/sc (<a href="11-sc.html#SP1_14">&#167;1.14</a>, <a href="11-sc.html#SP3_2">&#167;3.2</a>), 11/tcp (<a href="11-tcp.html#SP6">&#167;6</a>), 12/dtd (<a href="12-dtd.html#SP28">&#167;28</a>).</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>Occasionally we really do care only about one of the 26 variables:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::status</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="reserved">int</span><span class="plain"> </span><span class="identifier">v</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">var_states</span><span class="plain">[26];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">v</span><span class="plain"> == -1) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">UNUSED_VST</span><span class="plain">;</span>
<span class="functiontext">Calculus::Variables::determine_status</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">, </span><span class="identifier">var_states</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">var_states</span><span class="plain">[</span><span class="identifier">v</span><span class="plain">];</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Variables::status is used in <a href="#SP15_1">&#167;15.1</a>, 11/sc (<a href="11-sc.html#SP3_2">&#167;3.2</a>).</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>To distinguish sentences from descriptions, the following can be informative:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::number_free</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="reserved">int</span><span class="plain"> </span><span class="identifier">var_states</span><span class="plain">[26], </span><span class="identifier">j</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">;</span>
<span class="functiontext">Calculus::Variables::determine_status</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">, </span><span class="identifier">var_states</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">j</span><span class="plain">=0, </span><span class="identifier">c</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;26; </span><span class="identifier">j</span><span class="plain">++) </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">var_states</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] == </span><span class="constant">FREE_VST</span><span class="plain">) </span><span class="identifier">c</span><span class="plain">++;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">PREDICATE_CALCULUS_WORKINGS</span><span class="plain">, </span><span class="string">"There %s %d free variable%s in $D\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="plain">(</span><span class="identifier">c</span><span class="plain">==1)?</span><span class="string">"is"</span><span class="plain">:</span><span class="string">"are"</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">, (</span><span class="identifier">c</span><span class="plain">==1)?</span><span class="string">""</span><span class="plain">:</span><span class="string">"s"</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">c</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Variables::number_free is used in 9/ma (<a href="9-ma.html#SP3_3_39_5">&#167;3.3.39.5</a>), 11/sc (<a href="11-sc.html#SP1_14">&#167;1.14</a>, <a href="11-sc.html#SP3_2">&#167;3.2</a>), 12/dtd (<a href="12-dtd.html#SP28">&#167;28</a>), 14/ds (<a href="14-ds.html#SP6">&#167;6</a>), 14/ds2 (<a href="14-ds2.html#SP25">&#167;25</a>), 22/dptd (<a href="22-dptd.html#SP20_2_3">&#167;20.2.3</a>).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>While this gives us a new variable which can safely be added to an existing
proposition:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::find_unused</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="reserved">int</span><span class="plain"> </span><span class="identifier">var_states</span><span class="plain">[26], </span><span class="identifier">j</span><span class="plain">;</span>
<span class="functiontext">Calculus::Variables::determine_status</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">, </span><span class="identifier">var_states</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">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;26; </span><span class="identifier">j</span><span class="plain">++) </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">var_states</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] == </span><span class="constant">UNUSED_VST</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> 25; </span> <span class="comment">the best we can do: it avoids crashes, at least...</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Variables::find_unused is used in 11/sc (<a href="11-sc.html#SP3_7">&#167;3.7</a>), 11/sm (<a href="11-sm.html#SP3_2">&#167;3.2</a>, <a href="11-sm.html#SP4">&#167;4</a>).</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. Renumbering. </b>Another "vector operation" on variables: to renumber them throughout a
proposition according to a map array. If <code class="display"><span class="extract">renumber_map[j]</span></code> is -1, make
no change; otherwise each instance of variable j should be changed to
this new number.
</p>
<p class="inwebparagraph">Note that because <code class="display"><span class="extract">QUANTIFIER_ATOM</span></code>s store the variable being quantified
as a term, the following changes quantification variables as well as
predicate terms, which is as it should be.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::vars_map</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="reserved">int</span><span class="plain"> *</span><span class="identifier">renumber_map</span><span class="plain">, </span><span class="reserved">pcalc_term</span><span class="plain"> *</span><span class="identifier">preserving</span><span class="plain">) {</span>
<span class="identifier">TRAVERSE_VARIABLE</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">;</span>
<span class="identifier">TRAVERSE_PROPOSITION</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;arity</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++) {</span>
<span class="reserved">pcalc_term</span><span class="plain"> *</span><span class="identifier">pt</span><span class="plain"> = &amp;(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;terms</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]);</span>
<span class="functiontext">Calculus::Variables::term_map</span><span class="plain">(</span><span class="identifier">pt</span><span class="plain">, </span><span class="identifier">renumber_map</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">preserving</span><span class="plain">) </span><span class="functiontext">Calculus::Variables::term_map</span><span class="plain">(</span><span class="identifier">preserving</span><span class="plain">, </span><span class="identifier">renumber_map</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::term_map</span><span class="plain">(</span><span class="reserved">pcalc_term</span><span class="plain"> *</span><span class="identifier">pt</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">renumber_map</span><span class="plain">) {</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;function</span><span class="plain">) </span><span class="identifier">pt</span><span class="plain">=&amp;(</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;function</span><span class="plain">-</span><span class="element">&gt;fn_of</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">nv</span><span class="plain"> = </span><span class="identifier">renumber_map</span><span class="plain">[</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;variable</span><span class="plain">];</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;variable</span><span class="plain"> &gt;= 0) &amp;&amp; (</span><span class="identifier">nv</span><span class="plain"> &gt;= 0)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nv</span><span class="plain"> &gt;= 26) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"malformed renumbering map"</span><span class="plain">);</span>
<span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;variable</span><span class="plain"> = </span><span class="identifier">nv</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Variables::vars_map is used in <a href="#SP10">&#167;10</a>, <a href="#SP11">&#167;11</a>.</p>
<p class="endnote">The function Calculus::Variables::term_map appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>The following takes any proposition and edits it so that the variables
used are the lowest-numbered ones; moreover, variables are introduced
in numerical order &mdash; that is, the first mentioned will be x, then the
next introduced will be y, and so on.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::renumber</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="reserved">pcalc_term</span><span class="plain"> *</span><span class="identifier">preserving</span><span class="plain">) {</span>
<span class="identifier">TRAVERSE_VARIABLE</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">, </span><span class="identifier">renumber_map</span><span class="plain">[26];</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;26; </span><span class="identifier">j</span><span class="plain">++) </span><span class="identifier">renumber_map</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] = -1;</span>
<span class="identifier">k</span><span class="plain"> = 0;</span>
<span class="identifier">TRAVERSE_PROPOSITION</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;arity</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">v</span><span class="plain"> = </span><span class="functiontext">Calculus::Terms::variable_underlying</span><span class="plain">(&amp;(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;terms</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]));</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">v</span><span class="plain"> &gt;= 0) &amp;&amp; (</span><span class="identifier">renumber_map</span><span class="plain">[</span><span class="identifier">v</span><span class="plain">] == -1)) </span><span class="identifier">renumber_map</span><span class="plain">[</span><span class="identifier">v</span><span class="plain">] = </span><span class="identifier">k</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="functiontext">Calculus::Variables::vars_map</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">, </span><span class="identifier">renumber_map</span><span class="plain">, </span><span class="identifier">preserving</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Variables::renumber is used in <a href="#SP12">&#167;12</a>, 11/sc (<a href="11-sc.html#SP1_14">&#167;1.14</a>, <a href="11-sc.html#SP2">&#167;2</a>), 11/sm (<a href="11-sm.html#SP14">&#167;14</a>).</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>This more complicated routine renumbers bound variables in one proposition
in order to guarantee that none of them coincides with a variable used
in a second proposition. This is needed in order to take the conjunction of
two propositions, because "for all x, x is a door" and "there exists x
such that x is a container" mean different things by x; they can only
be combined in a single proposition if one of the x variables is changed
to, say, y.
</p>
<p class="inwebparagraph">The surprising thing here is the asymmetry. Why do we only renumber to avoid
clashes with bound variables in <code class="display"><span class="extract">prop</span></code> &mdash; why not free ones as well? The
answer is that we use a form of conjunction in Inform which assumes that a
free variable in φ has the same meaning as it does in ψ; thus in
conjoining "open" with "lockable" we assume that the same thing is meant
to be both open and lockable. If we renumbered to avoid clashes in free
variables, we would produce a proposition meaning that one unknown thing is
open, and another one lockable: that would have two free variables and be
much harder to interpret.
</p>
<p class="inwebparagraph">If we pass a <code class="display"><span class="extract">query</span></code> parameter which is a valid variable number, the routine
returns its new identity when renumbered.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::renumber_bound</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="reserved">pcalc_prop</span><span class="plain"> *</span><span class="identifier">not_to_overlap</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">query</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">prop_vstates</span><span class="plain">[26], </span><span class="identifier">nto_vstates</span><span class="plain">[26], </span><span class="identifier">renumber_map</span><span class="plain">[26];</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">, </span><span class="identifier">next_unused</span><span class="plain">;</span>
<span class="functiontext">Calculus::Variables::determine_status</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">, </span><span class="identifier">prop_vstates</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="functiontext">Calculus::Variables::determine_status</span><span class="plain">(</span><span class="identifier">not_to_overlap</span><span class="plain">, </span><span class="identifier">nto_vstates</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">j</span><span class="plain">=0, </span><span class="identifier">next_unused</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;26; </span><span class="identifier">j</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prop_vstates</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] == </span><span class="constant">BOUND_VST</span><span class="plain">) &amp;&amp; (</span><span class="identifier">nto_vstates</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] != </span><span class="constant">UNUSED_VST</span><span class="plain">)) {</span>
&lt;<span class="cwebmacro">Advance to the next variable not used in either proposition</span> <span class="cwebmacronumber">11.1</span>&gt;<span class="plain">;</span>
<span class="identifier">renumber_map</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] = </span><span class="identifier">next_unused</span><span class="plain">++;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">renumber_map</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] = -1;</span>
<span class="functiontext">Calculus::Variables::vars_map</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">, </span><span class="identifier">renumber_map</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">query</span><span class="plain"> == -1) </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">renumber_map</span><span class="plain">[</span><span class="identifier">query</span><span class="plain">] == -1) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">query</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">renumber_map</span><span class="plain">[</span><span class="identifier">query</span><span class="plain">];</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Variables::renumber_bound is used in 11/pr (<a href="11-pr.html#SP16">&#167;16</a>), 11/sc (<a href="11-sc.html#SP1_13">&#167;1.13</a>).</p>
<p class="inwebparagraph"><a id="SP11_1"></a><b>&#167;11.1. </b>Again, we fall back on variable 25 if we run out. (This can only happen if
the conjunction of the two propositions had 26 variables.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Advance to the next variable not used in either proposition</span> <span class="cwebmacronumber">11.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain">=</span><span class="identifier">next_unused</span><span class="plain">; (</span><span class="identifier">k</span><span class="plain">&lt;26) &amp;&amp;</span>
<span class="plain">(!((</span><span class="identifier">prop_vstates</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">] == </span><span class="constant">UNUSED_VST</span><span class="plain">) &amp;&amp; (</span><span class="identifier">nto_vstates</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">] == </span><span class="constant">UNUSED_VST</span><span class="plain">))); </span><span class="identifier">k</span><span class="plain">++) ;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain"> == 26) </span><span class="identifier">next_unused</span><span class="plain"> = 25; </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">next_unused</span><span class="plain"> = </span><span class="identifier">k</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. Binding. </b>In this routine, we look for free variables and preface the proposition
with ∃ quantifiers to bind them. For instance, open(x) becomes
∃ x: open(x).
</p>
<p class="inwebparagraph">We first renumber the proposition's variables from left to right, and
then quantify in reverse order &mdash; thus starting with the innermost free
variable and working outwards (i.e., towards the left). Since at each
stage we are prefacing the proposition, though, the net effect is that in
the final proposition the previously free variables are bound in increasing
order. For instance:
in(x, y) --&gt;
∃ y: in(x, y) --&gt;
∃ x: ∃ y: in(x, y)
</p>
<pre class="display">
<span class="reserved">pcalc_prop</span><span class="plain"> *</span><span class="functiontext">Calculus::Variables::bind_existential</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="reserved">pcalc_term</span><span class="plain"> *</span><span class="identifier">preserving</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">var_states</span><span class="plain">[26], </span><span class="identifier">j</span><span class="plain">;</span>
<span class="functiontext">Calculus::Variables::renumber</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">, </span><span class="identifier">preserving</span><span class="plain">);</span>
<span class="functiontext">Calculus::Variables::determine_status</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">, </span><span class="identifier">var_states</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">j</span><span class="plain">=25; </span><span class="identifier">j</span><span class="plain">&gt;=0; </span><span class="identifier">j</span><span class="plain">--)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">var_states</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] == </span><span class="constant">FREE_VST</span><span class="plain">)</span>
<span class="identifier">prop</span><span class="plain"> = </span><span class="functiontext">Calculus::Propositions::insert_atom</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="functiontext">Calculus::Atoms::QUANTIFIER_new</span><span class="plain">(</span><span class="identifier">exists_quantifier</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">, 0));</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">prop</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Variables::bind_existential is used in 11/sc (<a href="11-sc.html#SP1_3">&#167;1.3</a>, <a href="11-sc.html#SP1_9">&#167;1.9</a>, <a href="11-sc.html#SP3_7">&#167;3.7</a>).</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. Substitution. </b>In the following, we substitute term T (a constant or function) in place
of variable v in the given proposition. We begin with two utility routines
to substitute into the variable "underneath" a given term.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::substitute_v_in_term</span><span class="plain">(</span><span class="reserved">pcalc_term</span><span class="plain"> *</span><span class="identifier">pt</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">v</span><span class="plain">, </span><span class="reserved">pcalc_term</span><span class="plain"> *</span><span class="identifier">t</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;variable</span><span class="plain"> == </span><span class="identifier">v</span><span class="plain">) { *</span><span class="identifier">pt</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">TRUE</span><span class="plain">; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;function</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::substitute_v_in_term</span><span class="plain">(&amp;(</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;function</span><span class="plain">-</span><span class="element">&gt;fn_of</span><span class="plain">), </span><span class="identifier">v</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">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::substitute_nothing_in_term</span><span class="plain">(</span><span class="reserved">pcalc_term</span><span class="plain"> *</span><span class="identifier">pt</span><span class="plain">, </span><span class="reserved">pcalc_term</span><span class="plain"> *</span><span class="identifier">t</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;constant</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Rvalues::is_nothing_object_constant</span><span class="plain">(</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;constant</span><span class="plain">))) { *</span><span class="identifier">pt</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="reserved">if</span><span class="plain"> (</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;function</span><span class="plain">) </span><span class="functiontext">Calculus::Variables::substitute_nothing_in_term</span><span class="plain">(&amp;(</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;function</span><span class="plain">-</span><span class="element">&gt;fn_of</span><span class="plain">), </span><span class="identifier">t</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::substitute_term_in_term</span><span class="plain">(</span><span class="reserved">pcalc_term</span><span class="plain"> *</span><span class="identifier">pt</span><span class="plain">, </span><span class="reserved">pcalc_term</span><span class="plain"> *</span><span class="identifier">t</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;constant</span><span class="plain">) { *</span><span class="identifier">pt</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="reserved">if</span><span class="plain"> (</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;function</span><span class="plain">) </span><span class="functiontext">Calculus::Variables::substitute_term_in_term</span><span class="plain">(&amp;(</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;function</span><span class="plain">-</span><span class="element">&gt;fn_of</span><span class="plain">), </span><span class="identifier">t</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Variables::substitute_v_in_term is used in <a href="#SP15">&#167;15</a>.</p>
<p class="endnote">The function Calculus::Variables::substitute_nothing_in_term is used in 11/sm (<a href="11-sm.html#SP3_2">&#167;3.2</a>).</p>
<p class="endnote">The function Calculus::Variables::substitute_term_in_term is used in 11/sm (<a href="11-sm.html#SP4">&#167;4</a>).</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. </b>Now the main procedure. This is one of those deceptive problems where the
actual algorithm is obvious, but the circumstances when it can validly be
applied are less so.
</p>
<p class="inwebparagraph">The difficulty depends on the term T being substituted in for the variable
v. In general every term is a chain of functions with, right at the end,
either a constant or a variable. If a constant is underneath, there is no
problem at all. But if there is a variable underneath T &mdash; a VUT, as we
say below &mdash; then it's possible that the substitution introduces circularities
which would make it invalid. If that happens, we run into this:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">DISALLOW</span><span class="plain">(</span><span class="identifier">msg</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">verify_only</span><span class="plain">) { *</span><span class="identifier">allowed</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="identifier">prop</span><span class="plain">; }</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="identifier">msg</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. </b>So the routine is intended to be called twice: once to ask if the situation
looks viable, and once to perform the substitution itself.
</p>
<pre class="display">
<span class="reserved">pcalc_prop</span><span class="plain"> *</span><span class="functiontext">Calculus::Variables::substitute_term</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="reserved">int</span><span class="plain"> </span><span class="identifier">v</span><span class="plain">, </span><span class="reserved">pcalc_term</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">,</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">verify_only</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">allowed</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">changed</span><span class="plain">) {</span>
<span class="identifier">TRAVERSE_VARIABLE</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">verify_only</span><span class="plain">) *</span><span class="identifier">allowed</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">v</span><span class="plain">&lt;0) || (</span><span class="identifier">v</span><span class="plain">&gt;=26)) </span><span class="identifier">DISALLOW</span><span class="plain">(</span><span class="string">"variable substitution out of range"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Calculus::Variables::is_well_formed</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
<span class="identifier">DISALLOW</span><span class="plain">(</span><span class="string">"substituting into malformed prop"</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Make sure the substitution would not fail because of a circularity</span> <span class="cwebmacronumber">15.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">verify_only</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">prop</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">PREDICATE_CALCULUS_WORKINGS</span><span class="plain">, </span><span class="string">"Substituting %c = $0 in: $D\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">pcalc_vars</span><span class="plain">[</span><span class="identifier">v</span><span class="plain">], &amp;</span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">);</span>
<span class="identifier">TRAVERSE_PROPOSITION</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;arity</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Calculus::Variables::substitute_v_in_term</span><span class="plain">(&amp;(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;terms</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]), </span><span class="identifier">v</span><span class="plain">, &amp;</span><span class="identifier">t</span><span class="plain">))</span>
<span class="plain">*</span><span class="identifier">changed</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Calculus::Variables::is_well_formed</span><span class="plain">(</span><span class="identifier">prop</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">"substitution made malformed prop"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">prop</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Variables::substitute_term is used in <a href="#SP17">&#167;17</a>, 11/sm (<a href="11-sm.html#SP14">&#167;14</a>).</p>
<p class="inwebparagraph"><a id="SP15_1"></a><b>&#167;15.1. </b>The problem we might find, then, is that setting v=T will be circular
because T itself depends on v. There are two ways this can happen: first,
T might be directly a function of v itself, i.e., the VUT might be v;
second, T might be a function of some variable w which, by being quantified
after v, is allowed to depend on it, in some way that we can't determine.
(For examples of this, see "Simplifications".)
</p>
<p class="inwebparagraph">The general rule, then, is that T can contain only constants or variables
which are free within and after the scope of v. (If w is bound
outside the scope of v but after it, this means w didn't exist at the
time that v did, and the attempted substitution would produce a proposition
which isn't well-formed &mdash; w would occur before its quantifier.) We can
check this condition pretty easily, it turns out:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Make sure the substitution would not fail because of a circularity</span> <span class="cwebmacronumber">15.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">verify_only</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Calculus::Variables::status</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">, </span><span class="identifier">v</span><span class="plain">) == </span><span class="constant">BOUND_VST</span><span class="plain">))</span>
<span class="identifier">DISALLOW</span><span class="plain">(</span><span class="string">"substituting bound variable"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">vut</span><span class="plain"> = </span><span class="functiontext">Calculus::Terms::variable_underlying</span><span class="plain">(&amp;</span><span class="identifier">t</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">vut</span><span class="plain"> &gt;= 0) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">v_has_been_seen</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">v</span><span class="plain"> == </span><span class="identifier">vut</span><span class="plain">) </span><span class="identifier">DISALLOW</span><span class="plain">(</span><span class="string">"resubstituting same variable"</span><span class="plain">);</span>
<span class="identifier">TRAVERSE_PROPOSITION</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">v_has_been_seen</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;arity</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Calculus::Terms::variable_underlying</span><span class="plain">(&amp;(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;terms</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])) == </span><span class="identifier">v</span><span class="plain">)</span>
<span class="identifier">v_has_been_seen</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;element</span><span class="plain"> == </span><span class="constant">QUANTIFIER_ATOM</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;terms</span><span class="plain">[0]</span><span class="element">.variable</span><span class="plain"> == </span><span class="identifier">vut</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">v_has_been_seen</span><span class="plain">))</span>
<span class="identifier">DISALLOW</span><span class="plain">(</span><span class="string">"substituted value may be circular"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. A footnote on variable 0. </b>Because of the special status of x (variable 0) &mdash; the one allowed to be
free in SN-propositions &mdash; we sometimes need to know about it. The range
of a bound variable can be found by looking at its quantifier, but a free
variable can remain ambiguous. The presence of a <code class="display"><span class="extract">KIND</span></code> atom will explicitly
solve the problem for us; if we don't find one, though, we will simply have
to assume that the set of objects is the domain of x. (We return <code class="display"><span class="extract">NULL</span></code>
here, but that's the assumption which the caller will have to make.)
</p>
<pre class="display">
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">Calculus::Variables::kind_of_variable_0</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">TRAVERSE_VARIABLE</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="identifier">TRAVERSE_PROPOSITION</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;element</span><span class="plain"> == </span><span class="constant">KIND_ATOM</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;terms</span><span class="plain">[0]</span><span class="element">.variable</span><span class="plain"> == 0)) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;assert_kind</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="reserved">return</span><span class="plain"> </span><span class="identifier">K</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="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Variables::kind_of_variable_0 is used in 9/rpt (<a href="9-rpt.html#SP1">&#167;1</a>).</p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. </b>And a quick way to substitute it:
</p>
<pre class="display">
<span class="reserved">pcalc_prop</span><span class="plain"> *</span><span class="functiontext">Calculus::Variables::substitute_var_0_in</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="reserved">int</span><span class="plain"> </span><span class="identifier">bogus</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::substitute_term</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">, 0, </span><span class="functiontext">Calculus::Terms::new_constant</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">NULL</span><span class="plain">, &amp;</span><span class="identifier">bogus</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Variables::substitute_var_0_in is used in 12/dtd (<a href="12-dtd.html#SP7">&#167;7</a>, <a href="12-dtd.html#SP21">&#167;21</a>).</p>
<p class="inwebparagraph"><a id="SP18"></a><b>&#167;18. </b>If we are willing to work a little harder:
</p>
<pre class="display">
<span class="identifier">kind</span><span class="plain"> *</span><span class="functiontext">Calculus::Variables::infer_kind_of_variable_0</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">TRAVERSE_VARIABLE</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="identifier">TRAVERSE_PROPOSITION</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;element</span><span class="plain"> == </span><span class="constant">KIND_ATOM</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;terms</span><span class="plain">[0]</span><span class="element">.variable</span><span class="plain"> == 0)) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;assert_kind</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="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;element</span><span class="plain"> == </span><span class="constant">PREDICATE_ATOM</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;arity</span><span class="plain"> == 1) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;terms</span><span class="plain">[0]</span><span class="element">.variable</span><span class="plain"> == 0)) {</span>
<span class="identifier">adjective_usage</span><span class="plain"> *</span><span class="identifier">tr</span><span class="plain"> = </span><span class="identifier">RETRIEVE_POINTER_adjective_usage</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;predicate</span><span class="plain">);</span>
<span class="identifier">adjectival_phrase</span><span class="plain"> *</span><span class="identifier">aph</span><span class="plain"> = </span><span class="identifier">AdjectiveUsages::get_aph</span><span class="plain">(</span><span class="identifier">tr</span><span class="plain">);</span>
<span class="reserved">adjective_meaning</span><span class="plain"> *</span><span class="identifier">am</span><span class="plain"> = </span><span class="functiontext">Adjectives::Meanings::first_meaning</span><span class="plain">(</span><span class="identifier">aph</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">Adjectives::Meanings::get_domain</span><span class="plain">(</span><span class="identifier">am</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="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">;</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="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Variables::infer_kind_of_variable_0 is used in 14/rv (<a href="14-rv.html#SP18">&#167;18</a>), 14/ds (<a href="14-ds.html#SP3">&#167;3</a>, <a href="14-ds.html#SP6">&#167;6</a>).</p>
<p class="inwebparagraph"><a id="SP19"></a><b>&#167;19. Detect locals. </b>Properly speaking, this has nothing to do with variables,
but it solves a similar problem.
</p>
<p class="inwebparagraph">Here we search a proposition to look for any term involving a local variable.
This is used to verify past tense propositions, which cannot rely on local
values because their contents may have been wiped and reused many times
since the time with which the proposition is concerned.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::detect_locals</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">example</span><span class="plain">) {</span>
<span class="identifier">TRAVERSE_VARIABLE</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">locals_count</span><span class="plain"> = 0;</span>
<span class="identifier">TRAVERSE_PROPOSITION</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="identifier">prop</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">pl</span><span class="plain">-</span><span class="element">&gt;arity</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="identifier">locals_count</span><span class="plain"> =</span>
<span class="functiontext">Calculus::Variables::detect_local_in_term</span><span class="plain">(&amp;(</span><span class="identifier">pl</span><span class="plain">-</span><span class="element">&gt;terms</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]), </span><span class="identifier">locals_count</span><span class="plain">, </span><span class="identifier">example</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">locals_count</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::detect_local_in_term</span><span class="plain">(</span><span class="reserved">pcalc_term</span><span class="plain"> *</span><span class="identifier">pt</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">locals_count</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> **</span><span class="identifier">example</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;function</span><span class="plain">)</span>
<span class="identifier">locals_count</span><span class="plain"> += </span><span class="functiontext">Calculus::Variables::detect_local_in_term</span><span class="plain">(&amp;(</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;function</span><span class="plain">-</span><span class="element">&gt;fn_of</span><span class="plain">), </span><span class="identifier">locals_count</span><span class="plain">, </span><span class="identifier">example</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;constant</span><span class="plain">)</span>
<span class="identifier">locals_count</span><span class="plain"> += </span><span class="functiontext">Calculus::Variables::detect_local_in_spec</span><span class="plain">(</span><span class="identifier">pt</span><span class="plain">-</span><span class="element">&gt;constant</span><span class="plain">, </span><span class="identifier">locals_count</span><span class="plain">, </span><span class="identifier">example</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">locals_count</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Calculus::Variables::detect_local_in_spec</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">int</span><span class="plain"> </span><span class="identifier">locals_count</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> **</span><span class="identifier">example</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"> </span><span class="identifier">locals_count</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Lvalues::get_storage_form</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">if</span><span class="plain"> ((</span><span class="identifier">example</span><span class="plain">) &amp;&amp; (*</span><span class="identifier">example</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) *</span><span class="identifier">example</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">locals_count</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Lvalues::get_storage_form</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">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">if</span><span class="plain"> (</span><span class="functiontext">NonlocalVariables::is_global</span><span class="plain">(</span><span class="identifier">nlv</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">example</span><span class="plain">) &amp;&amp; (*</span><span class="identifier">example</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) *</span><span class="identifier">example</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">locals_count</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTreeUsage::is_phrasal</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">)) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain">;</span>
<span class="identifier">LOOP_THROUGH_INVOCATION_LIST</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">spec</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">param</span><span class="plain">;</span>
<span class="identifier">LOOP_THROUGH_TOKENS_PARSED_IN_INV</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">param</span><span class="plain">)</span>
<span class="identifier">locals_count</span><span class="plain"> +=</span>
<span class="functiontext">Calculus::Variables::detect_local_in_spec</span><span class="plain">(</span><span class="identifier">param</span><span class="plain">, </span><span class="identifier">locals_count</span><span class="plain">, </span><span class="identifier">example</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">spec</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">)</span>
<span class="identifier">locals_count</span><span class="plain"> +=</span>
<span class="functiontext">Calculus::Variables::detect_local_in_spec</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">locals_count</span><span class="plain">, </span><span class="identifier">example</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">locals_count</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Calculus::Variables::detect_locals is used in 10/varc (<a href="10-varc.html#SP13_3">&#167;13.3</a>), 12/dtd (<a href="12-dtd.html#SP13">&#167;13</a>).</p>
<p class="endnote">The function Calculus::Variables::detect_local_in_term appears nowhere else.</p>
<p class="endnote">The function Calculus::Variables::detect_local_in_spec appears nowhere else.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="11-pr.html">Back to 'Propositions'</a></li><li><a href="11-tc.html">Continue with 'Tree Conversions'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>