1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 10:04:21 +03:00
inform7/docs/core-module/20-eq.html
2020-04-15 23:49:59 +01:00

2970 lines
392 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Equations</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-src/Figures/Inform.png" height=72">
</a></h1>
<ul><li><a href="../compiler.html">compiler tools</a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul><h2>Compiler Webs</h2><ul>
<li><a href="../inbuild/index.html">inbuild</a></li>
<li><a href="../inform7/index.html">inform7</a></li>
<li><a href="../inter/index.html">inter</a></li>
</ul><h2>Inbuild Modules</h2><ul>
<li><a href="../supervisor-module/index.html">supervisor</a></li>
</ul><h2>Inform7 Modules</h2><ul>
<li><a href="index.html"><span class="selectedlink">core</span></a></li>
<li><a href="../inflections-module/index.html">inflections</a></li>
<li><a href="../linguistics-module/index.html">linguistics</a></li>
<li><a href="../kinds-module/index.html">kinds</a></li>
<li><a href="../if-module/index.html">if</a></li>
<li><a href="../multimedia-module/index.html">multimedia</a></li>
<li><a href="../problems-module/index.html">problems</a></li>
<li><a href="../index-module/index.html">index</a></li>
</ul><h2>Inter Modules</h2><ul>
<li><a href="../bytecode-module/index.html">bytecode</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../codegen-module/index.html">codegen</a></li>
</ul><h2>Shared Modules</h2><ul>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../syntax-module/index.html">syntax</a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../html-module/index.html">html</a></li>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Equations' generated by 7-->
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../compiler.html">Inform7 Modules</a></li><li><a href="index.html">core</a></li><li><a href="index.html#20">Chapter 20: Equations</a></li><li><b>Equations</b></li></ul><p class="purpose">To manage and compile equations, which relate numerical quantities.</p>
<ul class="toc"><li><a href="20-eq.html#SP1">&#167;1. Definitions</a></li><li><a href="20-eq.html#SP9">&#167;9. Traversing for equations</a></li><li><a href="20-eq.html#SP12">&#167;12. Parsing equations</a></li><li><a href="20-eq.html#SP14">&#167;14. Declaring symbols</a></li><li><a href="20-eq.html#SP25">&#167;25. Equation nodes</a></li><li><a href="20-eq.html#SP28">&#167;28. Tokenising equations</a></li><li><a href="20-eq.html#SP31">&#167;31. The shift-reduce parser</a></li><li><a href="20-eq.html#SP39">&#167;39. Typechecking equations</a></li><li><a href="20-eq.html#SP42">&#167;42. Flotation</a></li><li><a href="20-eq.html#SP43">&#167;43. Compiling</a></li><li><a href="20-eq.html#SP45">&#167;45. Solving</a></li><li><a href="20-eq.html#SP50">&#167;50. Rearrangement</a></li><li><a href="20-eq.html#SP52">&#167;52. Internal test case</a></li><li><a href="20-eq.html#SP53">&#167;53. Indexing and logging</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>As with tables, equations are detected early on in Inform's run but not
parsed for their contents until later, so we store several word ranges.
Also as with tables, each can have a number, a name or both.
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">equation</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">equation_text</span><span class="plain">; </span><span class="comment"> the text of the actual equation</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">equation_no_text</span><span class="plain">; </span><span class="comment"> the equation number (if any)</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">equation_name_text</span><span class="plain">; </span><span class="comment"> the equation name (if any)</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">where_text</span><span class="plain">; </span><span class="comment"> declaration of symbols</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">usage_text</span><span class="plain">; </span><span class="comment"> usage notes</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">equation_created_at</span><span class="plain">; </span><span class="comment"> where created in source</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">examined_already</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">parsed_equation</span><span class="plain">; </span><span class="comment"> and the equation itself (when eventually parsed)</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">eqn_iname</span><span class="plain">; </span><span class="comment"> used at run-time to identify this</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">symbol_list</span><span class="plain">; </span><span class="comment"> the symbols used</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">equation</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure equation is accessed in 2/si and here.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Each equation is allowed to use one or more symbols. Some may correspond
to local variables in surrounding code from time to time, but others will
be constants, and it's better to think of these as placeholders in the
syntax of the equation, not as storage objects like variables. For instance,
in
$$ E = mc^2 $$
we have three symbols: \(E\), \(m\) and \(c\). (The 2 does not count.) There
might be symbols called \(m\) in any number of other equations; if so each
instance has its own <code class="display"><span class="extract">equation_symbol</span></code> structure.
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">equation_symbol</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">name</span><span class="plain">; </span><span class="comment"> always just one word, in fact</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">var_kind</span><span class="plain">; </span><span class="comment"> if a variable &mdash; must be quasinumerical</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">function_notated</span><span class="plain">; </span><span class="comment"> if a phrase QN to QN</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">var_const</span><span class="plain">; </span><span class="comment"> if a symbol for a constant value</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">temp_constant</span><span class="plain">; </span><span class="comment"> is this constant a substitution for one usage only?</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">next</span><span class="plain">; </span><span class="comment"> in the list belonging to the equation</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">local_variable</span><span class="plain"> *</span><span class="identifier">local_map</span><span class="plain">; </span><span class="comment"> when being solved in a given stack frame</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">promote_local_to_real</span><span class="plain">; </span><span class="comment"> from integer, if necessary</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">equation_symbol</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure equation_symbol is accessed in 2/sq, 2/si, 3/pd, 5/lp, 5/ut, 5/un, 5/ins, 5/nv, 6/rlt, 6/nv, 7/ns, 7/oaf, 7/rs, 8/ef, 9/tfa, 9/tbath, 9/rpt, 9/tc, 9/ma, 9/pk, 9/rk, 9/ass, 9/imp, 9/pd, 10/teav, 10/cap, 11/ap, 11/pr, 11/bas, 11/tc, 11/sm, 12/dtd, 12/cdp, 14/rv, 14/lv, 14/cn, 14/ds, 14/ds2, 15/pr, 15/ep, 15/vp, 15/cp, 15/spr, 16/is, 16/in, 16/cmw, 17/rs, 19/tc, 19/tb, 19/rsft, 19/tod, 21/rl, 21/rl2, 21/fao, 21/rps, 21/sv, 21/ac, 22/ph, 22/pu, 22/dptd, 22/po, 22/pav, 22/tp, 22/tp2, 23/ad, 24/lv, 24/sf, 25/in, 25/pi, 25/cii, 25/cp, 26/uo, 26/tti, 26/pc, 26/ts, 27/cm and here.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>In addition, there are some standing symbols used by all equations: the
constant "pi", for example. They're stored in this linked list:
</p>
<pre class="display">
<span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">standard_equation_symbols</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>When parsed, the equation is stored as a tree of <code class="display"><span class="extract">equation_node</span></code> structures.
As usual, the leaves represent symbols or else constants not given symbol
status (such as the 2 in \(E = mc^2\)); the non-leaf nodes represent operations,
identified with the same codes as used in "Dimensions". Note
that the equals sign <code class="display"><span class="extract">=</span></code> is itself considered an operation here.Thus:
</p>
<pre class="display">
<span class="plain">OPERATION_EQN =</span>
<span class="plain">SYMBOL_EQN E</span>
<span class="plain">OPERATION_EQN *</span>
<span class="plain">SYMBOL_EQN m</span>
<span class="plain">OPERATION_EQN ^</span>
<span class="plain">SYMBOL_EQN c</span>
<span class="plain">CONSTANT_EQN 2</span>
</pre>
<p class="inwebparagraph"></p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">CONSTANT_EQN</span><span class="plain"> </span><span class="constant">1</span><span class="plain"> </span><span class="comment"> a leaf, representing a quasinumerical constant not given a symbol</span>
<span class="definitionkeyword">define</span> <span class="constant">SYMBOL_EQN</span><span class="plain"> </span><span class="constant">2</span><span class="plain"> </span><span class="comment"> a leaf, representing a symbol</span>
<span class="definitionkeyword">define</span> <span class="constant">OPERATION_EQN</span><span class="plain"> </span><span class="constant">3</span><span class="plain"> </span><span class="comment"> a non-leaf, representing an operation</span>
</pre>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>However, because of the algorithm used to parse the text of the equation into
this tree, we also need certain other kinds of node to exist during parsing
only. They are syntactic gimmicks, and are forbidden in the final tree.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">OPEN_BRACKET_EQN</span><span class="plain"> </span><span class="constant">4</span>
<span class="definitionkeyword">define</span> <span class="constant">CLOSE_BRACKET_EQN</span><span class="plain"> </span><span class="constant">5</span>
<span class="definitionkeyword">define</span> <span class="constant">END_EQN</span><span class="plain"> </span><span class="constant">6</span><span class="plain"> </span><span class="comment"> the end (left or right edge, really) of the equation</span>
</pre>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>Another temporary trick in parsing is to distinguish between explicit
multiplication, where the source text uses an asterisk <code class="display"><span class="extract">*</span></code>, and implicit,
as between \(m\) and \(c^2\) in \(E = mc^2\). We distinguish these so that they
can bind with different tightnesses, but both are represented just as
<code class="display"><span class="extract">TIMES_OPERATION</span></code> nodes in the eventual tree.
</p>
<p class="inwebparagraph">Implicit function application is similarly used to represent the unwritten
operation in <code class="display"><span class="extract">log pi</span></code> &mdash; where the function <code class="display"><span class="extract">log</span></code> is being applied to the
value <code class="display"><span class="extract">pi</span></code>.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">IMPLICIT_TIMES_OPERATION</span><span class="plain"> </span><span class="constant">100</span>
<span class="definitionkeyword">define</span> <span class="constant">IMPLICIT_APPLICATION_OPERATION</span><span class="plain"> </span><span class="constant">101</span>
</pre>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>And now the equation node structure:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_EQN_ARITY</span><span class="plain"> </span><span class="constant">2</span><span class="plain"> </span><span class="comment"> at present all operations are at most binary</span>
</pre>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">equation_node</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">eqn_type</span><span class="plain">; </span><span class="comment"> one of the <code class="display"><span class="extract">*_EQN</span></code> values</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">eqn_operation</span><span class="plain">; </span><span class="comment"> one of the <code class="display"><span class="extract">*_OPERATION</span></code> values (see "Dimensions.w")</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">enode_arity</span><span class="plain">; </span><span class="comment"> 0 for a leaf</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">enode_operands</span><span class="plain">[</span><span class="constant">MAX_EQN_ARITY</span><span class="plain">]; </span><span class="comment"> the operands</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">leaf_constant</span><span class="plain">; </span><span class="comment"> if e.g. "21"</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">leaf_symbol</span><span class="plain">; </span><span class="comment"> if e.g. "G"</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">generalised_kind</span><span class="plain"> </span><span class="identifier">gK_before</span><span class="plain">; </span><span class="comment"> result of the node as it is</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">generalised_kind</span><span class="plain"> </span><span class="identifier">gK_after</span><span class="plain">; </span><span class="comment"> result of the node as we need it to be</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">enode_promotion</span><span class="plain">; </span><span class="comment"> promote this from an integer to a real number?</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rational_n</span><span class="plain">; </span><span class="comment"> represents the rational number <code class="display"><span class="extract">n/m</span></code>...</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rational_m</span><span class="plain">; </span><span class="comment"> ...unless <code class="display"><span class="extract">m</span></code> is zero</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">equation_node</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure equation_node is accessed in 13/ca and here.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. Traversing for equations. </b>Early in Inform's run, the following takes place:
</p>
<pre class="display">
<span class="reserved">sentence_handler</span><span class="plain"> </span><span class="identifier">EQUATION_SH_handler</span><span class="plain"> = { </span><span class="identifier">EQUATION_NT</span><span class="plain">, -1, </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain"> };</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::traverse_to_create<button class="popup" onclick="togglePopup('usagePopup1436')">...<span class="popuptext" id="usagePopup1436">Usage of <b>Equations::traverse_to_create</b>:<br>How To Compile - <a href="1-htc.html#SP2_3">&#167;2.3</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">ParseTree::traverse</span><span class="plain">(</span><span class="functiontext"><a href="1-wtc.html#SP5">Task::syntax_tree</a></span><span class="plain">(), </span><span class="functiontext"><a href="20-eq.html#SP9">Equations::visit_to_create</a></span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::visit_to_create<button class="popup" onclick="togglePopup('usagePopup1437')">...<span class="popuptext" id="usagePopup1437">Usage of <b>Equations::visit_to_create</b>:<br>none</span></button></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="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) == </span><span class="identifier">EQUATION_NT</span><span class="plain">)</span>
<span class="functiontext"><a href="20-eq.html#SP10_1">Equations::new</a></span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">), </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>Equation names follow the same conventions as table names.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt; ::=</span>
<span class="reserved">equation</span><span class="plain"> {&lt;</span><span class="identifier">cardinal</span><span class="plain">-</span><span class="identifier">number</span><span class="plain">&gt;} - ... | ==&gt; </span><span class="constant">3</span>
<span class="reserved">equation</span><span class="plain"> {&lt;</span><span class="identifier">cardinal</span><span class="plain">-</span><span class="identifier">number</span><span class="plain">&gt;} | ==&gt; </span><span class="constant">1</span>
<span class="reserved">equation</span><span class="plain"> - ... | ==&gt; </span><span class="constant">2</span>
<span class="reserved">equation</span><span class="plain"> *** ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_EquationMisnumbered problem</span> <span class="cwebmacronumber">10.3</span>&gt;
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP10_1"></a><b>&#167;10.1. </b>The above catches all of the named expressions written out in the
source text, but not the ones written "inline", in phrases like
</p>
<blockquote>
<p>let F be given by F = ma;</p>
</blockquote>
<p class="inwebparagraph">Those equations are created by calling <code class="display"><span class="extract">Equations::new</span></code> direct from the
S-parser: such equations are called "anonymous", as they have no name. But in
either case, an equation begins here:
</p>
<pre class="display">
<span class="reserved">equation</span><span class="plain"> *</span><span class="functiontext">Equations::new<button class="popup" onclick="togglePopup('usagePopup1438')">...<span class="popuptext" id="usagePopup1438">Usage of <b>Equations::new</b>:<br><a href="20-eq.html#SP9">&#167;9</a>, <a href="20-eq.html#SP52">&#167;52</a>, Type Expressions and Values - <a href="10-teav.html#SP12_1">&#167;12.1</a>, <a href="10-teav.html#SP12_3">&#167;12.3</a></span></button></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">int</span><span class="plain"> </span><span class="identifier">anonymous</span><span class="plain">) {</span>
<span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="reserved">equation</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_created_at</span><span class="plain"> == </span><span class="identifier">current_sentence</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">eqn</span><span class="plain">;</span>
<span class="identifier">eqn</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">equation</span><span class="plain">);</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_created_at</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">where_text</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">usage_text</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">symbol_list</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">examined_already</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">package_request</span><span class="plain"> *</span><span class="identifier">PR</span><span class="plain"> = </span><span class="functiontext"><a href="27-hr.html#SP4">Hierarchy::local_package</a></span><span class="plain">(</span><span class="constant">EQUATIONS_HAP</span><span class="plain">);</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">eqn_iname</span><span class="plain"> = </span><span class="functiontext"><a href="27-hr.html#SP4">Hierarchy::make_iname_in</a></span><span class="plain">(</span><span class="constant">SOLVE_FN_HL</span><span class="plain">, </span><span class="identifier">PR</span><span class="plain">);</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">NO</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">, </span><span class="identifier">NA</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">anonymous</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Parse the equation's number and/or name</span> <span class="cwebmacronumber">10.1.1</span>&gt;<span class="character">;</span>
&lt;<span class="cwebmacro">Register any names for this equation</span> <span class="cwebmacronumber">10.1.3</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="identifier">W</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">&gt;, </span><span class="constant">1</span><span class="plain">);</span>
<span class="functiontext"><a href="20-eq.html#SP11">Equations::set_wherewithal</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">&gt;, </span><span class="constant">2</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_no_text</span><span class="plain"> = </span><span class="identifier">NO</span><span class="plain">;</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_name_text</span><span class="plain"> = </span><span class="identifier">NA</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">text</span><span class="plain">-</span><span class="identifier">ending</span><span class="plain">-</span><span class="identifier">in</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="identifier">text</span><span class="plain">-</span><span class="identifier">ending</span><span class="plain">-</span><span class="identifier">in</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">&gt;, </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_text</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">eqn</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP10_2"></a><b>&#167;10.2. </b></p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">text</span><span class="plain">-</span><span class="identifier">ending</span><span class="plain">-</span><span class="identifier">in</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">&gt; ::=</span>
<span class="plain">... ,</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP10_3"></a><b>&#167;10.3. </b>We take the word range \((w_1, w_2)\) and shave off the first line, that is,
all the words up to the first line break occurring between words. (Compare
the syntax for a table declaration.) This becomes the word range \((tw_1, tw_2)\).
We know that this begins with the word "equation", or we wouldn't be here
(because the sentence would not have been classed an <code class="display"><span class="extract">EQUATION_NT</span></code>).
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_EquationMisnumbered problem</span> <span class="cwebmacronumber">10.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="functiontext"><a href="1-wtc.html#SP5">Task::syntax_tree</a></span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationMisnumbered</span><span class="plain">),</span>
<span class="string">"the top line of this equation declaration seems not to be a "</span>
<span class="string">"legal equation number or name"</span><span class="plain">,</span>
<span class="string">"and should read something like 'Equation 6', or 'Equation - "</span>
<span class="string">"Newton's Second Law', or 'Equation 41 - Coulomb's Law'."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_1_1"></a><b>&#167;10.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Parse the equation's number and/or name</span> <span class="cwebmacronumber">10.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="identifier">Wordings::last_word_of_formatted_text</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">TW</span><span class="plain"> = </span><span class="identifier">Wordings::up_to</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Wordings::from</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+1);</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt;(</span><span class="identifier">TW</span><span class="plain">)) {</span>
<span class="reserved">switch</span><span class="plain"> (&lt;&lt;</span><span class="identifier">r</span><span class="plain">&gt;&gt;) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">0</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="reserved">case</span><span class="plain"> </span><span class="constant">1</span><span class="plain">: </span><span class="identifier">NO</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt;, </span><span class="constant">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">2</span><span class="plain">: </span><span class="identifier">NA</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt;, </span><span class="constant">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">3</span><span class="plain">: </span><span class="identifier">NO</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt;, </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">NA</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt;, </span><span class="constant">2</span><span class="plain">); </span><span class="reserved">break</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">internal_error</span><span class="plain">(</span><span class="string">"malformed equation sentence"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP10_1">&#167;10.1</a>.</p>
<p class="inwebparagraph"><a id="SP10_1_2"></a><b>&#167;10.1.2. </b>An equation can be referred to by its number, or by its name. Thus
</p>
<blockquote>
<p>Equation 64 - Distribution of Cheese</p>
</blockquote>
<p class="inwebparagraph">could be referred to elsewhere in the text by any of three names:
</p>
<blockquote>
<p>equation 64, Distribution of Cheese, Distribution of Cheese equation</p>
</blockquote>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">names</span><span class="plain">-</span><span class="identifier">construction</span><span class="plain">&gt; ::=</span>
<span class="reserved">equation</span><span class="plain"> ... |</span>
<span class="plain">... </span><span class="reserved">equation</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP10_1_3"></a><b>&#167;10.1.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Register any names for this equation</span> <span class="cwebmacronumber">10.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">NO</span><span class="plain">)) {</span>
<span class="identifier">word_assemblage</span><span class="plain"> </span><span class="identifier">wa</span><span class="plain"> = </span><span class="identifier">Preform::Nonparsing::merge</span><span class="plain">(&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">names</span><span class="plain">-</span><span class="identifier">construction</span><span class="plain">&gt;, </span><span class="constant">0</span><span class="plain">,</span>
<span class="identifier">WordAssemblages::from_wording</span><span class="plain">(</span><span class="identifier">NO</span><span class="plain">));</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">AW</span><span class="plain"> = </span><span class="identifier">WordAssemblages::to_wording</span><span class="plain">(&amp;</span><span class="identifier">wa</span><span class="plain">);</span>
<span class="identifier">Nouns::new_proper_noun</span><span class="plain">(</span><span class="identifier">AW</span><span class="plain">, </span><span class="identifier">NEUTER_GENDER</span><span class="plain">,</span>
<span class="identifier">REGISTER_SINGULAR_NTOPT</span><span class="plain"> + </span><span class="identifier">PARSE_EXACTLY_NTOPT</span><span class="plain">,</span>
<span class="constant">EQUATION_MC</span><span class="plain">, </span><span class="functiontext"><a href="14-rv.html#SP1">Rvalues::from_equation</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">NA</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">type</span><span class="plain">-</span><span class="identifier">expression</span><span class="plain">-</span><span class="identifier">or</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">&gt;(</span><span class="identifier">NA</span><span class="plain">)) {</span>
<span class="identifier">Problems::quote_wording_as_source</span><span class="plain">(1, </span><span class="identifier">NA</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext"><a href="1-wtc.html#SP5">Task::syntax_tree</a></span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationMisnamed</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The equation name %1 will have to be disallowed as it is text "</span>
<span class="string">"which already has a meaning to Inform. For instance, creating "</span>
<span class="string">"an equation called 'Equation - 2 + 2' would be disallowed "</span>
<span class="string">"because Inform would read '2 + 2' as arithmetic, not a name."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">Nouns::new_proper_noun</span><span class="plain">(</span><span class="identifier">NA</span><span class="plain">, </span><span class="identifier">NEUTER_GENDER</span><span class="plain">,</span>
<span class="identifier">REGISTER_SINGULAR_NTOPT</span><span class="plain"> + </span><span class="identifier">PARSE_EXACTLY_NTOPT</span><span class="plain">,</span>
<span class="constant">EQUATION_MC</span><span class="plain">, </span><span class="functiontext"><a href="14-rv.html#SP1">Rvalues::from_equation</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">));</span>
<span class="identifier">word_assemblage</span><span class="plain"> </span><span class="identifier">wa</span><span class="plain"> =</span>
<span class="identifier">Preform::Nonparsing::merge</span><span class="plain">(&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">names</span><span class="plain">-</span><span class="identifier">construction</span><span class="plain">&gt;, </span><span class="constant">0</span><span class="plain">,</span>
<span class="identifier">WordAssemblages::from_wording</span><span class="plain">(</span><span class="identifier">NA</span><span class="plain">));</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">AW</span><span class="plain"> = </span><span class="identifier">WordAssemblages::to_wording</span><span class="plain">(&amp;</span><span class="identifier">wa</span><span class="plain">);</span>
<span class="identifier">Nouns::new_proper_noun</span><span class="plain">(</span><span class="identifier">AW</span><span class="plain">, </span><span class="identifier">NEUTER_GENDER</span><span class="plain">,</span>
<span class="identifier">REGISTER_SINGULAR_NTOPT</span><span class="plain"> + </span><span class="identifier">PARSE_EXACTLY_NTOPT</span><span class="plain">,</span>
<span class="constant">EQUATION_MC</span><span class="plain">, </span><span class="functiontext"><a href="14-rv.html#SP1">Rvalues::from_equation</a></span><span class="plain">(</span><span class="identifier">eqn</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="20-eq.html#SP10_1">&#167;10.1</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>A "where" clause following an equation defines its symbols, as we shall
see. That can be detected in the above parsing process where the equation
is displayed, but for anonymous equations occurring inline, the S-parser
has to discover it; and the S-parser then calls this routine:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::set_wherewithal<button class="popup" onclick="togglePopup('usagePopup1439')">...<span class="popuptext" id="usagePopup1439">Usage of <b>Equations::set_wherewithal</b>:<br><a href="20-eq.html#SP10_1">&#167;10.1</a>, <a href="20-eq.html#SP52">&#167;52</a>, Type Expressions and Values - <a href="10-teav.html#SP12_1">&#167;12.1</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</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">eqn</span><span class="plain">-&gt;</span><span class="element">where_text</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. Parsing equations. </b>So now it's later on. We can run through all the equations displayed in the
source text:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::traverse_to_stock<button class="popup" onclick="togglePopup('usagePopup1440')">...<span class="popuptext" id="usagePopup1440">Usage of <b>Equations::traverse_to_stock</b>:<br>How To Compile - <a href="1-htc.html#SP2_7">&#167;2.7</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="reserved">equation</span><span class="plain">) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_created_at</span><span class="plain">;</span>
<span class="functiontext"><a href="20-eq.html#SP13">Equations::examine</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b>And, as with creation, <code class="display"><span class="extract">Equations::examine</span></code> is called explicitly in the meaning
list converter when an equation is found inline. So in all cases, we call the
following before we need to use the equation, which runs a three-stage process:
parsing the "where..." clause to declare the symbols, then parsing the equation,
then type-checking it.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::examine<button class="popup" onclick="togglePopup('usagePopup1441')">...<span class="popuptext" id="usagePopup1441">Usage of <b>Equations::examine</b>:<br><a href="20-eq.html#SP12">&#167;12</a>, <a href="20-eq.html#SP52">&#167;52</a>, Type Expressions and Values - <a href="10-teav.html#SP12_1">&#167;12.1</a>, <a href="10-teav.html#SP12_2">&#167;12.2</a>, <a href="10-teav.html#SP12_3">&#167;12.3</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">examined_already</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">examined_already</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="functiontext"><a href="20-eq.html#SP15">Equations::eqn_declare_symbols</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="functiontext"><a href="20-eq.html#SP21">Equations::eqn_declare_standard_symbols</a></span><span class="plain">();</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP28">Equations::eqn_parse</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</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="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP39">Equations::eqn_typecheck</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="functiontext"><a href="20-eq.html#SP27">Equations::log_equation_node</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. Declaring symbols. </b>Equations are allowed to end with a "where..." clause, explaining what
the symbols in it mean. For example:
</p>
<blockquote>
<p>where F is a force, a = 9.801 m/ss, m1 and m2 are masses;</p>
</blockquote>
<p class="inwebparagraph">At the earlier stages of parsing, we simply split the "where" text away
using this:
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">&gt; ::=</span>
<span class="plain">... </span><span class="identifier">where</span><span class="plain"> ...</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. </b>For a displayed equation, the following parses the "where..." text, which
is expected to declare every symbol occurring in it.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::eqn_declare_symbols<button class="popup" onclick="togglePopup('usagePopup1442')">...<span class="popuptext" id="usagePopup1442">Usage of <b>Equations::eqn_declare_symbols</b>:<br><a href="20-eq.html#SP13">&#167;13</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::empty</span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">where_text</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">int</span><span class="plain"> </span><span class="identifier">result</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP18">Equations::eqn_declare_variables_inner</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">where_text</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">changed</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">changed</span><span class="plain">) {</span>
<span class="identifier">changed</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">symbol_list</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">var_kind</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">ev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_symbol_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">),</span>
<span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="identifier">where_text</span><span class="plain">,</span>
<span class="string">"each symbol in a equation has to be declared with a kind of "</span>
<span class="string">"value or else an actual value. So '...where N = 1701.' or "</span>
<span class="string">"'...where N, M are numbers.' would be fine."</span><span class="plain">);</span>
<span class="identifier">result</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">var_kind</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">-&gt;</span><span class="element">var_kind</span><span class="plain">;</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">var_const</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">-&gt;</span><span class="element">var_const</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="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">result</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. </b>But the following routine is also used with the "where" text supplied in
a phrase like so:
</p>
<blockquote>
<p>let F be given by Newton's Second Law, where m = 101kg;</p>
</blockquote>
<p class="inwebparagraph">In this context the "where" text sets explicit values for symbols occurring
in the equation; these are temporary settings only and will not change the
equation's behaviour elsewhere.
</p>
<p class="inwebparagraph">So the following is called in either permanent mode, when it declares symbols
for an equation, or temporary mode, when it gives them temporary assignments.
It returns <code class="display"><span class="extract">TRUE</span></code> if all went well, or <code class="display"><span class="extract">FALSE</span></code> if problem messages had to be
issued.
</p>
<pre class="display">
<span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">equation_being_declared</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">equation_declared_temporarily</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">eq_symbol_wn</span><span class="plain"> = -1;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. </b>The following grammar is later used to parse the text after "where". For
example:
</p>
<blockquote>
<p>F is a force, a = 9.801 m/ss, m1 and m2 are masses</p>
</blockquote>
<p class="inwebparagraph">This is split into four clauses, of which the trickiest is the third, reading
just "m1". This abbreviated form is allowed only in permanent declarations
(i.e., not in equations defined inside "let" phrases) and gives the symbol
the same definition as the one following it &mdash; so m1 becomes defined as a
mass, too.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt; ::=</span>
<span class="plain">... | ==&gt; </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">eq_symbol_wn</span><span class="plain"> = </span><span class="identifier">Wordings::first_wn</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">preform_lookahead_mode</span><span class="plain">; </span><span class="comment"> match only when looking ahead</span>
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">-</span><span class="identifier">setting</span><span class="plain">-</span><span class="identifier">entry</span><span class="plain">&gt; &lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">-</span><span class="identifier">tail</span><span class="plain">&gt; | ==&gt; </span><span class="constant">0</span>
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">-</span><span class="identifier">setting</span><span class="plain">-</span><span class="identifier">entry</span><span class="plain">&gt; ==&gt; </span><span class="constant">0</span>
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">-</span><span class="identifier">tail</span><span class="plain">&gt; ::=</span>
<span class="plain">, </span><span class="identifier">_and</span><span class="plain"> &lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt; | ==&gt; </span><span class="constant">0</span>
<span class="identifier">_</span><span class="plain">,/</span><span class="identifier">and</span><span class="plain"> &lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt; ==&gt; </span><span class="constant">0</span>
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">-</span><span class="identifier">setting</span><span class="plain">-</span><span class="identifier">entry</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">-</span><span class="identifier">setting</span><span class="plain">&gt; ==&gt; </span><span class="constant">0</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (!</span><span class="identifier">preform_lookahead_mode</span><span class="plain">) </span><span class="functiontext"><a href="20-eq.html#SP18">Equations::eqn_dec_var</a></span><span class="plain">(</span><span class="identifier">equation_being_declared</span><span class="plain">, </span><span class="identifier">Wordings::one_word</span><span class="plain">(</span><span class="identifier">eq_symbol_wn</span><span class="plain">), </span><span class="identifier">R</span><span class="plain">[1], </span><span class="identifier">RP</span><span class="plain">[1]);</span>
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">-</span><span class="identifier">setting</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">symbol</span><span class="plain">&gt; </span><span class="identifier">is</span><span class="plain">/</span><span class="identifier">are</span><span class="plain"> &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">kind</span><span class="plain">&gt; | ==&gt; </span><span class="constant">EQW_IDENTIFIES_KIND</span><span class="plain">; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">RP</span><span class="plain">[2]; </span><span class="identifier">eq_symbol_wn</span><span class="plain"> = </span><span class="identifier">R</span><span class="plain">[1];</span>
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">symbol</span><span class="plain">&gt; </span><span class="identifier">is</span><span class="plain">/</span><span class="identifier">are</span><span class="plain"> &lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">&gt; | ==&gt; </span><span class="constant">EQW_IDENTIFIES_VALUE</span><span class="plain">; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">RP</span><span class="plain">[2]; </span><span class="identifier">eq_symbol_wn</span><span class="plain"> = </span><span class="identifier">R</span><span class="plain">[1];</span>
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">symbol</span><span class="plain">&gt; </span><span class="identifier">is</span><span class="plain">/</span><span class="identifier">are</span><span class="plain"> ... | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_EquationSymbolNonValue problem</span> <span class="cwebmacronumber">17.1</span>&gt;
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">symbol</span><span class="plain">&gt; = &lt;</span><span class="identifier">k</span><span class="plain">-</span><span class="identifier">kind</span><span class="plain">&gt; | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_EquationSymbolEqualsKOV problem</span> <span class="cwebmacronumber">17.2</span>&gt;
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">symbol</span><span class="plain">&gt; = &lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">&gt; | ==&gt; </span><span class="constant">EQW_IDENTIFIES_VALUE</span><span class="plain">; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">RP</span><span class="plain">[2]; </span><span class="identifier">eq_symbol_wn</span><span class="plain"> = </span><span class="identifier">R</span><span class="plain">[1];</span>
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">symbol</span><span class="plain">&gt; = ... | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_EquationSymbolNonValue problem</span> <span class="cwebmacronumber">17.1</span>&gt;
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">symbol</span><span class="plain">&gt; ==&gt; </span><span class="constant">EQW_IDENTIFIES_NOTHING</span><span class="plain">; </span><span class="identifier">eq_symbol_wn</span><span class="plain"> = </span><span class="identifier">R</span><span class="plain">[1];</span>
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">symbol</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">valid</span><span class="plain">-</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">symbol</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">R</span><span class="plain">[1]</span>
<span class="plain">### | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_EquationSymbolMalformed problem</span> <span class="cwebmacronumber">17.3</span>&gt;
<span class="plain">... ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_EquationSymbolMisdeclared problem</span> <span class="cwebmacronumber">17.4</span>&gt;
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP17_1"></a><b>&#167;17.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_EquationSymbolNonValue problem</span> <span class="cwebmacronumber">17.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = </span><span class="constant">EQW_IDENTIFIES_PROBLEM</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (!</span><span class="identifier">preform_lookahead_mode</span><span class="plain">)</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_symbol_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationSymbolNonValue</span><span class="plain">),</span>
<span class="identifier">equation_being_declared</span><span class="plain">, </span><span class="identifier">Wordings::one_word</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">[1]),</span>
<span class="string">"this has neither a kind of value nor an actual value."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP17">&#167;17</a> (twice).</p>
<p class="inwebparagraph"><a id="SP17_2"></a><b>&#167;17.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_EquationSymbolEqualsKOV problem</span> <span class="cwebmacronumber">17.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = </span><span class="constant">EQW_IDENTIFIES_PROBLEM</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (!</span><span class="identifier">preform_lookahead_mode</span><span class="plain">)</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_symbol_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationSymbolEqualsKOV</span><span class="plain">),</span>
<span class="identifier">equation_being_declared</span><span class="plain">, </span><span class="identifier">Wordings::one_word</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">[1]),</span>
<span class="string">"'is' should be used, not '=', for a kind of value rather "</span>
<span class="string">"than an actual value."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP17">&#167;17</a>.</p>
<p class="inwebparagraph"><a id="SP17_3"></a><b>&#167;17.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_EquationSymbolMalformed problem</span> <span class="cwebmacronumber">17.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = -1;</span>
<span class="reserved">if</span><span class="plain"> (!</span><span class="identifier">preform_lookahead_mode</span><span class="plain">)</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_symbol_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationSymbolMalformed</span><span class="plain">),</span>
<span class="identifier">equation_being_declared</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">,</span>
<span class="string">"a symbol in a equation has to be a sequence of one to ten "</span>
<span class="string">"letters optionally followed by a number from 0 to 99, so "</span>
<span class="string">"'G', 'm', 'pi' and 'KE1' are all legal symbol names. But "</span>
<span class="string">"this one is not."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP17">&#167;17</a>.</p>
<p class="inwebparagraph"><a id="SP17_4"></a><b>&#167;17.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_EquationSymbolMisdeclared problem</span> <span class="cwebmacronumber">17.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = -1;</span>
<span class="reserved">if</span><span class="plain"> (!</span><span class="identifier">preform_lookahead_mode</span><span class="plain">)</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="functiontext"><a href="1-wtc.html#SP5">Task::syntax_tree</a></span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationSymbolMisdeclared</span><span class="plain">),</span>
<span class="string">"the symbols here are not declared properly"</span><span class="plain">,</span>
<span class="string">"and should each be declared with a kind of value or else an "</span>
<span class="string">"actual value."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP17">&#167;17</a>.</p>
<p class="inwebparagraph"><a id="SP18"></a><b>&#167;18. </b></p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">EQW_IDENTIFIES_KIND</span><span class="plain"> </span><span class="constant">1</span>
<span class="definitionkeyword">define</span> <span class="constant">EQW_IDENTIFIES_VALUE</span><span class="plain"> </span><span class="constant">2</span>
<span class="definitionkeyword">define</span> <span class="constant">EQW_IDENTIFIES_NOTHING</span><span class="plain"> </span><span class="constant">3</span>
<span class="definitionkeyword">define</span> <span class="constant">EQW_IDENTIFIES_PROBLEM</span><span class="plain"> </span><span class="constant">4</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::eqn_declare_variables_inner<button class="popup" onclick="togglePopup('usagePopup1443')">...<span class="popuptext" id="usagePopup1443">Usage of <b>Equations::eqn_declare_variables_inner</b>:<br><a href="20-eq.html#SP15">&#167;15</a>, <a href="20-eq.html#SP46">&#167;46</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</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">int</span><span class="plain"> </span><span class="identifier">temp</span><span class="plain">) {</span>
<span class="identifier">equation_being_declared</span><span class="plain"> = </span><span class="identifier">eqn</span><span class="plain">;</span>
<span class="identifier">equation_declared_temporarily</span><span class="plain"> = </span><span class="identifier">temp</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pc</span><span class="plain"> = </span><span class="identifier">problem_count</span><span class="plain">;</span>
<span class="plain">&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> &gt; </span><span class="identifier">pc</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>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::eqn_dec_var<button class="popup" onclick="togglePopup('usagePopup1444')">...<span class="popuptext" id="usagePopup1444">Usage of <b>Equations::eqn_dec_var</b>:<br><a href="20-eq.html#SP17">&#167;17</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</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">int</span><span class="plain"> </span><span class="identifier">X</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">XP</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="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">temp</span><span class="plain"> = </span><span class="identifier">equation_declared_temporarily</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">X</span><span class="plain"> == </span><span class="constant">EQW_IDENTIFIES_PROBLEM</span><span class="plain">) || (</span><span class="identifier">Wordings::empty</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">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">X</span><span class="plain"> != </span><span class="constant">EQW_IDENTIFIES_NOTHING</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Find the actual value, or kind of value, which the symbol is to match</span> <span class="cwebmacronumber">18.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">temp</span><span class="plain">) </span>&lt;<span class="cwebmacro">Assign the given value to this symbol on a temporary basis</span> <span class="cwebmacronumber">18.2</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext"><a href="20-eq.html#SP22">Equations::eqn_add_symbol</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP18_1"></a><b>&#167;18.1. </b>Symbols are allowed to be set equal to kinds of value, but only quasinumerical
ones; or to quasinumerical constants; or to global variables which contain
quasinumerical values. The latter are included to make it easier for extensions
to set up sets of equations for, say, gravity, defining
</p>
<blockquote>
<p>The acceleration due to gravity is an acceleration that varies.</p>
</blockquote>
<p class="inwebparagraph">and thus letting the extension's user decide how strong gravity is, but
still using it in equations:
</p>
<blockquote>
<p>let F be given by Newton's Second Law, where a = the acceleration due to gravity;</p>
</blockquote>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Find the actual value, or kind of value, which the symbol is to match</span> <span class="cwebmacronumber">18.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<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">X</span><span class="plain"> == </span><span class="constant">EQW_IDENTIFIES_KIND</span><span class="plain">) {</span>
<span class="identifier">K</span><span class="plain"> = </span><span class="identifier">XP</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">temp</span><span class="plain">) {</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_symbol_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationSymbolVague</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">,</span>
<span class="string">"when an equation is named for use in a 'let' "</span>
<span class="string">"phrase, any variables listed under 'where...' have "</span>
<span class="string">"to be given definite values, not just vaguely said "</span>
<span class="string">"to have particular kinds. Otherwise, I can't do any "</span>
<span class="string">"calculation with them."</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="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">X</span><span class="plain"> == </span><span class="constant">EQW_IDENTIFIES_VALUE</span><span class="plain">) {</span>
<span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">XP</span><span class="plain">;</span>
<span class="identifier">K</span><span class="plain"> = </span><span class="functiontext"><a href="14-sp.html#SP1">Specifications::to_kind</a></span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Behaviour::is_quasinumerical</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_symbol_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationSymbolNonNumeric</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">,</span>
<span class="string">"this has a kind of value on which arithmetic cannot be done, "</span>
<span class="string">"so it can have no place in an equation."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP18">&#167;18</a>.</p>
<p class="inwebparagraph"><a id="SP18_2"></a><b>&#167;18.2. </b>At this point we know the user means the variable named at word <code class="display"><span class="extract">wn</span></code>
to have the temporary value <code class="display"><span class="extract">spec</span></code>, and we have to identify that as one
of the symbols:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Assign the given value to this symbol on a temporary basis</span> <span class="cwebmacronumber">18.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">symbol_list</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::match_cs</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">var_kind</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_symbol_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationSymbolBadSub</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">,</span>
<span class="string">"you're using 'where' to substitute something into this "</span>
<span class="string">"symbol which has the wrong kind of value."</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">temp_constant</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">var_const</span><span class="plain"> = </span><span class="identifier">spec</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_symbol_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationSymbolSpurious</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">,</span>
<span class="string">"when 'where' is used to supply values to plug into a "</span>
<span class="string">"named equation as part of a 'let' phrase, you can only "</span>
<span class="string">"supply values for symbols actually used in that equation. "</span>
<span class="string">"This one doesn't seem to occur there."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP18">&#167;18</a>.</p>
<p class="inwebparagraph"><a id="SP19"></a><b>&#167;19. </b>We won't want those temporary assignments hanging around, so once the
hurly-burly is done, the following is called:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::eqn_remove_temp_variables<button class="popup" onclick="togglePopup('usagePopup1445')">...<span class="popuptext" id="usagePopup1445">Usage of <b>Equations::eqn_remove_temp_variables</b>:<br><a href="20-eq.html#SP46">&#167;46</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">symbol_list</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">temp_constant</span><span class="plain">) {</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">var_const</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">temp_constant</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP20"></a><b>&#167;20. </b>As we saw, permanent symbol declarations cause <code class="display"><span class="extract">Equations::eqn_add_symbol</span></code> to be called.
But what about the symbols for an inline equation, like this one?
</p>
<blockquote>
<p>let F be given by F = ma;</p>
</blockquote>
<p class="inwebparagraph">These are not explicitly declared. What happens is that any local variable
on the current stack frame, whose name could plausibly be that of a symbol,
is made into one. Sometimes the locals won't be symbols in the equation at all,
but will just have short names and coincidentally hold quasinumeric values;
that doesn't matter, because if they're not in the equation, they'll never
be used.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::declare_local_variables<button class="popup" onclick="togglePopup('usagePopup1446')">...<span class="popuptext" id="usagePopup1446">Usage of <b>Equations::declare_local_variables</b>:<br>Type Expressions and Values - <a href="10-teav.html#SP12_1">&#167;12.1</a>, <a href="10-teav.html#SP12_2">&#167;12.2</a>, <a href="10-teav.html#SP12_3">&#167;12.3</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">) {</span>
<span class="functiontext"><a href="24-lv.html#SP30">LocalVariables::make_available_to_equation</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="comment"> which calls the following for each current local variable in turn:</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::declare_local<button class="popup" onclick="togglePopup('usagePopup1447')">...<span class="popuptext" id="usagePopup1447">Usage of <b>Equations::declare_local</b>:<br>Local Variables - <a href="24-lv.html#SP30">&#167;30</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</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">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext"><a href="20-eq.html#SP24">Equations::equation_symbol_legal</a></span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) &amp;&amp; (</span><span class="identifier">Kinds::Behaviour::is_quasinumerical</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)))</span>
<span class="functiontext"><a href="20-eq.html#SP22">Equations::eqn_add_symbol</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP21"></a><b>&#167;21. </b>Next we add "e" and "pi". These are added last, so that any local
declarations will trump them.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::eqn_declare_standard_symbols<button class="popup" onclick="togglePopup('usagePopup1448')">...<span class="popuptext" id="usagePopup1448">Usage of <b>Equations::eqn_declare_standard_symbols</b>:<br><a href="20-eq.html#SP13">&#167;13</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">standard_equation_symbols</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">TCW</span><span class="plain"> = </span><span class="identifier">Feeds::feed_text</span><span class="plain">(</span><span class="identifier">L</span><span class="string">"e pi"</span><span class="plain">);</span>
<span class="identifier">LOOP_THROUGH_WORDING</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">TCW</span><span class="plain">) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">V</span><span class="plain"> = </span><span class="identifier">Wordings::one_word</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">type</span><span class="plain">-</span><span class="identifier">expression</span><span class="plain">&gt;(</span><span class="identifier">V</span><span class="plain">)) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="functiontext"><a href="20-eq.html#SP22">Equations::eqn_add_symbol</a></span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">K_real_number</span><span class="plain">, </span><span class="identifier">spec</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">, </span><span class="reserved">phrase</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="functiontext"><a href="22-pu.html#SP16">Phrases::Usage::get_equation_form</a></span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-&gt;</span><span class="element">usage_data</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">ev</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP22">Equations::eqn_add_symbol</a></span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">K_real_number</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">function_notated</span><span class="plain"> = </span><span class="identifier">ph</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP22"></a><b>&#167;22. </b>And that about wraps up symbol declaration, except for the routine which
actually declares symbols:
</p>
<pre class="display">
<span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="functiontext">Equations::eqn_add_symbol<button class="popup" onclick="togglePopup('usagePopup1449')">...<span class="popuptext" id="usagePopup1449">Usage of <b>Equations::eqn_add_symbol</b>:<br><a href="20-eq.html#SP18">&#167;18</a>, <a href="20-eq.html#SP20">&#167;20</a>, <a href="20-eq.html#SP21">&#167;21</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</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">kind</span><span class="plain"> *</span><span class="identifier">K</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">W</span><span class="plain"> = </span><span class="identifier">Wordings::first_word</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="reserved">equation_symbol</span><span class="plain"> **</span><span class="identifier">list_head</span><span class="plain"> = &amp;</span><span class="identifier">standard_equation_symbols</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">eqn</span><span class="plain">) </span><span class="identifier">list_head</span><span class="plain"> = &amp;(</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">symbol_list</span><span class="plain">);</span>
<span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">ev</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">ev</span><span class="plain"> = *</span><span class="identifier">list_head</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::match_cs</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">ev</span><span class="plain">;</span>
<span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">equation_symbol</span><span class="plain">);</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">var_kind</span><span class="plain"> = </span><span class="identifier">K</span><span class="plain">;</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">function_notated</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">var_const</span><span class="plain"> = </span><span class="identifier">spec</span><span class="plain">;</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (*</span><span class="identifier">list_head</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) *</span><span class="identifier">list_head</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">f</span><span class="plain"> = *</span><span class="identifier">list_head</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">f</span><span class="plain">) &amp;&amp; (</span><span class="identifier">f</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">)) </span><span class="identifier">f</span><span class="plain"> = </span><span class="identifier">f</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">;</span>
<span class="identifier">f</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">temp_constant</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">ev</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP23"></a><b>&#167;23. </b>This is where the criterion for being a valid symbol name is expressed:
it matches only a single word, and only if the lettering matches the regular
expression <code class="display"><span class="extract">[A-Za-z]?{1,8}\d?{0,2}</span></code>.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">valid</span><span class="plain">-</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">symbol</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP24">Equations::equation_symbol_legal</a></span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) { *</span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">Wordings::first_wn</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">TRUE</span><span class="plain">; }</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP24"></a><b>&#167;24. </b>Using:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::equation_symbol_legal<button class="popup" onclick="togglePopup('usagePopup1450')">...<span class="popuptext" id="usagePopup1450">Usage of <b>Equations::equation_symbol_legal</b>:<br><a href="20-eq.html#SP20">&#167;20</a>, <a href="20-eq.html#SP23">&#167;23</a></span></button></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">Wordings::length</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">) == </span><span class="constant">1</span><span class="plain">) {</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">Lexer::word_raw_text</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</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">letters</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">digits</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">name_legal</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">p</span><span class="plain">[</span><span class="identifier">j</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">c</span><span class="plain"> = </span><span class="identifier">p</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">Characters::isdigit</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">)) </span><span class="identifier">digits</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">Characters::isalpha</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">)) { </span><span class="identifier">letters</span><span class="plain">++; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">digits</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">name_legal</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; }</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">name_legal</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">j</span><span class="plain"> &gt;= </span><span class="constant">13</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">letters</span><span class="plain"> &gt; </span><span class="constant">10</span><span class="plain">) || (</span><span class="identifier">digits</span><span class="plain"> &gt; </span><span class="constant">2</span><span class="plain">)) </span><span class="identifier">name_legal</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">name_legal</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP25"></a><b>&#167;25. Equation nodes. </b>The parsed equation is a tree full of nodes, so we need routines to make
and examine them.
</p>
<pre class="display">
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="functiontext">Equations::enode_new<button class="popup" onclick="togglePopup('usagePopup1451')">...<span class="popuptext" id="usagePopup1451">Usage of <b>Equations::enode_new</b>:<br><a href="20-eq.html#SP26">&#167;26</a>, <a href="20-eq.html#SP28">&#167;28</a>, <a href="20-eq.html#SP28_1_3">&#167;28.1.3</a>, <a href="20-eq.html#SP32">&#167;32</a></span></button></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="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">enode</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">equation_node</span><span class="plain">);</span>
<span class="identifier">enode</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain"> = </span><span class="identifier">t</span><span class="plain">;</span>
<span class="identifier">enode</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain"> = -1;</span>
<span class="identifier">enode</span><span class="plain">-&gt;</span><span class="element">enode_arity</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">enode</span><span class="plain">-&gt;</span><span class="element">leaf_constant</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">enode</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">enode</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">enode</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::new_gk</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">); </span><span class="comment"> unknown for now</span>
<span class="identifier">enode</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::new_gk</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">); </span><span class="comment"> unknown for now</span>
<span class="identifier">enode</span><span class="plain">-&gt;</span><span class="element">enode_promotion</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">enode</span><span class="plain">-&gt;</span><span class="element">rational_n</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">enode</span><span class="plain">-&gt;</span><span class="element">rational_m</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">enode</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP26"></a><b>&#167;26. </b>This is how we make the three kinds of enode permitted in the final compiled
equation. (The other kinds can be created using <code class="display"><span class="extract">Equations::enode_new</span></code> directly.)
</p>
<pre class="display">
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="functiontext">Equations::enode_new_op<button class="popup" onclick="togglePopup('usagePopup1452')">...<span class="popuptext" id="usagePopup1452">Usage of <b>Equations::enode_new_op</b>:<br><a href="20-eq.html#SP28_1_3">&#167;28.1.3</a>, <a href="20-eq.html#SP28_2">&#167;28.2</a>, <a href="20-eq.html#SP50_3_1">&#167;50.3.1</a>, <a href="20-eq.html#SP50_4">&#167;50.4</a></span></button></span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">op</span><span class="plain">) {</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">enode</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP25">Equations::enode_new</a></span><span class="plain">(</span><span class="constant">OPERATION_EQN</span><span class="plain">);</span>
<span class="identifier">enode</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain"> = </span><span class="identifier">op</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">enode</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="functiontext">Equations::enode_new_symbol<button class="popup" onclick="togglePopup('usagePopup1453')">...<span class="popuptext" id="usagePopup1453">Usage of <b>Equations::enode_new_symbol</b>:<br><a href="20-eq.html#SP28_1_1_1">&#167;28.1.1.1</a></span></button></span><span class="plain">(</span><span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">ev</span><span class="plain">) {</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">enode</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP25">Equations::enode_new</a></span><span class="plain">(</span><span class="constant">SYMBOL_EQN</span><span class="plain">);</span>
<span class="identifier">enode</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">enode</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="functiontext">Equations::enode_new_constant<button class="popup" onclick="togglePopup('usagePopup1454')">...<span class="popuptext" id="usagePopup1454">Usage of <b>Equations::enode_new_constant</b>:<br><a href="20-eq.html#SP28_1_2">&#167;28.1.2</a>, <a href="20-eq.html#SP50_3_1">&#167;50.3.1</a></span></button></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">equation_node</span><span class="plain"> *</span><span class="identifier">enode</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP25">Equations::enode_new</a></span><span class="plain">(</span><span class="constant">CONSTANT_EQN</span><span class="plain">);</span>
<span class="identifier">enode</span><span class="plain">-&gt;</span><span class="element">leaf_constant</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">enode</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP27"></a><b>&#167;27. </b>Being able to log nodes is useful, if only because it's always pretty to
watch shift-reduce parsers in action.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::log_equation_node<button class="popup" onclick="togglePopup('usagePopup1455')">...<span class="popuptext" id="usagePopup1455">Usage of <b>Equations::log_equation_node</b>:<br><a href="20-eq.html#SP13">&#167;13</a>, <a href="20-eq.html#SP31">&#167;31</a>, <a href="20-eq.html#SP41_4">&#167;41.4</a>, <a href="20-eq.html#SP50_3_2">&#167;50.3.2</a>, <a href="20-eq.html#SP53">&#167;53</a></span></button></span><span class="plain">(</span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok</span><span class="plain">) {</span>
<span class="functiontext"><a href="20-eq.html#SP27">Equations::log_equation_node_inner</a></span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::log_equation_node_inner<button class="popup" onclick="togglePopup('usagePopup1456')">...<span class="popuptext" id="usagePopup1456">Usage of <b>Equations::log_equation_node_inner</b>:<br>none</span></button></span><span class="plain">(</span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">d</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">d</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">+1&lt;</span><span class="identifier">d</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" "</span><span class="plain">); </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"+---"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;NULL&gt;\n"</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">tok</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain"> == </span><span class="constant">OPERATION_EQN</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PLUS_OPERATION:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;add&gt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">MINUS_OPERATION:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;subtract&gt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">DIVIDE_OPERATION:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;divide&gt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TIMES_OPERATION:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;multiply&gt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">IMPLICIT_TIMES_OPERATION:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;implicitly multiply&gt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">IMPLICIT_APPLICATION_OPERATION:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;apply function&gt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">EQUALS_OPERATION:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;set equal&gt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">ROOT_OPERATION:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;square root&gt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">REALROOT_OPERATION:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;real square root&gt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CUBEROOT_OPERATION:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;cube root&gt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">POWER_OPERATION:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;to the power&gt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">UNARY_MINUS_OPERATION:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;unary subtraction&gt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;op-%d&gt;"</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain"> == </span><span class="constant">SYMBOL_EQN</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;symbol-%W&gt;"</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">name</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">tok</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain"> == </span><span class="constant">CONSTANT_EQN</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;constant-$P&gt;"</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">leaf_constant</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">tok</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain"> == </span><span class="constant">OPEN_BRACKET_EQN</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;open-bracket&gt;"</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">tok</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain"> == </span><span class="constant">CLOSE_BRACKET_EQN</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;close-bracket&gt;"</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">tok</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain"> == </span><span class="constant">END_EQN</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;end&gt;"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;bad-eqn&gt;\n"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">" : "</span><span class="plain">);</span>
<span class="identifier">Kinds::FloatingPoint::log_gk</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">", "</span><span class="plain">);</span>
<span class="identifier">Kinds::FloatingPoint::log_gk</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain"> == </span><span class="constant">OPERATION_EQN</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_arity</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="functiontext"><a href="20-eq.html#SP27">Equations::log_equation_node_inner</a></span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">d</span><span class="plain">+1);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP28"></a><b>&#167;28. Tokenising equations. </b>We break up the word range \((w_1, w_2)\) into tokens of equation matter. Word
boundaries divide tokens, but so do operators like <code class="display"><span class="extract">+</span></code>, and boundaries can
also occur in runs of alphanumerics if we spot symbol names: thus <code class="display"><span class="extract">mv^21</span></code>
will be divided into tokens <code class="display"><span class="extract">m</span></code>, <code class="display"><span class="extract">v</span></code>, <code class="display"><span class="extract">^</span></code>, <code class="display"><span class="extract">21</span></code>.
</p>
<p class="inwebparagraph">The following routine sends each token in turn to the shift/reduce parser
below, encoding each token as an enode. We return <code class="display"><span class="extract">NULL</span></code> if a problem message
has to be issued, or else a pointer to the parsed tree if we succeed.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_ENODES_IN_EXPRESSION</span><span class="plain"> </span><span class="constant">100</span>
</pre>
<pre class="display">
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="functiontext">Equations::eqn_parse<button class="popup" onclick="togglePopup('usagePopup1457')">...<span class="popuptext" id="usagePopup1457">Usage of <b>Equations::eqn_parse</b>:<br><a href="20-eq.html#SP13">&#167;13</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</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">eqn</span><span class="plain">-&gt;</span><span class="element">equation_text</span><span class="plain">;</span>
<span class="functiontext"><a href="20-eq.html#SP32">Equations::enode_sr_start</a></span><span class="plain">(); </span><span class="comment"> start the shift-reduce parser</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">previous_token</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">enode_count</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="comment"> number of tokens shipped so far</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">bl</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="comment"> bracket nesting level</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">wn</span><span class="plain"> = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">), </span><span class="identifier">i</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">wn</span><span class="plain"> &lt;= </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">W</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">p</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">i</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">Lexer::word_raw_text</span><span class="plain">(</span><span class="identifier">wn</span><span class="plain">++); }</span>
<span class="comment"> we are now at character <code class="display"><span class="extract">i</span></code> in string <code class="display"><span class="extract">p</span></code>, while <code class="display"><span class="extract">wn</span></code> is the next word</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">token</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Break off a token from the current position</span> <span class="cwebmacronumber">28.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Issue the token to the shift-reduce parser</span> <span class="cwebmacronumber">28.2</span>&gt;<span class="plain">;</span>
<span class="identifier">previous_token</span><span class="plain"> = </span><span class="identifier">token</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="identifier">i</span><span class="plain">] == </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP34">Equations::enode_sr_token</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="functiontext"><a href="20-eq.html#SP25">Equations::enode_new</a></span><span class="plain">(</span><span class="constant">END_EQN</span><span class="plain">)) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Equation fails in the shift-reduce parser</span> <span class="cwebmacronumber">28.3</span>&gt;<span class="plain">;</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">result</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP33">Equations::enode_sr_result</a></span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">bl</span><span class="plain"> != </span><span class="constant">0</span><span class="plain">) {</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="string">""</span><span class="plain">,</span>
<span class="string">"this seems to use brackets in a mismatched way, since there "</span>
<span class="string">"are different numbers of left and right brackets '(' and ')'."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">result</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP28_1"></a><b>&#167;28.1. </b>Note that symbol names can't begin with a digit.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Break off a token from the current position</span> <span class="cwebmacronumber">28.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Characters::isalpha</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">)) </span>&lt;<span class="cwebmacro">Break off a symbol name as a token</span> <span class="cwebmacronumber">28.1.1</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Characters::isdigit</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">)) </span>&lt;<span class="cwebmacro">Break off a numeric constant as a token</span> <span class="cwebmacronumber">28.1.2</span>&gt;
<span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Break off an operator or a piece of punctuation as a token</span> <span class="cwebmacronumber">28.1.3</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP28">&#167;28</a>.</p>
<p class="inwebparagraph"><a id="SP28_1_1"></a><b>&#167;28.1.1. </b>Note that symbols are identified by recognition: without knowing the identities
of the symbols, the syntax alone wouldn't tell us how to break them. We can only
break <code class="display"><span class="extract">mc^2</span></code> as <code class="display"><span class="extract">m</span></code> followed by <code class="display"><span class="extract">c^2</span></code> if we know that <code class="display"><span class="extract">m</span></code> and <code class="display"><span class="extract">c</span></code> are symbols,
rather than <code class="display"><span class="extract">mc</span></code>. (This is one reason why most programming languages don't
allow implicit multiplication.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Break off a symbol name as a token</span> <span class="cwebmacronumber">28.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">text_of_symbol</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="comment"> the length of the symbol name we try to break off</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;14) &amp;&amp; (</span><span class="identifier">Characters::isalnum</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+</span><span class="identifier">j</span><span class="plain">])) &amp;&amp; (</span><span class="identifier">token</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">); </span><span class="identifier">j</span><span class="plain">++)</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">text_of_symbol</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+</span><span class="identifier">j</span><span class="plain">]);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">standard_equation_symbols</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Look for this symbol name</span> <span class="cwebmacronumber">28.1.1.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">token</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">=1; (</span><span class="identifier">j</span><span class="plain">&lt;15) &amp;&amp; (</span><span class="identifier">Characters::isalnum</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+</span><span class="identifier">j</span><span class="plain">-1])) &amp;&amp; (</span><span class="identifier">token</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">); </span><span class="identifier">j</span><span class="plain">++) {</span>
<span class="comment"> copy the first <code class="display"><span class="extract">j</span></code> characters into a C string:</span>
<span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">text_of_symbol</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain">=0; </span><span class="identifier">k</span><span class="plain">&lt;</span><span class="identifier">j</span><span class="plain">; </span><span class="identifier">k</span><span class="plain">++) </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">text_of_symbol</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+</span><span class="identifier">k</span><span class="plain">]);</span>
<span class="comment"> try to identify this as one of the declared symbols:</span>
<span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">ev</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">symbol_list</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Look for this symbol name</span> <span class="cwebmacronumber">28.1.1.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">token</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_problem_S</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationTokenUnrecognised</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">text_of_symbol</span><span class="plain">,</span>
<span class="string">"the symbol '%3' is one that I don't recognise. It doesn't "</span>
<span class="string">"seem to be declared after the equation - for instance, "</span>
<span class="string">"by adding 'where %3 is a number'."</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">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">text_of_symbol</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP28_1">&#167;28.1</a>.</p>
<p class="inwebparagraph"><a id="SP28_1_1_1"></a><b>&#167;28.1.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Look for this symbol name</span> <span class="cwebmacronumber">28.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">text_of_symbol</span><span class="plain">, </span><span class="identifier">Lexer::word_raw_text</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">)))) {</span>
<span class="identifier">token</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP26">Equations::enode_new_symbol</a></span><span class="plain">(</span><span class="identifier">ev</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain"> += </span><span class="identifier">j</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP28_1_1">&#167;28.1.1</a> (twice).</p>
<p class="inwebparagraph"><a id="SP28_1_2"></a><b>&#167;28.1.2. </b>The following is reliable because a string of digits not starting with a
0 is always a valid number to Inform unless it overflows the virtual machine's
capacity; and so is the number 0 itself.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Break off a numeric constant as a token</span> <span class="cwebmacronumber">28.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == </span><span class="character">'0'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Characters::isdigit</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1]))) {</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationLeadingZero</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="string">""</span><span class="plain">,</span>
<span class="string">"a number in an equation isn't allowed to begin with a "</span>
<span class="string">"'0' digit, so an equation like 'M = 007+Q' is against the rules."</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">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">text_of_number</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Copy the literal number into a C string, flanked by spaces</span> <span class="cwebmacronumber">28.1.2.1</span>&gt;<span class="plain">;</span>
<span class="comment"> now sneakily add this to the word stream, and let the S-parser read it:</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">NW</span><span class="plain"> = </span><span class="identifier">Feeds::feed_stream</span><span class="plain">(</span><span class="identifier">text_of_number</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">text_of_number</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"> (&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">type</span><span class="plain">-</span><span class="identifier">expression</span><span class="plain">&gt;(</span><span class="identifier">NW</span><span class="plain">)) </span><span class="identifier">spec</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="string">""</span><span class="plain">,</span>
<span class="string">"there's a literal number in that equation which doesn't make "</span>
<span class="string">"sense to me."</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="comment"> this can only go wrong if there was an overflow, and a problem will have been issued for that:</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">CONSTANT_NT</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">NULL</span><span class="plain">;</span>
<span class="identifier">token</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP26">Equations::enode_new_constant</a></span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP28_1">&#167;28.1</a>.</p>
<p class="inwebparagraph"><a id="SP28_1_2_1"></a><b>&#167;28.1.2.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Copy the literal number into a C string, flanked by spaces</span> <span class="cwebmacronumber">28.1.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">Characters::isdigit</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])) </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">text_of_number</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++]);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == </span><span class="character">'.'</span><span class="plain">) {</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">text_of_number</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++]);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">Characters::isdigit</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])) </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">text_of_number</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++]);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext"><a href="10-pl.html#SP6">Literals::ismultiplicationsign</a></span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1] == </span><span class="character">'1'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+2] == </span><span class="character">'0'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+3] == </span><span class="character">'^'</span><span class="plain">)) {</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">text_of_number</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++]);</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">text_of_number</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++]);</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">text_of_number</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++]);</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">text_of_number</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++]);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">Characters::isdigit</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])) </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">text_of_number</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++]);</span>
<span class="plain">}</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">text_of_number</span><span class="plain">, </span><span class="character">' '</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP28_1_2">&#167;28.1.2</a>.</p>
<p class="inwebparagraph"><a id="SP28_1_3"></a><b>&#167;28.1.3. </b>Which leaves just the easiest case:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Break off an operator or a piece of punctuation as a token</span> <span class="cwebmacronumber">28.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'='</span><span class="plain">: </span><span class="identifier">token</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP26">Equations::enode_new_op</a></span><span class="plain">(</span><span class="identifier">EQUALS_OPERATION</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="character">'+'</span><span class="plain">: </span><span class="identifier">token</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP26">Equations::enode_new_op</a></span><span class="plain">(</span><span class="identifier">PLUS_OPERATION</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="character">'-'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">previous_token</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">previous_token</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain"> == </span><span class="constant">OPERATION_EQN</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">previous_token</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain"> == </span><span class="constant">OPEN_BRACKET_EQN</span><span class="plain">))</span>
<span class="identifier">token</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP26">Equations::enode_new_op</a></span><span class="plain">(</span><span class="identifier">UNARY_MINUS_OPERATION</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">token</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP26">Equations::enode_new_op</a></span><span class="plain">(</span><span class="identifier">MINUS_OPERATION</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="character">'/'</span><span class="plain">: </span><span class="identifier">token</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP26">Equations::enode_new_op</a></span><span class="plain">(</span><span class="identifier">DIVIDE_OPERATION</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="character">'*'</span><span class="plain">: </span><span class="identifier">token</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP26">Equations::enode_new_op</a></span><span class="plain">(</span><span class="identifier">TIMES_OPERATION</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="character">'^'</span><span class="plain">: </span><span class="identifier">token</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP26">Equations::enode_new_op</a></span><span class="plain">(</span><span class="identifier">POWER_OPERATION</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="character">'('</span><span class="plain">: </span><span class="identifier">token</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP25">Equations::enode_new</a></span><span class="plain">(</span><span class="constant">OPEN_BRACKET_EQN</span><span class="plain">); </span><span class="identifier">bl</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="character">')'</span><span class="plain">: </span><span class="identifier">token</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP25">Equations::enode_new</a></span><span class="plain">(</span><span class="constant">CLOSE_BRACKET_EQN</span><span class="plain">); </span><span class="identifier">bl</span><span class="plain">--; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span><span class="plain"> {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">symbol</span><span class="plain">);</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">symbol</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_problem_S</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationOperatorUnrecognised</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">symbol</span><span class="plain">,</span>
<span class="string">"the symbol '%3' is one that I don't recognise. I was "</span>
<span class="string">"expecting an arithmetic sign, '+', '-', '*','/', or '^', "</span>
<span class="string">"or else '=' or a bracket '(' or ')'."</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Bad operator '%S'\n"</span><span class="plain">, </span><span class="identifier">symbol</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="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">symbol</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">i</span><span class="plain">++;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP28_1">&#167;28.1</a>.</p>
<p class="inwebparagraph"><a id="SP28_2"></a><b>&#167;28.2. </b>So now we have our next token, and are ready to ship it. But if we
detect an implicit multiplication, for instance between <code class="display"><span class="extract">m</span></code> and <code class="display"><span class="extract">c^2</span></code>
in <code class="display"><span class="extract">E=mc^2</span></code>, we issue that as an <code class="display"><span class="extract">IMPLICIT_TIMES_OPERATION</span></code> enode in
between; and in <code class="display"><span class="extract">log pi</span></code> we issue an <code class="display"><span class="extract">IMPLICIT_APPLICATION_OPERATION</span></code>.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue the token to the shift-reduce parser</span> <span class="cwebmacronumber">28.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP30">Equations::application_is_implied</a></span><span class="plain">(</span><span class="identifier">previous_token</span><span class="plain">, </span><span class="identifier">token</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP34">Equations::enode_sr_token</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="functiontext"><a href="20-eq.html#SP26">Equations::enode_new_op</a></span><span class="plain">(</span><span class="constant">IMPLICIT_APPLICATION_OPERATION</span><span class="plain">)) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Equation fails in the shift-reduce parser</span> <span class="cwebmacronumber">28.3</span>&gt;<span class="plain">;</span>
<span class="identifier">enode_count</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="functiontext"><a href="20-eq.html#SP29">Equations::multiplication_is_implied</a></span><span class="plain">(</span><span class="identifier">previous_token</span><span class="plain">, </span><span class="identifier">token</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP34">Equations::enode_sr_token</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="functiontext"><a href="20-eq.html#SP26">Equations::enode_new_op</a></span><span class="plain">(</span><span class="constant">IMPLICIT_TIMES_OPERATION</span><span class="plain">)) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Equation fails in the shift-reduce parser</span> <span class="cwebmacronumber">28.3</span>&gt;<span class="plain">;</span>
<span class="identifier">enode_count</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP34">Equations::enode_sr_token</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">token</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Equation fails in the shift-reduce parser</span> <span class="cwebmacronumber">28.3</span>&gt;<span class="plain">;</span>
<span class="identifier">enode_count</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">enode_count</span><span class="plain"> &gt;= </span><span class="constant">MAX_ENODES_IN_EXPRESSION</span><span class="plain"> - </span><span class="constant">2</span><span class="plain">) {</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationTooComplex</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="string">""</span><span class="plain">,</span>
<span class="string">"this is too long and complex an equation."</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">This code is used in <a href="20-eq.html#SP28">&#167;28</a>.</p>
<p class="inwebparagraph"><a id="SP28_3"></a><b>&#167;28.3. </b>In case any of the enode insertions fail. It's tricky to generate good error
messages and recover well when an operator-precedence grammar fails to match in
a parser like this, so we'll fall back on this:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Equation fails in the shift-reduce parser</span> <span class="cwebmacronumber">28.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationMispunctuated</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="string">""</span><span class="plain">,</span>
<span class="string">"this seems to be wrongly punctuated, and doesn't make sense as a "</span>
<span class="string">"mathematical formula."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP28">&#167;28</a>, <a href="20-eq.html#SP28_2">&#167;28.2</a> (three times).</p>
<p class="inwebparagraph"><a id="SP29"></a><b>&#167;29. </b>Lastly, here is when multiplication is implied:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::multiplication_is_implied<button class="popup" onclick="togglePopup('usagePopup1458')">...<span class="popuptext" id="usagePopup1458">Usage of <b>Equations::multiplication_is_implied</b>:<br><a href="20-eq.html#SP28_2">&#167;28.2</a></span></button></span><span class="plain">(</span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">previous_token</span><span class="plain">, </span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">token</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">lt</span><span class="plain">, </span><span class="identifier">rt</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">token</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">previous_token</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">FALSE</span><span class="plain">;</span>
<span class="identifier">lt</span><span class="plain"> = </span><span class="identifier">previous_token</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain">; </span><span class="identifier">rt</span><span class="plain"> = </span><span class="identifier">token</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (((</span><span class="identifier">lt</span><span class="plain"> == </span><span class="constant">SYMBOL_EQN</span><span class="plain">) || (</span><span class="identifier">lt</span><span class="plain"> == </span><span class="constant">CONSTANT_EQN</span><span class="plain">) || (</span><span class="identifier">lt</span><span class="plain"> == </span><span class="constant">CLOSE_BRACKET_EQN</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">((</span><span class="identifier">rt</span><span class="plain"> == </span><span class="constant">SYMBOL_EQN</span><span class="plain">) || (</span><span class="identifier">rt</span><span class="plain"> == </span><span class="constant">CONSTANT_EQN</span><span class="plain">) || (</span><span class="identifier">rt</span><span class="plain"> == </span><span class="constant">OPEN_BRACKET_EQN</span><span class="plain">)))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP30"></a><b>&#167;30. </b>And when function application is implied:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::application_is_implied<button class="popup" onclick="togglePopup('usagePopup1459')">...<span class="popuptext" id="usagePopup1459">Usage of <b>Equations::application_is_implied</b>:<br><a href="20-eq.html#SP28_2">&#167;28.2</a></span></button></span><span class="plain">(</span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">previous_token</span><span class="plain">, </span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">token</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">lt</span><span class="plain">, </span><span class="identifier">rt</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">token</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">previous_token</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">FALSE</span><span class="plain">;</span>
<span class="identifier">lt</span><span class="plain"> = </span><span class="identifier">previous_token</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain">; </span><span class="identifier">rt</span><span class="plain"> = </span><span class="identifier">token</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">lt</span><span class="plain"> == </span><span class="constant">SYMBOL_EQN</span><span class="plain">) &amp;&amp; (</span><span class="identifier">previous_token</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">function_notated</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP31"></a><b>&#167;31. The shift-reduce parser. </b>This is a classic algorithm for expression-evaluator grammars; see for
instance Aho, Sethi and Ullman, "Compilers", section 4.6 in the second edition.
We use a pair of stacks. The SR stack holds possible attempts to understand
what we have so far, given the tokens that have arrived; the emitter stack
holds nodes which form pieces of the output tree as it is assembled. Nodes
flow from our input, are usually "shifted" onto the SR stack for a while,
are eventually "reduced" in clumps taken off this stack and "emitted",
then go onto the emitter stack, and are finally removed as they are made
into trees.
</p>
<p class="inwebparagraph">The flow is therefore always forwards; tokens can't slosh back and forth
between the stacks. On each iteration, at least one token makes progress,
so if there are \(N\) tokens of input (including both end marker tokens) then we
take at worst \(2N\) steps to finish. Each stack can't need more than \(N\)
entries, and \(N\) is bounded above by <code class="display"><span class="extract">MAX_ENODES_IN_EXPRESSION</span></code> plus 2
(allowing for the end markers). So:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">SR_sp</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">SR_stack</span><span class="plain">[</span><span class="constant">MAX_ENODES_IN_EXPRESSION</span><span class="plain">+2];</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">emitter_sp</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">emitter_stack</span><span class="plain">[</span><span class="constant">MAX_ENODES_IN_EXPRESSION</span><span class="plain">+2];</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::log_sr_stacks<button class="popup" onclick="togglePopup('usagePopup1460')">...<span class="popuptext" id="usagePopup1460">Usage of <b>Equations::log_sr_stacks</b>:<br>none</span></button></span><span class="plain">(</span><span class="reserved">void</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">LOG</span><span class="plain">(</span><span class="string">"SR: "</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">SR_sp</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" %d: "</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">); </span><span class="functiontext"><a href="20-eq.html#SP27">Equations::log_equation_node</a></span><span class="plain">(</span><span class="identifier">SR_stack</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]); }</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"EMITTER: "</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">emitter_sp</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" %d: "</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">); </span><span class="functiontext"><a href="20-eq.html#SP27">Equations::log_equation_node</a></span><span class="plain">(</span><span class="identifier">emitter_stack</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]); }</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP32"></a><b>&#167;32. </b>The start and finish are as follows. At the start, the emitter stack is
empty and the SR stack contains an <code class="display"><span class="extract">END_EQN</span></code> token, which represents the
left-hand end of the expression. (Another such token, this time representing the
right-hand end, will be sent by the routines above at the end of the stream. So
there will be two <code class="display"><span class="extract">END_EQN</span></code> tokens in play.)
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::enode_sr_start<button class="popup" onclick="togglePopup('usagePopup1461')">...<span class="popuptext" id="usagePopup1461">Usage of <b>Equations::enode_sr_start</b>:<br><a href="20-eq.html#SP28">&#167;28</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">SR_stack</span><span class="plain">[0] = </span><span class="functiontext"><a href="20-eq.html#SP25">Equations::enode_new</a></span><span class="plain">(</span><span class="constant">END_EQN</span><span class="plain">);</span>
<span class="identifier">SR_sp</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">emitter_sp</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP33"></a><b>&#167;33. </b>If we have succeeded, the end state of the emitter stack contains a single
node: the head of the tree we have grown to represent the expression.
</p>
<pre class="display">
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="functiontext">Equations::enode_sr_result<button class="popup" onclick="togglePopup('usagePopup1462')">...<span class="popuptext" id="usagePopup1462">Usage of <b>Equations::enode_sr_result</b>:<br><a href="20-eq.html#SP28">&#167;28</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">emitter_stack</span><span class="plain">[0];</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP34"></a><b>&#167;34. </b>So the following is the routine which iteratively deals with tokens as
they arrive. As noted above, the loop however ominous always terminates.
</p>
<p class="inwebparagraph">For proofs and explanations see ASU, but the idea is simple enough: as we
see the expression a little at a time, we collect possibilities of how to
read it on the SR-stack, until we reach a point where it's possible to tell
what was meant; we then reduce the SR-stack by taking the winning possibility
off the top and moving it to the emitter stack. For instance, if we have
read <code class="display"><span class="extract">4 + 5</span></code> then we don't know yet whether the <code class="display"><span class="extract">+</span></code> will add the 4 to the 5;
if the next token is <code class="display"><span class="extract">+</span></code> or <code class="display"><span class="extract">END_EQN</span></code> then it will, but if the next token
is <code class="display"><span class="extract">*</span></code> then it won't, because we're looking at something like <code class="display"><span class="extract">4 + 5 * 6</span></code>.
</p>
<p class="inwebparagraph">If the next token is of lower precedence than <code class="display"><span class="extract">+</span></code> then we "reduce" &mdash;
telling the emitter about the addition, which we now understand &mdash; but if
it's higher, as with <code class="display"><span class="extract">*</span></code>, then we "shift", meaning, we postpone worrying
about the addition and start worrying about the multiplication instead;
our new problem, working out what <code class="display"><span class="extract">*</span></code> applies to, sits on top of the
addition problem on the SR-stack.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::enode_sr_token<button class="popup" onclick="togglePopup('usagePopup1463')">...<span class="popuptext" id="usagePopup1463">Usage of <b>Equations::enode_sr_token</b>:<br><a href="20-eq.html#SP28">&#167;28</a>, <a href="20-eq.html#SP28_2">&#167;28.2</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">, </span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">safety_cutout</span><span class="plain"> = </span><span class="constant">3</span><span class="plain">*</span><span class="constant">MAX_ENODES_IN_EXPRESSION</span><span class="plain">;</span>
<span class="reserved">while</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">SR_sp</span><span class="plain"> &lt;= </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"SR stack empty"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">SR_stack</span><span class="plain">[</span><span class="identifier">SR_sp</span><span class="plain">-1]-&gt;</span><span class="element">eqn_type</span><span class="plain"> == </span><span class="constant">END_EQN</span><span class="plain">) &amp;&amp; (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain"> == </span><span class="constant">END_EQN</span><span class="plain">)) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext"><a href="20-eq.html#SP36">Equations::enode_lt</a></span><span class="plain">(</span><span class="identifier">SR_stack</span><span class="plain">[</span><span class="identifier">SR_sp</span><span class="plain">-1], </span><span class="identifier">tok</span><span class="plain">)) || (</span><span class="functiontext"><a href="20-eq.html#SP36">Equations::enode_eq</a></span><span class="plain">(</span><span class="identifier">SR_stack</span><span class="plain">[</span><span class="identifier">SR_sp</span><span class="plain">-1], </span><span class="identifier">tok</span><span class="plain">)))</span>
&lt;<span class="cwebmacro">Shift an enode onto the SR-stack</span> <span class="cwebmacronumber">34.1</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP36">Equations::enode_gt</a></span><span class="plain">(</span><span class="identifier">SR_stack</span><span class="plain">[</span><span class="identifier">SR_sp</span><span class="plain">-1], </span><span class="identifier">tok</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Reduce some enodes from the SR-stack to the emitter stack</span> <span class="cwebmacronumber">34.2</span>&gt;
<span class="reserved">else</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">if</span><span class="plain"> (</span><span class="identifier">safety_cutout</span><span class="plain">-- &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"SR parser deadlocked"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">emitter_sp</span><span class="plain"> != </span><span class="constant">1</span><span class="plain">) || (</span><span class="identifier">SR_sp</span><span class="plain"> != </span><span class="constant">1</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="inwebparagraph"><a id="SP34_1"></a><b>&#167;34.1. </b>After shifting, we return a signal of success, which asks for the next
token to be sent.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Shift an enode onto the SR-stack</span> <span class="cwebmacronumber">34.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">SR_stack</span><span class="plain">[</span><span class="identifier">SR_sp</span><span class="plain">++] = </span><span class="identifier">tok</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP34">&#167;34</a>.</p>
<p class="inwebparagraph"><a id="SP34_2"></a><b>&#167;34.2. </b>The ASU book is a little vague about what happens if there is an underflow
here, I think because it's possible to set up the grammar such that an
underflow cannot occur. But I can see no obvious proof that it will never
occur for us given syntactically incorrect input, so we will return <code class="display"><span class="extract">FALSE</span></code>
on an underflow to be safe.
</p>
<p class="inwebparagraph">Note that we can never emit the bottom-most token on the SR stack: that's the
left-hand end marker, so can never be validly part of any arithmetic. So
an underflow occurs if that's all that's left, i.e., when the SR stack pointer
is 1, not 0.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Reduce some enodes from the SR-stack to the emitter stack</span> <span class="cwebmacronumber">34.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">do</span><span class="plain"> { </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">SR_sp</span><span class="plain"> &lt;= </span><span class="constant">1</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">if</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP35">Equations::enode_emit</a></span><span class="plain">(</span><span class="identifier">SR_stack</span><span class="plain">[--</span><span class="identifier">SR_sp</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="plain">} </span><span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">SR_sp</span><span class="plain"> &gt;= </span><span class="constant">1</span><span class="plain">) &amp;&amp; (</span><span class="functiontext"><a href="20-eq.html#SP36">Equations::enode_lt</a></span><span class="plain">(</span><span class="identifier">SR_stack</span><span class="plain">[</span><span class="identifier">SR_sp</span><span class="plain">-1], </span><span class="identifier">SR_stack</span><span class="plain">[</span><span class="identifier">SR_sp</span><span class="plain">]) == </span><span class="identifier">FALSE</span><span class="plain">));</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP34">&#167;34</a>.</p>
<p class="inwebparagraph"><a id="SP35"></a><b>&#167;35. </b>The key point is that if nodes arrive at the SR parser in their
ordinary order of mathematical writing, then they "reduce" off the
SR stack and onto the emitter stack in reverse Polish notation order.
Thus the sequence <code class="display"><span class="extract">4 + 2 * 7</span></code> is emitted as <code class="display"><span class="extract">4 2 7 * +</span></code>. RPN has no
need of brackets to clarify the sequence of operation, and it's very
easy to build a tree from.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::enode_emit<button class="popup" onclick="togglePopup('usagePopup1464')">...<span class="popuptext" id="usagePopup1464">Usage of <b>Equations::enode_emit</b>:<br><a href="20-eq.html#SP34_2">&#167;34.2</a></span></button></span><span class="plain">(</span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">SYMBOL_EQN:</span><span class="plain"> </span><span class="reserved">case</span><span class="plain"> </span><span class="identifier">CONSTANT_EQN:</span>
<span class="identifier">emitter_stack</span><span class="plain">[</span><span class="identifier">emitter_sp</span><span class="plain">++] = </span><span class="identifier">tok</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">OPERATION_EQN:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain"> == </span><span class="constant">IMPLICIT_TIMES_OPERATION</span><span class="plain">)</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain"> = </span><span class="identifier">TIMES_OPERATION</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain"> == </span><span class="constant">IMPLICIT_APPLICATION_OPERATION</span><span class="plain">)</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_arity</span><span class="plain"> = </span><span class="constant">2</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Dimensions::arithmetic_op_is_unary</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain">))</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_arity</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">else</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_arity</span><span class="plain"> = </span><span class="constant">2</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"> = </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_arity</span><span class="plain"> - </span><span class="constant">1</span><span class="plain">; </span><span class="identifier">i</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">--) {</span>
<span class="identifier">emitter_sp</span><span class="plain">--;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">emitter_sp</span><span class="plain"> &lt; </span><span class="constant">0</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="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">emitter_stack</span><span class="plain">[</span><span class="identifier">emitter_sp</span><span class="plain">];</span>
<span class="plain">}</span>
<span class="identifier">emitter_stack</span><span class="plain">[</span><span class="identifier">emitter_sp</span><span class="plain">++] = </span><span class="identifier">tok</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</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="inwebparagraph"><a id="SP36"></a><b>&#167;36. </b>All we need now is to decide the order of precedence of our tokens,
though this isn't as simple as it looks, because they are not all
symmetrical left-right. That's obviously true of things like an open
bracket <code class="display"><span class="extract">(</span></code>, which affects the stuff to the left very differently from
the stuff to the right. But it is also true of operators. <code class="display"><span class="extract">+</span></code> may be
associative mathematically, but in computing there's a difference
between evaluating <code class="display"><span class="extract">a + (b+c)</span></code> and <code class="display"><span class="extract">(a+b) + c</span></code>.
</p>
<p class="inwebparagraph">All of this means there's no simple order relationship on the tokens,
where \(T&lt;S\) if and only if \(S&gt;T\). We order them using a numerical score,
but they get one score \(f(T)\) if they appear on the left and another
score \(g(T)\) if they appear on the right:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::enode_lt<button class="popup" onclick="togglePopup('usagePopup1465')">...<span class="popuptext" id="usagePopup1465">Usage of <b>Equations::enode_lt</b>:<br><a href="20-eq.html#SP34">&#167;34</a>, <a href="20-eq.html#SP34_2">&#167;34.2</a></span></button></span><span class="plain">(</span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok1</span><span class="plain">, </span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok2</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">f_left</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP37">Equations::f_function</a></span><span class="plain">(</span><span class="identifier">tok1</span><span class="plain">), </span><span class="identifier">g_right</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP38">Equations::g_function</a></span><span class="plain">(</span><span class="identifier">tok2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">f_left</span><span class="plain"> &lt; </span><span class="identifier">g_right</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::enode_eq<button class="popup" onclick="togglePopup('usagePopup1466')">...<span class="popuptext" id="usagePopup1466">Usage of <b>Equations::enode_eq</b>:<br><a href="20-eq.html#SP34">&#167;34</a></span></button></span><span class="plain">(</span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok1</span><span class="plain">, </span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok2</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">f_left</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP37">Equations::f_function</a></span><span class="plain">(</span><span class="identifier">tok1</span><span class="plain">), </span><span class="identifier">g_right</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP38">Equations::g_function</a></span><span class="plain">(</span><span class="identifier">tok2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">f_left</span><span class="plain"> == </span><span class="identifier">g_right</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::enode_gt<button class="popup" onclick="togglePopup('usagePopup1467')">...<span class="popuptext" id="usagePopup1467">Usage of <b>Equations::enode_gt</b>:<br><a href="20-eq.html#SP34">&#167;34</a></span></button></span><span class="plain">(</span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok1</span><span class="plain">, </span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok2</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">f_left</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP37">Equations::f_function</a></span><span class="plain">(</span><span class="identifier">tok1</span><span class="plain">), </span><span class="identifier">g_right</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP38">Equations::g_function</a></span><span class="plain">(</span><span class="identifier">tok2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">f_left</span><span class="plain"> &gt; </span><span class="identifier">g_right</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP37"></a><b>&#167;37. </b>And here are those scorings. Note that for the binary operators, \(f\)
scores are usually slightly higher than \(g\) scores: that's what makes
them left associative, that is, \(a+b+c\) is read as \((a+b)+c\). The
exception to this is raising to powers: <code class="display"><span class="extract">a^2^3</span></code> evaluates \(a^8\), not
\(a^6\), because it is read as <code class="display"><span class="extract">a^(2^3)</span></code>.
</p>
<p class="inwebparagraph">Implicit multiplication has higher precedence than explicit. This is
actually to give it higher precedence than division (which has to have
the same precedence as explicit multiplication), and is so that
<code class="display"><span class="extract">ab/cd</span></code> evaluates \((ab)/(cd)\) rather than \(a\cdot (b/c)\cdot d\).
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::f_function<button class="popup" onclick="togglePopup('usagePopup1468')">...<span class="popuptext" id="usagePopup1468">Usage of <b>Equations::f_function</b>:<br><a href="20-eq.html#SP36">&#167;36</a></span></button></span><span class="plain">(</span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">SYMBOL_EQN:</span><span class="plain"> </span><span class="reserved">case</span><span class="plain"> </span><span class="identifier">CONSTANT_EQN:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">16</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">OPERATION_EQN:</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">EQUALS_OPERATION:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">2</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PLUS_OPERATION:</span><span class="plain"> </span><span class="reserved">case</span><span class="plain"> </span><span class="identifier">MINUS_OPERATION:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">4</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TIMES_OPERATION:</span><span class="plain"> </span><span class="reserved">case</span><span class="plain"> </span><span class="identifier">DIVIDE_OPERATION:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">6</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">IMPLICIT_TIMES_OPERATION:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">8</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">POWER_OPERATION:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">9</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">IMPLICIT_APPLICATION_OPERATION:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">5</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">UNARY_MINUS_OPERATION:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">1</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"unknown operator precedence"</span><span class="plain">);</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">OPEN_BRACKET_EQN:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CLOSE_BRACKET_EQN:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">16</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">END_EQN:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"unknown f-value"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP38"></a><b>&#167;38. </b>And symmetrically:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::g_function<button class="popup" onclick="togglePopup('usagePopup1469')">...<span class="popuptext" id="usagePopup1469">Usage of <b>Equations::g_function</b>:<br><a href="20-eq.html#SP36">&#167;36</a></span></button></span><span class="plain">(</span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">SYMBOL_EQN:</span><span class="plain"> </span><span class="reserved">case</span><span class="plain"> </span><span class="identifier">CONSTANT_EQN:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">15</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">OPERATION_EQN:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">) </span><span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">EQUALS_OPERATION:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PLUS_OPERATION:</span><span class="plain"> </span><span class="reserved">case</span><span class="plain"> </span><span class="identifier">MINUS_OPERATION:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">3</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TIMES_OPERATION:</span><span class="plain"> </span><span class="reserved">case</span><span class="plain"> </span><span class="identifier">DIVIDE_OPERATION:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">5</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">IMPLICIT_TIMES_OPERATION:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">7</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">POWER_OPERATION:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">10</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">IMPLICIT_APPLICATION_OPERATION:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">14</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">UNARY_MINUS_OPERATION:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">12</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"unknown operator precedence"</span><span class="plain">);</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">OPEN_BRACKET_EQN:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">15</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CLOSE_BRACKET_EQN:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">END_EQN:</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"unknown g-value"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP39"></a><b>&#167;39. Typechecking equations. </b>The SR parser can generate trees for any syntactically valid equation, but
it may be something using <code class="display"><span class="extract">=</span></code> inappropriately or not at all. We rule that
out first: we want the top node in the tree to be the unique <code class="display"><span class="extract">=</span></code> operator.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::eqn_typecheck<button class="popup" onclick="togglePopup('usagePopup1470')">...<span class="popuptext" id="usagePopup1470">Usage of <b>Equations::eqn_typecheck</b>:<br><a href="20-eq.html#SP13">&#167;13</a>, <a href="20-eq.html#SP47_2">&#167;47.2</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP40">Equations::enode_count_equals</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">)) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">0</span><span class="plain">:</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationDoesntEquate</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="string">""</span><span class="plain">,</span>
<span class="string">"this equation doesn't seem to contain an equals sign, and "</span>
<span class="string">"without '=' there is no equating anything with anything."</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">case</span><span class="plain"> </span><span class="constant">1</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP40">Equations::enode_is_equals</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationEquatesBadly</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="string">""</span><span class="plain">,</span>
<span class="string">"the equals sign '=' here seems to be buried inside the "</span>
<span class="string">"formula, not at the surface. For instance, 'F = ma' is "</span>
<span class="string">"fine, but 'F(m=a)' would not make sense - the '=' would "</span>
<span class="string">"be inside brackets."</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">break</span><span class="plain">;</span>
<span class="identifier">default:</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationEquatesMultiply</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="string">""</span><span class="plain">,</span>
<span class="string">"this equation seems to contain more than one equals "</span>
<span class="string">"sign '='."</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">return</span><span class="plain"> </span><span class="functiontext"><a href="20-eq.html#SP41">Equations::enode_typecheck</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP40"></a><b>&#167;40. </b>A recursive count of instances down the tree from <code class="display"><span class="extract">tok</span></code>:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::enode_count_equals<button class="popup" onclick="togglePopup('usagePopup1471')">...<span class="popuptext" id="usagePopup1471">Usage of <b>Equations::enode_count_equals</b>:<br><a href="20-eq.html#SP39">&#167;39</a></span></button></span><span class="plain">(</span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP40">Equations::enode_is_equals</a></span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">)) </span><span class="identifier">c</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">tok</span><span class="plain">-&gt;</span><span class="element">enode_arity</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="identifier">c</span><span class="plain"> += </span><span class="functiontext"><a href="20-eq.html#SP40">Equations::enode_count_equals</a></span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</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>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::enode_is_equals<button class="popup" onclick="togglePopup('usagePopup1472')">...<span class="popuptext" id="usagePopup1472">Usage of <b>Equations::enode_is_equals</b>:<br><a href="20-eq.html#SP39">&#167;39</a></span></button></span><span class="plain">(</span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</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">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="identifier">eqn_type</span><span class="plain"> == </span><span class="constant">OPERATION_EQN</span><span class="plain">) &amp;&amp; (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain"> == </span><span class="identifier">EQUALS_OPERATION</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP41"></a><b>&#167;41. </b>Now we come to the real typechecking. The following is called, depth-first,
at each node in the equation; it has to assign a kind at every node, in such
a way that all operations are dimensionally valid. We return <code class="display"><span class="extract">FALSE</span></code> if we
are obliged to issue a problem message.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">float_terminal_nodes</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="functiontext">Equations::enode_typecheck<button class="popup" onclick="togglePopup('usagePopup1473')">...<span class="popuptext" id="usagePopup1473">Usage of <b>Equations::enode_typecheck</b>:<br><a href="20-eq.html#SP39">&#167;39</a>, <a href="20-eq.html#SP42">&#167;42</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">, </span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">result</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">tok</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">result</span><span class="plain">;</span>
<span class="identifier">LOG_INDENT</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">tok</span><span class="plain">-&gt;</span><span class="element">enode_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"><a href="20-eq.html#SP41">Equations::enode_typecheck</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
<span class="identifier">result</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">result</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">SYMBOL_EQN:</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain"> =</span>
<span class="identifier">Kinds::FloatingPoint::new_gk</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">var_kind</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CONSTANT_EQN:</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain"> =</span>
<span class="identifier">Kinds::FloatingPoint::new_gk</span><span class="plain">(</span>
<span class="identifier">ParseTree::get_kind_of_value</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">leaf_constant</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="identifier">enode_promotion</span><span class="plain">) &amp;&amp; (</span><span class="functiontext"><a href="13-rsfk.html#SP26">Kinds::RunTime::target_VM_supports</a></span><span class="plain">(</span><span class="identifier">K_real_number</span><span class="plain">)))</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain"> =</span>
<span class="identifier">Kinds::FloatingPoint::to_real</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">OPERATION_EQN:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain"> == </span><span class="identifier">EQUALS_OPERATION</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Typecheck the set-equals node at the top level</span> <span class="cwebmacronumber">41.1</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain"> == </span><span class="identifier">POWER_OPERATION</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Typecheck a raise-to-integer-power node</span> <span class="cwebmacronumber">41.2</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain"> == </span><span class="constant">IMPLICIT_APPLICATION_OPERATION</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Typecheck a function application node</span> <span class="cwebmacronumber">41.3</span>&gt;
<span class="reserved">else</span>
&lt;<span class="cwebmacro">Typecheck a general operation node</span> <span class="cwebmacronumber">41.4</span>&gt;<span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"forbidden enode found in parsed equation"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain"> = </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">float_terminal_nodes</span><span class="plain">) &amp;&amp; (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_arity</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">))</span>
<span class="functiontext"><a href="20-eq.html#SP42">Equations::promote_subequation</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">result</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP41_1"></a><b>&#167;41.1. </b>If we know that we need a real rather than integer answer, that has to
propagate downwards from the equality into the trees on either side, casting
integers to reals.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Typecheck the set-equals node at the top level</span> <span class="cwebmacronumber">41.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0]-&gt;</span><span class="element">gK_after</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">gK_after</span><span class="plain">);</span>
<span class="identifier">L</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::integer_equivalent</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">R</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::integer_equivalent</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">result</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">"Tried to equate $u and $u\n"</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">);</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationIncomparable</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="string">""</span><span class="plain">,</span>
<span class="string">"this equation tries to set two values equal which have "</span>
<span class="string">"different kinds from each other."</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">lf</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::is_real</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0]-&gt;</span><span class="element">gK_after</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rf</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::is_real</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">gK_after</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">lf</span><span class="plain"> == </span><span class="identifier">TRUE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">rf</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)) </span><span class="functiontext"><a href="20-eq.html#SP42">Equations::promote_subequation</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1], </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">lf</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">rf</span><span class="plain"> == </span><span class="identifier">TRUE</span><span class="plain">)) </span><span class="functiontext"><a href="20-eq.html#SP42">Equations::demote_subequation</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]);</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain"> = </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0]-&gt;</span><span class="element">gK_after</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP41">&#167;41</a>.</p>
<p class="inwebparagraph"><a id="SP41_2"></a><b>&#167;41.2. </b>The restriction on powers is needed to make it possible to know the
dimensions of the result. If \(h\) is a length, \(h^2\) is an area but \(h^3\) is
a volume; so if all we have is \(h^n\), and we don't know the value of \(n\),
we're unable to see what equations \(h^n\) can appear in.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Typecheck a raise-to-integer-power node</span> <span class="cwebmacronumber">41.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">base</span><span class="plain"> = </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0];</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">power</span><span class="plain"> = </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Dimensions::dimensionless</span><span class="plain">(</span><span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span><span class="identifier">base</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain">))) {</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain"> = </span><span class="identifier">base</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain">;</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain"> = </span><span class="identifier">base</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Take the dimensional power of the kind of the base</span> <span class="cwebmacronumber">41.2.1</span>&gt;<span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">lf</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::is_real</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0]-&gt;</span><span class="element">gK_after</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rf</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::is_real</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">gK_after</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">lf</span><span class="plain"> == </span><span class="identifier">TRUE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">rf</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)) </span><span class="functiontext"><a href="20-eq.html#SP42">Equations::promote_subequation</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1], </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">lf</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">rf</span><span class="plain"> == </span><span class="identifier">TRUE</span><span class="plain">)) </span><span class="functiontext"><a href="20-eq.html#SP42">Equations::promote_subequation</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0], </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Kinds::FloatingPoint::is_real</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; ((</span><span class="identifier">lf</span><span class="plain">) || (</span><span class="identifier">rf</span><span class="plain">))) {</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::to_real</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP41">&#167;41</a>.</p>
<p class="inwebparagraph"><a id="SP41_3"></a><b>&#167;41.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Typecheck a function application node</span> <span class="cwebmacronumber">41.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">fn</span><span class="plain"> = </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0];</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain"> == </span><span class="constant">SYMBOL_EQN</span><span class="plain">) &amp;&amp; (</span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">function_notated</span><span class="plain">)) {</span>
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain"> = </span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">function_notated</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">RK</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="22-ptd.html#SP27">Phrases::TypeData::arithmetic_operation</a></span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">) == </span><span class="identifier">REALROOT_OPERATION</span><span class="plain">) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">OPK</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">gK_after</span><span class="plain">);</span>
<span class="identifier">RK</span><span class="plain"> = </span><span class="identifier">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">OPK</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">REALROOT_OPERATION</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">RK</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationCantRoot</span><span class="plain">-</span><span class="identifier">G</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="string">""</span><span class="plain">,</span>
<span class="string">"the square root function 'root' can only be used on quantities "</span>
<span class="string">"whose dimensions are themselves a square - for example, the "</span>
<span class="string">"root of the area 100 sq m makes sense (it's 10m), but the root "</span>
<span class="string">"of 4m doesn't make sense, because what's a square root of a meter?"</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="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">RK</span><span class="plain"> = </span><span class="functiontext"><a href="22-ptd.html#SP11">Phrases::TypeData::get_return_kind</a></span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-&gt;</span><span class="element">type_data</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::to_real</span><span class="plain">(</span><span class="identifier">Kinds::FloatingPoint::new_gk</span><span class="plain">(</span><span class="identifier">RK</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rf</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::is_real</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">gK_after</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rf</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="functiontext"><a href="20-eq.html#SP42">Equations::promote_subequation</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1], </span><span class="identifier">FALSE</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP41">&#167;41</a>.</p>
<p class="inwebparagraph"><a id="SP41_2_1"></a><b>&#167;41.2.1. </b>To work out the kind of \(b^n\), we use repeated multiplication or division
of dimensions; if \(n=0\) then we have a dimensionless value, and choose
"number" as the simplest possibility.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Take the dimensional power of the kind of the base</span> <span class="cwebmacronumber">41.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain"> =</span>
<span class="identifier">Kinds::FloatingPoint::integer_equivalent</span><span class="plain">(</span>
<span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span>
<span class="identifier">base</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain">));</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">real</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">Kinds::FloatingPoint::is_real</span><span class="plain">(</span><span class="identifier">base</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain">)) </span><span class="identifier">real</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain"> = -1, </span><span class="identifier">m</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain">-&gt;</span><span class="identifier">rational_m</span><span class="plain"> != </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">n</span><span class="plain"> = </span><span class="identifier">power</span><span class="plain">-&gt;</span><span class="identifier">rational_n</span><span class="plain">; </span><span class="identifier">m</span><span class="plain"> = </span><span class="identifier">power</span><span class="plain">-&gt;</span><span class="element">rational_m</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">m</span><span class="plain"> &gt; </span><span class="constant">1</span><span class="plain">) &amp;&amp; (</span><span class="identifier">real</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="identifier">result</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationCantPower2</span><span class="plain">-</span><span class="identifier">G</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="string">""</span><span class="plain">,</span>
<span class="string">"except for the special cases of squaring and cubing, the '^' "</span>
<span class="string">"raise-to-power symbol can only be used to power a value using "</span>
<span class="string">"real rather than integer arithmetic."</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span><span class="identifier">power</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain">), </span><span class="identifier">K_number</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">power</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain"> != </span><span class="constant">CONSTANT_EQN</span><span class="plain">)) {</span>
<span class="identifier">result</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationDimensionPower</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="string">""</span><span class="plain">,</span>
<span class="string">"the '^' raise-to-power symbol can only be used to raise a value "</span>
<span class="string">"with dimensions to a specific number. So 'mv^2' is fine, but not "</span>
<span class="string">"'mv^n' or 'mv^(1+n)'. (This is because I would need to work out what "</span>
<span class="string">"kind of value 'v^n' would be, and the answer would depend on 'n', "</span>
<span class="string">"but I wouldn't know what 'n' is.)"</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">n</span><span class="plain"> = </span><span class="functiontext"><a href="14-rv.html#SP8">Rvalues::to_int</a></span><span class="plain">(</span><span class="identifier">power</span><span class="plain">-&gt;</span><span class="element">leaf_constant</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">n</span><span class="plain"> &gt;= </span><span class="constant">1</span><span class="plain">) {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">Kinds::Dimensions::to_rational_power</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">, </span><span class="identifier">n</span><span class="plain">, </span><span class="identifier">m</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="functiontext"><a href="2-si.html#SP4">Problems::Issue::equation_problem</a></span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">), </span><span class="identifier">eqn</span><span class="plain">, </span><span class="string">""</span><span class="plain">,</span>
<span class="string">"this would involve taking a fractional power of an amount whose "</span>
<span class="string">"dimensions are not of that power form - for example, the square "</span>
<span class="string">"root of the area 100 sq m makes sense (it's 10m), but the square "</span>
<span class="string">"root of 4m doesn't make sense, because what's a square root of "</span>
<span class="string">"a meter?"</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">if</span><span class="plain"> (</span><span class="identifier">real</span><span class="plain">)</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain"> =</span>
<span class="identifier">Kinds::FloatingPoint::to_real</span><span class="plain">(</span>
<span class="identifier">Kinds::FloatingPoint::new_gk</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">));</span>
<span class="reserved">else</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain"> =</span>
<span class="identifier">Kinds::FloatingPoint::new_gk</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP41_2">&#167;41.2</a>.</p>
<p class="inwebparagraph"><a id="SP41_4"></a><b>&#167;41.4. </b>The following is easy because it was the content of the whole "Dimensions.w"
section:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Typecheck a general operation node</span> <span class="cwebmacronumber">41.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">O1</span><span class="plain"> =</span>
<span class="identifier">Kinds::FloatingPoint::integer_equivalent</span><span class="plain">(</span>
<span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0]-&gt;</span><span class="element">gK_after</span><span class="plain">));</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">real</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">Kinds::FloatingPoint::is_real</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0]-&gt;</span><span class="element">gK_after</span><span class="plain">))</span>
<span class="identifier">real</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">Kinds::Dimensions::arithmetic_op_is_unary</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain">))</span>
<span class="identifier">K</span><span class="plain"> = </span><span class="identifier">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">O1</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">O2</span><span class="plain"> =</span>
<span class="identifier">Kinds::FloatingPoint::integer_equivalent</span><span class="plain">(</span>
<span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">gK_after</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::FloatingPoint::is_real</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">gK_after</span><span class="plain">))</span>
<span class="identifier">real</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">K</span><span class="plain"> = </span><span class="identifier">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">O1</span><span class="plain">, </span><span class="identifier">O2</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">lf</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::is_real</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0]-&gt;</span><span class="element">gK_after</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rf</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::is_real</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">gK_after</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">lf</span><span class="plain"> == </span><span class="identifier">TRUE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">rf</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)) </span><span class="functiontext"><a href="20-eq.html#SP42">Equations::promote_subequation</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1], </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">lf</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">rf</span><span class="plain"> == </span><span class="identifier">TRUE</span><span class="plain">)) </span><span class="functiontext"><a href="20-eq.html#SP42">Equations::promote_subequation</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0], </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">result</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::new_gk</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Failed at operation:\n"</span><span class="plain">); </span><span class="functiontext"><a href="20-eq.html#SP27">Equations::log_equation_node</a></span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Dimensions::arithmetic_op_is_unary</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Issue unary equation typechecking problem message</span> <span class="cwebmacronumber">41.4.1</span>&gt;
<span class="reserved">else</span>
&lt;<span class="cwebmacro">Issue binary equation typechecking problem message</span> <span class="cwebmacronumber">41.4.2</span>&gt;<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">real</span><span class="plain">)</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain"> =</span>
<span class="identifier">Kinds::FloatingPoint::to_real</span><span class="plain">(</span>
<span class="identifier">Kinds::FloatingPoint::new_gk</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">));</span>
<span class="reserved">else</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain"> =</span>
<span class="identifier">Kinds::FloatingPoint::new_gk</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="20-eq.html#SP41">&#167;41</a>.</p>
<p class="inwebparagraph"><a id="SP41_4_1"></a><b>&#167;41.4.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue unary equation typechecking problem message</span> <span class="cwebmacronumber">41.4.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="functiontext"><a href="2-sq.html#SP3">Problems::quote_kind</a></span><span class="plain">(4,</span>
<span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0]-&gt;</span><span class="element">gK_after</span><span class="plain">));</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">UNARY_MINUS_OPERATION:</span>
<span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"negating"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">ROOT_OPERATION:</span>
<span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"taking the square root of"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">REALROOT_OPERATION:</span>
<span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"taking the (real-valued) square root of"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CUBEROOT_OPERATION:</span>
<span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"taking the cube root of"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext"><a href="1-wtc.html#SP5">Task::syntax_tree</a></span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but that equation seems to involve %6 %4, which is not "</span>
<span class="string">"good arithmetic."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP41_4">&#167;41.4</a>.</p>
<p class="inwebparagraph"><a id="SP41_4_2"></a><b>&#167;41.4.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue binary equation typechecking problem message</span> <span class="cwebmacronumber">41.4.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="functiontext"><a href="2-sq.html#SP3">Problems::quote_kind</a></span><span class="plain">(4, </span><span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0]-&gt;</span><span class="element">gK_after</span><span class="plain">));</span>
<span class="functiontext"><a href="2-sq.html#SP3">Problems::quote_kind</a></span><span class="plain">(5, </span><span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">gK_after</span><span class="plain">));</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PLUS_OPERATION:</span>
<span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"adding"</span><span class="plain">); </span><span class="identifier">Problems::quote_text</span><span class="plain">(7, </span><span class="string">"to"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">MINUS_OPERATION:</span>
<span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"subtracting"</span><span class="plain">); </span><span class="identifier">Problems::quote_text</span><span class="plain">(7, </span><span class="string">"from"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TIMES_OPERATION:</span>
<span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"multiplying"</span><span class="plain">); </span><span class="identifier">Problems::quote_text</span><span class="plain">(7, </span><span class="string">"by"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">DIVIDE_OPERATION:</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">REMAINDER_OPERATION:</span>
<span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"dividing"</span><span class="plain">); </span><span class="identifier">Problems::quote_text</span><span class="plain">(7, </span><span class="string">"by"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">POWER_OPERATION:</span>
<span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"raising"</span><span class="plain">); </span><span class="identifier">Problems::quote_text</span><span class="plain">(7, </span><span class="string">"to the power of"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span>
<span class="identifier">Problems::quote_text</span><span class="plain">(6, </span><span class="string">"combining"</span><span class="plain">); </span><span class="identifier">Problems::quote_text</span><span class="plain">(7, </span><span class="string">"with"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext"><a href="1-wtc.html#SP5">Task::syntax_tree</a></span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationBadArithmetic</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but that equation seems to involve "</span>
<span class="string">"%6 %4 %7 %5, which is not good arithmetic."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP41_4">&#167;41.4</a>.</p>
<p class="inwebparagraph"><a id="SP42"></a><b>&#167;42. Flotation. </b></p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::promote_subequation<button class="popup" onclick="togglePopup('usagePopup1474')">...<span class="popuptext" id="usagePopup1474">Usage of <b>Equations::promote_subequation</b>:<br><a href="20-eq.html#SP41">&#167;41</a>, <a href="20-eq.html#SP41_1">&#167;41.1</a>, <a href="20-eq.html#SP41_2">&#167;41.2</a>, <a href="20-eq.html#SP41_3">&#167;41.3</a>, <a href="20-eq.html#SP41_4">&#167;41.4</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">, </span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">deeply</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</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="reserved">if</span><span class="plain"> (</span><span class="identifier">deeply</span><span class="plain">) {</span>
<span class="identifier">float_terminal_nodes</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="functiontext"><a href="20-eq.html#SP41">Equations::enode_typecheck</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">);</span>
<span class="identifier">float_terminal_nodes</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::to_real</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::demote_subequation<button class="popup" onclick="togglePopup('usagePopup1475')">...<span class="popuptext" id="usagePopup1475">Usage of <b>Equations::demote_subequation</b>:<br><a href="20-eq.html#SP41_1">&#167;41.1</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">, </span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</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">tok</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::to_integer</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP43"></a><b>&#167;43. Compiling. </b>We want each equation to have a distinct value at runtime. The following
routines do nothing (for now, anyway) except to give the I6 identifiers
for equations a value; they are never called.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::compile<button class="popup" onclick="togglePopup('usagePopup1476')">...<span class="popuptext" id="usagePopup1476">Usage of <b>Equations::compile</b>:<br>How To Compile - <a href="1-htc.html#SP2_8">&#167;2.8</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="reserved">equation</span><span class="plain">) {</span>
<span class="identifier">packaging_state</span><span class="plain"> </span><span class="identifier">save</span><span class="plain"> = </span><span class="functiontext"><a href="26-rt.html#SP1">Routines::begin</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">eqn_iname</span><span class="plain">);</span>
<span class="identifier">Produce::rfalse</span><span class="plain">(</span><span class="functiontext"><a href="27-em.html#SP2">Emit::tree</a></span><span class="plain">());</span>
<span class="functiontext"><a href="26-rt.html#SP4">Routines::end</a></span><span class="plain">(</span><span class="identifier">save</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP44"></a><b>&#167;44. </b>These identifiers are used to compile equation names as values, so:
</p>
<pre class="display">
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="functiontext">Equations::identifier<button class="popup" onclick="togglePopup('usagePopup1477')">...<span class="popuptext" id="usagePopup1477">Usage of <b>Equations::identifier</b>:<br>RValues - <a href="14-rv.html#SP24_3">&#167;24.3</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">eqn_iname</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP45"></a><b>&#167;45. Solving. </b>So we can finally turn to putting equations to use. Firstly, when a named
equation is used, a "where..." clause is sometimes given to make temporary
assignments (see above); what happens is that the S-parser temporarily sets
the usage words of the equation to the relevant text...
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::set_usage_notes<button class="popup" onclick="togglePopup('usagePopup1478')">...<span class="popuptext" id="usagePopup1478">Usage of <b>Equations::set_usage_notes</b>:<br>Type Expressions and Values - <a href="10-teav.html#SP12_2">&#167;12.2</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</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">eqn</span><span class="plain">-&gt;</span><span class="element">usage_text</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP46"></a><b>&#167;46. </b>...so that, when we come to solve the equation (i.e., later on in the
invocation compiler), we know where to find these temporary assignments.
They are wiped out once this compilation is over.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::emit_solution<button class="popup" onclick="togglePopup('usagePopup1479')">...<span class="popuptext" id="usagePopup1479">Usage of <b>Equations::emit_solution</b>:<br>Compile Invocations Inline - <a href="25-cii.html#SP3_7_3">&#167;3.7.3</a></span></button></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">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">usage_text</span><span class="plain">))</span>
<span class="functiontext"><a href="20-eq.html#SP18">Equations::eqn_declare_variables_inner</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">usage_text</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="functiontext"><a href="20-eq.html#SP47">Equations::emit_solution_inner</a></span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">eqn</span><span class="plain">);</span>
<span class="functiontext"><a href="20-eq.html#SP19">Equations::eqn_remove_temp_variables</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">);</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">usage_text</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP47"></a><b>&#167;47. </b>With that dance out of the way, we can concentrate on the actual task.
We have to compile code which assigns the correct value to the symbol
specified by \((w_1, w_2)\), according to the equation <code class="display"><span class="extract">eqn</span></code>.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::emit_solution_inner<button class="popup" onclick="togglePopup('usagePopup1480')">...<span class="popuptext" id="usagePopup1480">Usage of <b>Equations::emit_solution_inner</b>:<br><a href="20-eq.html#SP46">&#167;46</a></span></button></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">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">) {</span>
<span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">to_solve</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Identify which symbol in the equation we are solving for</span> <span class="cwebmacronumber">47.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Rearrange the equation so that this symbol is the entire LHS</span> <span class="cwebmacronumber">47.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Identify the symbols in the equation with local variables</span> <span class="cwebmacronumber">47.3</span>&gt;<span class="plain">;</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="string">"Solving %n for '$w'"</span><span class="plain">, </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">eqn_iname</span><span class="plain">, </span><span class="identifier">to_solve</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">);</span>
<span class="functiontext"><a href="27-em.html#SP3">Emit::code_comment</a></span><span class="plain">(</span><span class="identifier">C</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">);</span>
<span class="functiontext"><a href="20-eq.html#SP48">Equations::enode_compile_by_emission</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP47_1"></a><b>&#167;47.1. </b>Note the case sensitivity here.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Identify which symbol in the equation we are solving for</span> <span class="cwebmacronumber">47.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::length</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">) == </span><span class="constant">1</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">symbol_list</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::match_cs</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">))</span>
<span class="identifier">to_solve</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">to_solve</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(3, </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_text</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext"><a href="1-wtc.html#SP5">Task::syntax_tree</a></span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationBadTarget</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In %1, you asked to let %2 be given by the equation '%3', "</span>
<span class="string">"but '%2' isn't a symbol in that equation."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">to_solve</span><span class="plain">-&gt;</span><span class="element">var_const</span><span class="plain">) {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(3, </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_text</span><span class="plain">);</span>
<span class="functiontext"><a href="2-sq.html#SP1">Problems::quote_spec</a></span><span class="plain">(4, </span><span class="identifier">to_solve</span><span class="plain">-&gt;</span><span class="element">var_const</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext"><a href="1-wtc.html#SP5">Task::syntax_tree</a></span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationConstantTarget</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In %1, you asked to let %2 be given by the equation '%3', "</span>
<span class="string">"but '%2' isn't something which can vary freely in that equation - "</span>
<span class="string">"it's been set equal to %4."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP47">&#167;47</a>.</p>
<p class="inwebparagraph"><a id="SP47_2"></a><b>&#167;47.2. </b>This step is not easy, but is delegated to <code class="display"><span class="extract">Equations::eqn_rearrange</span></code> below, so it
looks easy here. The surprising thing is the fresh round of typechecking:
why do we do that? The answer is not that we doubt whether the equation is
still valid &mdash; the rearranged equation should pass if and only if the original
did, if we've implemented all of this correctly &mdash; but because the alterations
made to the tree mean that the assignments of kinds at each node are now
potentially incorrect. Re-typechecking will recalculate these.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Rearrange the equation so that this symbol is the entire LHS</span> <span class="cwebmacronumber">47.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP50">Equations::eqn_rearrange</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">to_solve</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(3, </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_text</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext"><a href="1-wtc.html#SP5">Task::syntax_tree</a></span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationInsoluble</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In %1, you asked to let %2 be given by the equation '%3', "</span>
<span class="string">"but I am unable to rearrange the equation in any simple way "</span>
<span class="string">"so that it sets '%2' equal to something else. Maybe you could "</span>
<span class="string">"write a more explicit equation? (You're certainly better at "</span>
<span class="string">"maths than I am; I can only make easy deductions.)"</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP39">Equations::eqn_typecheck</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP47">&#167;47</a>.</p>
<p class="inwebparagraph"><a id="SP47_3"></a><b>&#167;47.3. </b>Suppose we read a phrase such as
</p>
<blockquote>
<p>let PE be given by PE = mgh, where g = 9.801 m/ss;</p>
</blockquote>
<p class="inwebparagraph">We can only compile code to do this if we can identify values for the symbols.
"g" is not a problem because a temporary assignment supplies this. For each
symbol <code class="display"><span class="extract">ev</span></code> which isn't a constant, we must set <code class="display"><span class="extract">ev-&gt;local_map</span></code> to the
corresponding local variable.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Identify the symbols in the equation with local variables</span> <span class="cwebmacronumber">47.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">ev</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">symbol_list</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">var_const</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">local_map</span><span class="plain"> = </span><span class="functiontext"><a href="24-lv.html#SP24">LocalVariables::parse</a></span><span class="plain">(</span><span class="functiontext"><a href="24-sf.html#SP8">Frames::current_stack_frame</a></span><span class="plain">(), </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">);</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">promote_local_to_real</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">ev</span><span class="plain">-&gt;</span><span class="element">local_map</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Can't find an unset symbol among the local variables</span> <span class="cwebmacronumber">47.3.1</span>&gt;
<span class="reserved">else</span>
&lt;<span class="cwebmacro">Check that the kind of the local variable matches that of the symbol</span> <span class="cwebmacronumber">47.3.2</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP47">&#167;47</a>.</p>
<p class="inwebparagraph"><a id="SP47_3_1"></a><b>&#167;47.3.1. </b>In the above example, finding "PE" should not be a problem: this
is the <code class="display"><span class="extract">to_solve</span></code> symbol, and it must be a current local variable name
since the "let" will have created it as such if it didn't already
exist. But things can certainly go wrong with "m" and "h", which
need to exist as local variables in the current stack frame.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Can't find an unset symbol among the local variables</span> <span class="cwebmacronumber">47.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ev</span><span class="plain"> == </span><span class="identifier">to_solve</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"can't find 'let' variable to assign"</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(3, </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_text</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(4, </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext"><a href="1-wtc.html#SP5">Task::syntax_tree</a></span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationSymbolMissing</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In %1, you asked to let %2 be given by the equation '%3', "</span>
<span class="string">"but I can't see what to use for '%4'. The usual idea is "</span>
<span class="string">"to set the other variables in the equation using 'let': "</span>
<span class="string">"so adding 'let %4 be ...' before trying to find '%2' "</span>
<span class="string">"should work."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP47_3">&#167;47.3</a>.</p>
<p class="inwebparagraph"><a id="SP47_3_2"></a><b>&#167;47.3.2. </b>In the case of the symbol we are setting, the local variable might be one
which has only just been created and thus has no value yet &mdash; not having
set it, Inform hasn't given it a kind more explicit than "value".
We can improve that by giving it the kind of the symbol it is to match.
</p>
<p class="inwebparagraph">In all other cases, the local variable already exists and has a fixed kind.
This must exactly match that of the symbol. (Again, if we ever need implicit
casting between quasinumerical kinds, we'll have to return to this.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Check that the kind of the local variable matches that of the symbol</span> <span class="cwebmacronumber">47.3.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext"><a href="24-lv.html#SP37">LocalVariables::kind</a></span><span class="plain">(</span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">local_map</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">)) {</span>
<span class="identifier">K</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">var_kind</span><span class="plain">;</span>
<span class="functiontext"><a href="24-lv.html#SP38">LocalVariables::set_kind</a></span><span class="plain">(</span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">local_map</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">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_number</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">var_kind</span><span class="plain">, </span><span class="identifier">K_real_number</span><span class="plain">))) {</span>
<span class="identifier">K</span><span class="plain"> = </span><span class="identifier">K_real_number</span><span class="plain">;</span>
<span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">promote_local_to_real</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">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">var_kind</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(3, </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_text</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(4, </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">);</span>
<span class="functiontext"><a href="2-sq.html#SP3">Problems::quote_kind</a></span><span class="plain">(5, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="functiontext"><a href="2-sq.html#SP3">Problems::quote_kind</a></span><span class="plain">(6, </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">var_kind</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext"><a href="1-wtc.html#SP5">Task::syntax_tree</a></span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EquationSymbolWrongKOV</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In %1, you asked to let %2 be given by the equation '%3', "</span>
<span class="string">"but in that equation '%4' is supposedly %6 - whereas right "</span>
<span class="string">"here, it seems to be %5. Perhaps two different quantities have "</span>
<span class="string">"ended up with the same symbol in the source text?"</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP47_3">&#167;47.3</a>.</p>
<p class="inwebparagraph"><a id="SP48"></a><b>&#167;48. </b>Actual compilation is simple, since the tree is set up for it.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::enode_compile_by_emission<button class="popup" onclick="togglePopup('usagePopup1481')">...<span class="popuptext" id="usagePopup1481">Usage of <b>Equations::enode_compile_by_emission</b>:<br><a href="20-eq.html#SP47">&#167;47</a>, Compile Arithmetic - <a href="13-ca.html#SP1_2_1">&#167;1.2.1</a>, <a href="13-ca.html#SP1_2_2">&#167;1.2.2</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">, </span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">a</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::FloatingPoint::is_real</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain">)) </span><span class="identifier">a</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">b</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::FloatingPoint::is_real</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain">)) </span><span class="identifier">b</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">f</span><span class="plain"> = </span><span class="identifier">b</span><span class="plain"> - </span><span class="identifier">a</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">f</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">) </span><span class="identifier">Kinds::FloatingPoint::begin_flotation_emit</span><span class="plain">(</span><span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</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">f</span><span class="plain"> == -1) </span><span class="identifier">Kinds::FloatingPoint::begin_deflotation_emit</span><span class="plain">(</span><span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain">));</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">SYMBOL_EQN:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">var_const</span><span class="plain">)</span>
<span class="functiontext"><a href="14-cfs.html#SP9">Specifications::Compiler::emit_as_val</a></span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">var_const</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">tok</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">local_map</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">promote_local_to_real</span><span class="plain">) {</span>
<span class="identifier">Produce::inv_call_iname</span><span class="plain">(</span><span class="functiontext"><a href="27-em.html#SP2">Emit::tree</a></span><span class="plain">(), </span><span class="functiontext"><a href="27-hr.html#SP4">Hierarchy::find</a></span><span class="plain">(</span><span class="constant">NUMBER_TY_TO_REAL_NUMBER_TY_HL</span><span class="plain">));</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext"><a href="27-em.html#SP2">Emit::tree</a></span><span class="plain">());</span>
<span class="plain">}</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">tok_s</span><span class="plain"> = </span><span class="functiontext"><a href="24-lv.html#SP47">LocalVariables::declare_this</a></span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">local_map</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="constant">8</span><span class="plain">);</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="functiontext"><a href="27-em.html#SP2">Emit::tree</a></span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">tok_s</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">promote_local_to_real</span><span class="plain">)</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext"><a href="27-em.html#SP2">Emit::tree</a></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">tok</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">function_notated</span><span class="plain">) {</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">RS</span><span class="plain"> = </span><span class="functiontext"><a href="22-tp.html#SP8">Routines::ToPhrases::make_iname</a></span><span class="plain">(</span>
<span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">function_notated</span><span class="plain">,</span>
<span class="functiontext"><a href="22-ptd.html#SP13">Phrases::TypeData::kind</a></span><span class="plain">(</span>
<span class="plain">&amp;(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">function_notated</span><span class="plain">-&gt;</span><span class="element">type_data</span><span class="plain">)));</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="functiontext"><a href="27-em.html#SP2">Emit::tree</a></span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">RS</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"uncompilable equation node"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CONSTANT_EQN:</span>
<span class="functiontext"><a href="14-cfs.html#SP9">Specifications::Compiler::emit_as_val</a></span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">leaf_constant</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">OPERATION_EQN:</span><span class="plain"> </span>&lt;<span class="cwebmacro">Emit a single operation</span> <span class="cwebmacronumber">48.1</span>&gt;<span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"forbidden enode found in parsed equation"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">f</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">) </span><span class="identifier">Kinds::FloatingPoint::end_flotation_emit</span><span class="plain">(</span><span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</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">f</span><span class="plain"> == -1) </span><span class="identifier">Kinds::FloatingPoint::end_deflotation_emit</span><span class="plain">(</span><span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">gK_before</span><span class="plain">));</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP48_1"></a><b>&#167;48.1. </b>And here we handle operation nodes:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Emit a single operation</span> <span class="cwebmacronumber">48.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0];</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">KX</span><span class="plain"> = </span><span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain">);</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1];</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">KY</span><span class="plain"> = (</span><span class="identifier">Y</span><span class="plain">)?(</span><span class="identifier">Kinds::FloatingPoint::underlying</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">-&gt;</span><span class="element">gK_after</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">Kinds::FloatingPoint::is_real</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">-&gt;</span><span class="element">gK_after</span><span class="plain">)) {</span>
<span class="identifier">KX</span><span class="plain"> = </span><span class="identifier">K_real_number</span><span class="plain">; </span><span class="identifier">KY</span><span class="plain"> = </span><span class="identifier">K_real_number</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="functiontext"><a href="13-ca.html#SP1">Kinds::Compile::perform_arithmetic_emit</a></span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain">, </span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">KX</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">KY</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP48">&#167;48</a>.</p>
<p class="inwebparagraph"><a id="SP49"></a><b>&#167;49. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::enode_compilation_error<button class="popup" onclick="togglePopup('usagePopup1482')">...<span class="popuptext" id="usagePopup1482">Usage of <b>Equations::enode_compilation_error</b>:<br>Compile Arithmetic - <a href="13-ca.html#SP1_12">&#167;1.12</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">, </span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok</span><span class="plain">) {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(2, </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_text</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext"><a href="1-wtc.html#SP5">Task::syntax_tree</a></span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_HardIntegerRoot</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In %1, you asked me to solve the equation '%2', but that would have "</span>
<span class="string">"involved taking a tricky root of a whole number. Using real numbers "</span>
<span class="string">"that would be easy, but with whole numbers I'm unable to get there."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP50"></a><b>&#167;50. Rearrangement. </b>We carry out only the simplest of operations, but it's surprising how often that's
good enough: if it isn't, we simply return <code class="display"><span class="extract">FALSE</span></code>.
</p>
<p class="inwebparagraph">Everything we do will be reversible, which is important since we are
changing the <code class="display"><span class="extract">parsed_equation</span></code> tree, and we don't want to be changing our
view of what the equation means in the process. One thing that never changes
is that the top node of the equation is always the unique "equal to" node
in the tree.
</p>
<p class="inwebparagraph">Suppose we are solving for <code class="display"><span class="extract">v</span></code>, which occurs in just one place in the equation.
Either it's at the top level under the <code class="display"><span class="extract">=</span></code>, in which case we now have an
explicit formula for <code class="display"><span class="extract">v</span></code>, or it's stuck underneath some operation node. We
rearrange the tree to move this operation over to the other side, which
allows <code class="display"><span class="extract">v</span></code> to make progress &mdash; see below for a proof that this terminates.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::eqn_rearrange<button class="popup" onclick="togglePopup('usagePopup1483')">...<span class="popuptext" id="usagePopup1483">Usage of <b>Equations::eqn_rearrange</b>:<br><a href="20-eq.html#SP47_2">&#167;47.2</a>, <a href="20-eq.html#SP52">&#167;52</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">, </span><span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">to_solve</span><span class="plain">) {</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">TRUE</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Swap the two sides if necessary so that v occurs only once and on the left</span> <span class="cwebmacronumber">50.1</span>&gt;<span class="plain">;</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">old_LHS</span><span class="plain"> = </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0];</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">old_RHS</span><span class="plain"> = </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">eqn_type</span><span class="plain"> != </span><span class="constant">OPERATION_EQN</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_arity</span><span class="plain"> == </span><span class="constant">2</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Rearrange to move v upwards through this binary operator</span> <span class="cwebmacronumber">50.3</span>&gt;
<span class="reserved">else</span>
&lt;<span class="cwebmacro">Rearrange to move v upwards through this unary operator</span> <span class="cwebmacronumber">50.4</span>&gt;<span class="plain">;</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="inwebparagraph"><a id="SP50_1"></a><b>&#167;50.1. </b>We have no ability to gather terms, so the variable <code class="display"><span class="extract">v</span></code> we are solving for can only
occur once in the formula. In Inform's idea of equations, <code class="display"><span class="extract">A = B</span></code> and <code class="display"><span class="extract">B = A</span></code>
have the same meaning, so we'll place <code class="display"><span class="extract">v</span></code> on the left.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Swap the two sides if necessary so that v occurs only once and on the left</span> <span class="cwebmacronumber">50.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">lc</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP51">Equations::enode_count_var</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0], </span><span class="identifier">to_solve</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rc</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP51">Equations::enode_count_var</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1], </span><span class="identifier">to_solve</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lc</span><span class="plain"> + </span><span class="identifier">rc</span><span class="plain"> != </span><span class="constant">1</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">if</span><span class="plain"> (</span><span class="identifier">lc</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">swap</span><span class="plain"> = </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0];</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1];</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="identifier">swap</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP50">&#167;50</a>.</p>
<p class="inwebparagraph"><a id="SP50_2"></a><b>&#167;50.2. </b>The main loop above terminates because on each iteration, either
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(i) the tree depth of <code class="display"><span class="extract">v</span></code> below <code class="display"><span class="extract">=</span></code> decreases by 1, or
</li><li>(ii) the tree depth of <code class="display"><span class="extract">v</span></code> remains the same but the number of <code class="display"><span class="extract">MINUS_OPERATION</span></code> or
<code class="display"><span class="extract">DIVIDE_OPERATION</span></code> nodes in the tree decreases by 1.
</li></ul>
<p class="inwebparagraph">Since at any given time there are a finite number of <code class="display"><span class="extract">MINUS_OPERATION</span></code> or
<code class="display"><span class="extract">DIVIDE_OPERATION</span></code> nodes, case (ii) cannot repeat indefinitely, and we must
therefore eventually fall into case (i); and then subsequently do so again,
and so on; and so the tree depth of <code class="display"><span class="extract">v</span></code> will ultimately fall to 1, at which
point it is at the top level as required and we break out of the loop.
</p>
<p class="inwebparagraph"><a id="SP50_3"></a><b>&#167;50.3. </b>So the rearrangement moves have to make sure the "(i) or (ii)" property
always holds. The simplest case to understand is <code class="display"><span class="extract">+</span></code>. Suppose we have:
</p>
<pre class="display">
<span class="plain">=</span>
<span class="plain">+</span>
<span class="plain">V</span>
<span class="plain">E</span>
<span class="plain">R</span>
</pre>
<p class="inwebparagraph">representing \((V+E) = R\), where \(V\) is the sub-equation containing
\(v\). (\(E\) is an arbitrary sub-equation, and \(R\) is the right hand
side.) One of the two operands of <code class="display"><span class="extract">+</span></code> will be "promoted", moving
upwards in the tree, and since we can choose to promote either \(V\) or
\(E\), we'll choose \(V\), thus obtaining:
</p>
<pre class="display">
<span class="plain">=</span>
<span class="plain">V</span>
<span class="plain">-</span>
<span class="plain">R</span>
<span class="plain">E</span>
</pre>
<p class="inwebparagraph">that is, \(V = (R - E)\). Since \(V\) has moved upwards, so has the unique instance
of \(v\), and therefore the tree depth of \(v\) has decreased by 1 &mdash; property (i).
Multiplication is similar, but turns into division on the right hand side.
</p>
<p class="inwebparagraph">But now consider <code class="display"><span class="extract">-</span></code>. When we rearrange:
</p>
<pre class="display">
<span class="plain">=</span>
<span class="plain">-</span>
<span class="plain">E</span>
<span class="plain">V</span>
<span class="plain">R</span>
</pre>
<p class="inwebparagraph">representing \((E-V) = R\) we no longer have a choice of which operand of <code class="display"><span class="extract">-</span></code>
to promote: we have to promote the right operand, and that produces \(E = (R+V)\).
The tree depth of \(v\) is not improved, and it's now over on the right hand
side. The next iteration of the main loop will swap sides again so that we
have \((R+V) = E\). But a tricky node (subtraction or division) has been
exchanged out of the tree for an easy one (addition or multiplication), so
we fail property (i) but achieve property (ii).
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Rearrange to move v upwards through this binary operator</span> <span class="cwebmacronumber">50.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="comment"> rearrange to move this operator</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">op</span><span class="plain"> = </span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">op</span><span class="plain"> == </span><span class="identifier">POWER_OPERATION</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Rearrange to remove a power</span> <span class="cwebmacronumber">50.3.1</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">op</span><span class="plain"> == </span><span class="constant">IMPLICIT_APPLICATION_OPERATION</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Rearrange using the inverse of function</span> <span class="cwebmacronumber">50.3.2</span>&gt;
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">promote</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">new_op</span><span class="plain"> = </span><span class="identifier">PLUS_OPERATION</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP51">Equations::enode_count_var</a></span><span class="plain">(</span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1], </span><span class="identifier">to_solve</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">promote</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">op</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PLUS_OPERATION:</span><span class="plain"> </span><span class="identifier">new_op</span><span class="plain"> = </span><span class="identifier">MINUS_OPERATION</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">MINUS_OPERATION:</span><span class="plain"> </span><span class="identifier">new_op</span><span class="plain"> = </span><span class="identifier">PLUS_OPERATION</span><span class="plain">; </span><span class="identifier">promote</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TIMES_OPERATION:</span><span class="plain"> </span><span class="identifier">new_op</span><span class="plain"> = </span><span class="identifier">DIVIDE_OPERATION</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">DIVIDE_OPERATION:</span><span class="plain"> </span><span class="identifier">new_op</span><span class="plain"> = </span><span class="identifier">TIMES_OPERATION</span><span class="plain">; </span><span class="identifier">promote</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%d\n"</span><span class="plain">, </span><span class="identifier">op</span><span class="plain">); </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"strange operator in rearrangement"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">E</span><span class="plain"> = </span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1 - </span><span class="identifier">promote</span><span class="plain">];</span>
<span class="comment"> the new LHS is the promoted operand:</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[</span><span class="identifier">promote</span><span class="plain">];</span>
<span class="comment"> the new RHS is the operator which used to be the LHS...</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="identifier">old_LHS</span><span class="plain">;</span>
<span class="comment"> ...the former RHS being the operand replacing the promoted one...</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_RHS</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="identifier">E</span><span class="plain">;</span>
<span class="comment"> ...except that the operator reverses in "sense"</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain"> = </span><span class="identifier">new_op</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP50">&#167;50</a>.</p>
<p class="inwebparagraph"><a id="SP50_3_1"></a><b>&#167;50.3.1. </b>Solving \(x^v = y\) for \(v\) requires logs, which are not in our scheme; and
solving \(v^n = y\) for non-constant \(n\) is no better. So in either case we
surrender by returning <code class="display"><span class="extract">FALSE</span></code>.
</p>
<p class="inwebparagraph">In fact, the only cases we can solve at present are \(V^2 = y\) and \(V^3 = y\).
It would be easy to add solutions for \(V^4 = y\), \(V^6 = y\) and in general for
\(V^k = y\) where the only prime factors of \(k\) are 2 and 3, but this is not
something people are likely to need very much. The taking of 4th or higher roots
hardly ever occurs in physical equations, and anyone wanting this will have
to write more explicit source text.
</p>
<p class="inwebparagraph">Anyway, rearrangement for our easy cases is indeed easy:
</p>
<pre class="display">
<span class="plain">=</span>
<span class="plain">^</span>
<span class="plain">V</span>
<span class="plain">2</span>
<span class="plain">R</span>
</pre>
<p class="inwebparagraph">becomes
</p>
<pre class="display">
<span class="plain">=</span>
<span class="plain">V</span>
<span class="plain">square-root</span>
<span class="plain">R</span>
</pre>
<p class="inwebparagraph">and \(V\) is always promoted, so we achieve property (i); and similarly for
cube roots.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Rearrange to remove a power</span> <span class="cwebmacronumber">50.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">p</span><span class="plain"> = </span><span class="functiontext"><a href="14-rv.html#SP8">Rvalues::to_int</a></span><span class="plain">(</span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="identifier">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">leaf_constant</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="constant">2</span><span class="plain">) {</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0];</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="identifier">old_LHS</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain"> = </span><span class="identifier">ROOT_OPERATION</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_arity</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_RHS</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">p</span><span class="plain"> == </span><span class="constant">3</span><span class="plain">) {</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0];</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="identifier">old_LHS</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain"> = </span><span class="identifier">CUBEROOT_OPERATION</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_arity</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_RHS</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0];</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="identifier">old_LHS</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain"> = </span><span class="identifier">POWER_OPERATION</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_arity</span><span class="plain"> = </span><span class="constant">2</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_RHS</span><span class="plain">;</span>
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">the_power</span><span class="plain"> = </span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1];</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="functiontext"><a href="20-eq.html#SP26">Equations::enode_new_op</a></span><span class="plain">(</span><span class="identifier">DIVIDE_OPERATION</span><span class="plain">);</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">enode_arity</span><span class="plain"> = </span><span class="constant">2</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="functiontext"><a href="20-eq.html#SP26">Equations::enode_new_constant</a></span><span class="plain">(</span>
<span class="functiontext"><a href="14-rv.html#SP8">Rvalues::from_int</a></span><span class="plain">(1, </span><span class="identifier">EMPTY_WORDING</span><span class="plain">));</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">enode_operands</span><span class="plain">[0]-&gt;</span><span class="element">gK_before</span><span class="plain"> =</span>
<span class="identifier">Kinds::FloatingPoint::new_gk</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">);</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">enode_operands</span><span class="plain">[0]-&gt;</span><span class="element">enode_promotion</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="identifier">the_power</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">gK_before</span><span class="plain"> =</span>
<span class="identifier">Kinds::FloatingPoint::new_gk</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">);</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">enode_promotion</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">gK_before</span><span class="plain"> =</span>
<span class="identifier">Kinds::FloatingPoint::new_gk</span><span class="plain">(</span><span class="identifier">K_real_number</span><span class="plain">);</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">gK_after</span><span class="plain"> =</span>
<span class="identifier">Kinds::FloatingPoint::new_gk</span><span class="plain">(</span><span class="identifier">K_real_number</span><span class="plain">);</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">rational_n</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">rational_m</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="functiontext"><a href="13-rsfk.html#SP26">Kinds::RunTime::notify_of_use</a></span><span class="plain">(</span><span class="identifier">K_real_number</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP50_3">&#167;50.3</a>.</p>
<p class="inwebparagraph"><a id="SP50_3_2"></a><b>&#167;50.3.2. </b>Here we have something like <code class="display"><span class="extract">log x = y</span></code> and want to rewrite as <code class="display"><span class="extract">x = exp y</span></code>,
which is only possible if we have an inverse available for our function &mdash;
in this case, <code class="display"><span class="extract">exp</span></code> being the inverse of <code class="display"><span class="extract">log</span></code>. Thus:
</p>
<pre class="display">
<span class="plain">=</span>
<span class="plain">apply</span>
<span class="plain">function</span>
<span class="plain">V</span>
<span class="plain">R</span>
</pre>
<p class="inwebparagraph">must become
</p>
<pre class="display">
<span class="plain">=</span>
<span class="plain">V</span>
<span class="plain">apply</span>
<span class="plain">inverse-of-function</span>
<span class="plain">R</span>
</pre>
<p class="inwebparagraph"></p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Rearrange using the inverse of function</span> <span class="cwebmacronumber">50.3.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">fnode</span><span class="plain"> = </span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0];</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">fnode</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">fnode</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">function_notated</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) {</span>
<span class="functiontext"><a href="20-eq.html#SP27">Equations::log_equation_node</a></span><span class="plain">(</span><span class="identifier">fnode</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"not a function being applied"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">f</span><span class="plain"> = </span><span class="identifier">fnode</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain">-&gt;</span><span class="element">function_notated</span><span class="plain">;</span>
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">finv</span><span class="plain"> = </span><span class="functiontext"><a href="22-pu.html#SP16">Phrases::Usage::get_equation_inverse</a></span><span class="plain">(&amp;(</span><span class="identifier">f</span><span class="plain">-&gt;</span><span class="element">usage_data</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">finv</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">FALSE</span><span class="plain">; </span><span class="comment"> no known inverse for this function</span>
<span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">ev</span><span class="plain">, *</span><span class="identifier">ev_inverse</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">ev</span><span class="plain"> = </span><span class="identifier">standard_equation_symbols</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">function_notated</span><span class="plain"> == </span><span class="identifier">finv</span><span class="plain">)</span>
<span class="identifier">ev_inverse</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ev_inverse</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">FALSE</span><span class="plain">; </span><span class="comment"> inverse can't be used in equations</span>
<span class="identifier">fnode</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain"> = </span><span class="identifier">ev_inverse</span><span class="plain">;</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1];</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="identifier">old_LHS</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="identifier">old_RHS</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP50_3">&#167;50.3</a>.</p>
<p class="inwebparagraph"><a id="SP50_4"></a><b>&#167;50.4. </b>The unary operations are easy in a similar way &mdash; they only have one operand,
so we always promote \(V\) and achieve property (i). A square root is rearranged
as a square, and a cube root as a cube. (It's important that everything we do
is reversible &mdash; we generate exactly those powers which we are able to undo
again if necessary.) Unary minus is easier still &mdash; we need only move it to
the other side; thus \(-V = R\) becomes \(V=-R\), and <code class="display"><span class="extract">v</span></code> again rises.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Rearrange to move v upwards through this unary operator</span> <span class="cwebmacronumber">50.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">op</span><span class="plain"> = </span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">op</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">UNARY_MINUS_OPERATION:</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0];</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="identifier">old_LHS</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_RHS</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">ROOT_OPERATION:</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">REALROOT_OPERATION:</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0];</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="identifier">old_LHS</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain"> = </span><span class="identifier">TIMES_OPERATION</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_arity</span><span class="plain"> = </span><span class="constant">2</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_RHS</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="identifier">old_RHS</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CUBEROOT_OPERATION:</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0];</span>
<span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="identifier">old_LHS</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">eqn_operation</span><span class="plain"> = </span><span class="identifier">TIMES_OPERATION</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_arity</span><span class="plain"> = </span><span class="constant">2</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_RHS</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="functiontext"><a href="20-eq.html#SP26">Equations::enode_new_op</a></span><span class="plain">(</span><span class="identifier">TIMES_OPERATION</span><span class="plain">);</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">enode_operands</span><span class="plain">[0] = </span><span class="identifier">old_RHS</span><span class="plain">;</span>
<span class="identifier">old_LHS</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[1]-&gt;</span><span class="element">enode_operands</span><span class="plain">[1] = </span><span class="identifier">old_RHS</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"unanticipated operator in rearrangement"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="20-eq.html#SP50">&#167;50</a>.</p>
<p class="inwebparagraph"><a id="SP51"></a><b>&#167;51. </b>And that's the whole rearranger, except for the utility routine which
counts instances of the magic variable <code class="display"><span class="extract">v</span></code> at or below a given point in the
equation tree.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Equations::enode_count_var<button class="popup" onclick="togglePopup('usagePopup1484')">...<span class="popuptext" id="usagePopup1484">Usage of <b>Equations::enode_count_var</b>:<br><a href="20-eq.html#SP50_1">&#167;50.1</a>, <a href="20-eq.html#SP50_3">&#167;50.3</a></span></button></span><span class="plain">(</span><span class="reserved">equation_node</span><span class="plain"> *</span><span class="identifier">tok</span><span class="plain">, </span><span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">to_solve</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tok</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">c</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="identifier">eqn_type</span><span class="plain"> == </span><span class="constant">SYMBOL_EQN</span><span class="plain">) &amp;&amp; (</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">leaf_symbol</span><span class="plain"> == </span><span class="identifier">to_solve</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">1</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">tok</span><span class="plain">-&gt;</span><span class="element">enode_arity</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="identifier">c</span><span class="plain"> += </span><span class="functiontext"><a href="20-eq.html#SP51">Equations::enode_count_var</a></span><span class="plain">(</span><span class="identifier">tok</span><span class="plain">-&gt;</span><span class="element">enode_operands</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">], </span><span class="identifier">to_solve</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="inwebparagraph"><a id="SP52"></a><b>&#167;52. Internal test case. </b>This is a little like those "advise all parties" law exam questions: we
parse the equation, then rearrange to solve it for each variable in turn.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::internal_test<button class="popup" onclick="togglePopup('usagePopup1485')">...<span class="popuptext" id="usagePopup1485">Usage of <b>Equations::internal_test</b>:<br>Test Scripts - <a href="26-ts.html#SP11">&#167;11</a></span></button></span><span class="plain">(</span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">E</span><span class="plain">) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">WH</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">&gt;(</span><span class="identifier">E</span><span class="plain">)) {</span>
<span class="identifier">E</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">&gt;, </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">WH</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">equation</span><span class="plain">-</span><span class="identifier">where</span><span class="plain">&gt;, </span><span class="constant">2</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain"> = </span><span class="functiontext"><a href="20-eq.html#SP10_1">Equations::new</a></span><span class="plain">(</span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="functiontext"><a href="20-eq.html#SP11">Equations::set_wherewithal</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">WH</span><span class="plain">);</span>
<span class="functiontext"><a href="20-eq.html#SP13">Equations::examine</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">);</span>
<span class="functiontext"><a href="26-ts.html#SP11">PL::Parsing::TestScripts::begin_internal_reporting</a></span><span class="plain">();</span>
<span class="functiontext"><a href="20-eq.html#SP53">Equations::log_equation_parsed</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">);</span>
<span class="reserved">equation_symbol</span><span class="plain"> *</span><span class="identifier">ev</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">symbol_list</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain">; </span><span class="identifier">ev</span><span class="plain"> = </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="20-eq.html#SP50">Equations::eqn_rearrange</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="identifier">ev</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">"Too hard to rearrange to solve for %W\n"</span><span class="plain">, </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Rearranged to solve for %W:\n"</span><span class="plain">, </span><span class="identifier">ev</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">);</span>
<span class="functiontext"><a href="20-eq.html#SP53">Equations::log_equation_parsed</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="functiontext"><a href="26-ts.html#SP11">PL::Parsing::TestScripts::end_internal_reporting</a></span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP53"></a><b>&#167;53. Indexing and logging. </b>And finally:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::log<button class="popup" onclick="togglePopup('usagePopup1486')">...<span class="popuptext" id="usagePopup1486">Usage of <b>Equations::log</b>:<br>Core Module - <a href="1-cm.html#SP5">&#167;5</a>, <a href="1-cm.html#SP6_6">&#167;6.6</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"{%W}"</span><span class="plain">, </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_text</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::log_equation_parsed<button class="popup" onclick="togglePopup('usagePopup1487')">...<span class="popuptext" id="usagePopup1487">Usage of <b>Equations::log_equation_parsed</b>:<br><a href="20-eq.html#SP52">&#167;52</a></span></button></span><span class="plain">(</span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">eqn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;null&gt;\n"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext"><a href="20-eq.html#SP27">Equations::log_equation_node</a></span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">parsed_equation</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Equations::index<button class="popup" onclick="togglePopup('usagePopup1488')">...<span class="popuptext" id="usagePopup1488">Usage of <b>Equations::index</b>:<br>none</span></button></span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ec</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="reserved">equation</span><span class="plain"> *</span><span class="identifier">eqn</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="reserved">equation</span><span class="plain">) { </span><span class="identifier">ec</span><span class="plain">++; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ec</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">); </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;b&gt;List of Named or Numbered Equations&lt;/b&gt; (&lt;i&gt;About equations&lt;/i&gt;"</span><span class="plain">);</span>
<span class="identifier">Index::DocReferences::link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"EQUATIONS"</span><span class="plain">); </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">")"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">, </span><span class="reserved">equation</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">mw</span><span class="plain"> = </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_no_text</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_name_text</span><span class="plain">) &gt; </span><span class="identifier">mw</span><span class="plain">)</span>
<span class="identifier">mw</span><span class="plain"> = </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_name_text</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">mw</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">Wordings::up_to</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_created_at</span><span class="plain">), </span><span class="identifier">mw</span><span class="plain">));</span>
<span class="identifier">Index::link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_created_at</span><span class="plain">)));</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" (%+W)"</span><span class="plain">, </span><span class="identifier">eqn</span><span class="plain">-&gt;</span><span class="element">equation_text</span><span class="plain">);</span>
<span class="identifier">HTML_TAG</span><span class="plain">(</span><span class="string">"br"</span><span class="plain">);</span>
<span class="identifier">N</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;i&gt;None&lt;/i&gt;.\n"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<!--End of weave-->
<script>
MathJax = {
tex: {
inlineMath: '$', '$'], ['\\(', '\\)'
},
svg: {
fontCache: 'global'
}
};
</script>
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
</script>
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
</main>
</body>
</html>