1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 00:24:22 +03:00
inform7/docs/assertions-module/7-eqt.html
2022-09-09 23:53:15 +01:00

2218 lines
429 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>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<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="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<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="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Preform-Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body class="commentary-font">
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-assets/Inform.png" height=72">
</a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../indocn.html">indoc</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
<li><a href="../inrtpsn.html">inrtps</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=18> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="../../../inweb/index.html">inweb</a></li>
<li><a href="../../../intest/index.html">intest</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Equations' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../inform7n.html">Inform7</a></li><li><a href="index.html">assertions</a></li><li><a href="index.html#7">Chapter 7: Other Gadgets</a></li><li><b>Equations</b></li></ul></div>
<p class="purpose">To manage and compile equations, which relate numerical quantities.</p>
<ul class="toc"><li><a href="7-eqt.html#SP10">&#167;10. Parsing equations</a></li><li><a href="7-eqt.html#SP12">&#167;12. Declaring symbols</a></li><li><a href="7-eqt.html#SP23">&#167;23. Equation nodes</a></li><li><a href="7-eqt.html#SP26">&#167;26. Tokenising equations</a></li><li><a href="7-eqt.html#SP29">&#167;29. The shift-reduce parser</a></li><li><a href="7-eqt.html#SP37">&#167;37. Typechecking equations</a></li><li><a href="7-eqt.html#SP40">&#167;40. Flotation</a></li><li><a href="7-eqt.html#SP41">&#167;41. Rearrangement</a></li><li><a href="7-eqt.html#SP43">&#167;43. Internal test case</a></li><li><a href="7-eqt.html#SP44">&#167;44. Logging</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. </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="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">equation</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">equation_text</span><span class="plain-syntax">; </span><span class="comment-syntax"> the text of the actual equation</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">equation_no_text</span><span class="plain-syntax">; </span><span class="comment-syntax"> the equation number (if any)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">equation_name_text</span><span class="plain-syntax">; </span><span class="comment-syntax"> the equation name (if any)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">where_text</span><span class="plain-syntax">; </span><span class="comment-syntax"> declaration of symbols</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">usage_text</span><span class="plain-syntax">; </span><span class="comment-syntax"> usage notes</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">equation_created_at</span><span class="plain-syntax">; </span><span class="comment-syntax"> where created in source</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">examined_already</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">parsed_equation</span><span class="plain-syntax">; </span><span class="comment-syntax"> and the equation itself (when eventually parsed)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">symbol_list</span><span class="plain-syntax">; </span><span class="comment-syntax"> the symbols used</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">equation_compilation_data</span><span class="plain-syntax"> </span><span class="identifier-syntax">compilation_data</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">equation</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure equation is accessed in 3/nuor, 5/id, 5/idf, 5/adf, 5/tpf, 5/rf, 5/rcd, 6/rls, 6/rlb, 6/fao, 6/act, 7/tc, 7/tbl and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </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 <span class="extract"><span class="extract-syntax">equation_symbol</span></span> structure.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">name</span><span class="plain-syntax">; </span><span class="comment-syntax"> always just one word, in fact</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">var_kind</span><span class="plain-syntax">; </span><span class="comment-syntax"> if a variable &mdash; must be quasinumerical</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">id_body</span><span class="plain-syntax"> *</span><span class="identifier-syntax">function_notated</span><span class="plain-syntax">; </span><span class="comment-syntax"> if a phrase QN to QN</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">var_const</span><span class="plain-syntax">; </span><span class="comment-syntax"> if a symbol for a constant value</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">temp_constant</span><span class="plain-syntax">; </span><span class="comment-syntax"> is this constant a substitution for one usage only?</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">next</span><span class="plain-syntax">; </span><span class="comment-syntax"> in the list belonging to the equation</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">local_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">local_map</span><span class="plain-syntax">; </span><span class="comment-syntax"> when being solved in a given stack frame</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">promote_local_to_real</span><span class="plain-syntax">; </span><span class="comment-syntax"> from integer, if necessary</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure equation_symbol is accessed in 2/ptmn, 2/cs, 2/ps, 2/is, 3/dlr, 3/pr, 3/tr, 3/nuor, 3/uor, 3/tr2, 3/dbtr, 3/rpr, 3/nar, 3/nlpr, 3/nrr, 3/npr, 3/nvr, 3/nar2, 4/rpt, 4/tc, 4/ass, 4/npa, 4/rk, 4/ass2, 4/imp, 5/id, 5/adf, 5/tpf, 5/po, 5/rcd, 6/rls, 6/rlb, 6/fao, 6/act, 6/sv, 7/tc, 7/tbl, 8/tcp, 8/abp, 8/cu and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </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="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">standard_equation_symbols</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>When parsed, the equation is stored as a tree of <span class="extract"><span class="extract-syntax">equation_node</span></span> 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 <span class="extract"><span class="extract-syntax">=</span></span> is itself considered an operation here.Thus:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> OPERATION_EQN =</span>
<span class="plain-syntax"> SYMBOL_EQN E</span>
<span class="plain-syntax"> OPERATION_EQN *</span>
<span class="plain-syntax"> SYMBOL_EQN m</span>
<span class="plain-syntax"> OPERATION_EQN ^</span>
<span class="plain-syntax"> SYMBOL_EQN c</span>
<span class="plain-syntax"> CONSTANT_EQN 2</span>
</pre>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">CONSTANT_EQN</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax"> </span><span class="comment-syntax"> a leaf, representing a quasinumerical constant not given a symbol</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">SYMBOL_EQN</span><span class="plain-syntax"> </span><span class="constant-syntax">2</span><span class="plain-syntax"> </span><span class="comment-syntax"> a leaf, representing a symbol</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">OPERATION_EQN</span><span class="plain-syntax"> </span><span class="constant-syntax">3</span><span class="plain-syntax"> </span><span class="comment-syntax"> a non-leaf, representing an operation</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. </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 code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">OPEN_BRACKET_EQN</span><span class="plain-syntax"> </span><span class="constant-syntax">4</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">CLOSE_BRACKET_EQN</span><span class="plain-syntax"> </span><span class="constant-syntax">5</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">END_EQN</span><span class="plain-syntax"> </span><span class="constant-syntax">6</span><span class="plain-syntax"> </span><span class="comment-syntax"> the end (left or right edge, really) of the equation</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. </b>Another temporary trick in parsing is to distinguish between explicit
multiplication, where the source text uses an asterisk <span class="extract"><span class="extract-syntax">*</span></span>, 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
<span class="extract"><span class="extract-syntax">TIMES_OPERATION</span></span> nodes in the eventual tree.
</p>
<p class="commentary">Implicit function application is similarly used to represent the unwritten
operation in <span class="extract"><span class="extract-syntax">log pi</span></span> &mdash; where the function <span class="extract"><span class="extract-syntax">log</span></span> is being applied to the
value <span class="extract"><span class="extract-syntax">pi</span></span>.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">IMPLICIT_TIMES_OPERATION</span><span class="plain-syntax"> </span><span class="constant-syntax">100</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">IMPLICIT_APPLICATION_OPERATION</span><span class="plain-syntax"> </span><span class="constant-syntax">101</span>
</pre>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. </b>And now the equation node structure:
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">MAX_EQN_ARITY</span><span class="plain-syntax"> </span><span class="constant-syntax">2</span><span class="plain-syntax"> </span><span class="comment-syntax"> at present all operations are at most binary</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">eqn_type</span><span class="plain-syntax">; </span><span class="comment-syntax"> one of the </span><span class="extract"><span class="extract-syntax">*_EQN</span></span><span class="comment-syntax"> values</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">eqn_operation</span><span class="plain-syntax">; </span><span class="comment-syntax"> one of the </span><span class="extract"><span class="extract-syntax">*_OPERATION</span></span><span class="comment-syntax"> values (see "Dimensions.w")</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">enode_arity</span><span class="plain-syntax">; </span><span class="comment-syntax"> 0 for a leaf</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">enode_operands</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_EQN_ARITY</span><span class="plain-syntax">]; </span><span class="comment-syntax"> the operands</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">leaf_constant</span><span class="plain-syntax">; </span><span class="comment-syntax"> if e.g. "21"</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">leaf_symbol</span><span class="plain-syntax">; </span><span class="comment-syntax"> if e.g. "G"</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">generalised_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">gK_before</span><span class="plain-syntax">; </span><span class="comment-syntax"> result of the node as it is</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">generalised_kind</span><span class="plain-syntax"> </span><span class="identifier-syntax">gK_after</span><span class="plain-syntax">; </span><span class="comment-syntax"> result of the node as we need it to be</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">enode_promotion</span><span class="plain-syntax">; </span><span class="comment-syntax"> promote this from an integer to a real number?</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">rational_n</span><span class="plain-syntax">; </span><span class="comment-syntax"> represents the rational number </span><span class="extract"><span class="extract-syntax">n/m</span></span><span class="comment-syntax">...</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">rational_m</span><span class="plain-syntax">; </span><span class="comment-syntax"> ...unless </span><span class="extract"><span class="extract-syntax">m</span></span><span class="comment-syntax"> is zero</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure equation_node is private to this section.</li></ul>
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>&#167;8. </b>Equation names follow the same conventions as table names.
</p>
<pre class="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-function-syntax">&lt;equation-name&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">equation</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{&lt;cardinal-number&gt;}</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">-</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> { 3, - }</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">equation</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{&lt;cardinal-number&gt;}</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> { 1, - }</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">equation</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">-</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> { 2, - }</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">equation</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">***</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP8_3" class="named-paragraph-link"><span class="named-paragraph">Issue PM_EquationMisnumbered problem</span><span class="named-paragraph-number">8.3</span></a></span>
</pre>
<ul class="endnotetexts"><li>This is <a href="../words-module/4-ap.html" class="internal">Preform grammar</a>, not regular C code.</li></ul>
<p class="commentary firstcommentary"><a id="SP8_1" class="paragraph-anchor"></a><b>&#167;8.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="commentary">Those equations are created by calling <span class="extract"><span class="Preform-extract-syntax">Equations::new</span></span> 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="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="function-syntax">Equations::new_at</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Equations::new_at</span></span>:<br/>Passes through Major Nodes - <a href="2-ptmn.html#SP3_1">&#167;3.1</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">anonymous</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::get_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="7-eqt.html#SP8_1" class="function-link"><span class="function-syntax">Equations::new</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">anonymous</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="function-syntax">Equations::new</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">Equations::new</span></span>:<br/><a href="7-eqt.html#SP43">&#167;43</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">anonymous</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="reserved-syntax">equation</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">equation_created_at</span><span class="plain-syntax"> == </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">equation_created_at</span><span class="plain-syntax"> = </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">where_text</span><span class="plain-syntax"> = </span><span class="identifier-syntax">EMPTY_WORDING</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">usage_text</span><span class="plain-syntax"> = </span><span class="identifier-syntax">EMPTY_WORDING</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">symbol_list</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">examined_already</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">NO</span><span class="plain-syntax"> = </span><span class="identifier-syntax">EMPTY_WORDING</span><span class="plain-syntax">, </span><span class="identifier-syntax">NA</span><span class="plain-syntax"> = </span><span class="identifier-syntax">EMPTY_WORDING</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">anonymous</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP8_1_1" class="named-paragraph-link"><span class="named-paragraph">Parse the equation's number and/or name</span><span class="named-paragraph-number">8.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP8_1_3" class="named-paragraph-link"><span class="named-paragraph">Register any names for this equation</span><span class="named-paragraph-number">8.1.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="function-syntax">&lt;equation-where&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">GET_RW</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;equation-where&gt;</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP9" class="function-link"><span class="function-syntax">Equations::set_wherewithal</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">GET_RW</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;equation-where&gt;</span><span class="plain-syntax">, </span><span class="constant-syntax">2</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">equation_no_text</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NO</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">equation_name_text</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NA</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="function-syntax">&lt;text-ending-in-comma&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">GET_RW</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;text-ending-in-comma&gt;</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">equation_text</span><span class="plain-syntax"> = </span><span class="identifier-syntax">W</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">compilation_data</span><span class="plain-syntax"> = </span><span class="identifier-syntax">RTEquations::new_compilation_data</span><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP8_2" class="paragraph-anchor"></a><b>&#167;8.2. </b></p>
<pre class="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-function-syntax">&lt;text-ending-in-comma&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">,</span>
</pre>
<ul class="endnotetexts"><li>This is <a href="../words-module/4-ap.html" class="internal">Preform grammar</a>, not regular C code.</li></ul>
<p class="commentary firstcommentary"><a id="SP8_3" class="paragraph-anchor"></a><b>&#167;8.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 <span class="extract"><span class="Preform-extract-syntax">EQUATION_NT</span></span>).
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Issue PM_EquationMisnumbered problem</span><span class="named-paragraph-number">8.3</span></span><span class="Preform-comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::sentence_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(), </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationMisnumbered</span><span class="plain-syntax">),</span>
<span class="plain-syntax"> </span><span class="string-syntax">"the top line of this equation declaration seems not to be a "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"legal equation number or name"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"and should read something like 'Equation 6', or 'Equation - "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"Newton's Second Law', or 'Equation 41 - Coulomb's Law'."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> ==&gt; { </span><span class="constant-syntax">0</span><span class="plain-syntax">, - };</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP8">&#167;8</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP8_1_1" class="paragraph-anchor"></a><b>&#167;8.1.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Parse the equation's number and/or name</span><span class="named-paragraph-number">8.1.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Wordings::last_word_of_formatted_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">TW</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Wordings::up_to</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Wordings::from</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">+1);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="function-syntax">&lt;equation-name&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">TW</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="function-syntax">&lt;&lt;r&gt;&gt;</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">: </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax">: </span><span class="identifier-syntax">NO</span><span class="plain-syntax"> = </span><span class="identifier-syntax">GET_RW</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;equation-name&gt;</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="constant-syntax">2</span><span class="plain-syntax">: </span><span class="identifier-syntax">NA</span><span class="plain-syntax"> = </span><span class="identifier-syntax">GET_RW</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;equation-name&gt;</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="constant-syntax">3</span><span class="plain-syntax">: </span><span class="identifier-syntax">NO</span><span class="plain-syntax"> = </span><span class="identifier-syntax">GET_RW</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;equation-name&gt;</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">NA</span><span class="plain-syntax"> = </span><span class="identifier-syntax">GET_RW</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;equation-name&gt;</span><span class="plain-syntax">, </span><span class="constant-syntax">2</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"malformed equation sentence"</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP8_1">&#167;8.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP8_1_2" class="paragraph-anchor"></a><b>&#167;8.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="commentary">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="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-function-syntax">&lt;equation-names-construction&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">equation</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">equation</span>
</pre>
<ul class="endnotetexts"><li>This is <a href="../words-module/4-ap.html" class="internal">Preform grammar</a>, not regular C code.</li></ul>
<p class="commentary firstcommentary"><a id="SP8_1_3" class="paragraph-anchor"></a><b>&#167;8.1.3. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Register any names for this equation</span><span class="named-paragraph-number">8.1.3</span></span><span class="Preform-comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::nonempty</span><span class="plain-syntax">(</span><span class="identifier-syntax">NO</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">word_assemblage</span><span class="plain-syntax"> </span><span class="identifier-syntax">wa</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PreformUtilities::merge</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;equation-names-construction&gt;</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WordAssemblages::from_wording</span><span class="plain-syntax">(</span><span class="identifier-syntax">NO</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">AW</span><span class="plain-syntax"> = </span><span class="identifier-syntax">WordAssemblages::to_wording</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">wa</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Nouns::new_proper_noun</span><span class="plain-syntax">(</span><span class="identifier-syntax">AW</span><span class="plain-syntax">, </span><span class="identifier-syntax">NEUTER_GENDER</span><span class="plain-syntax">, </span><span class="identifier-syntax">ADD_TO_LEXICON_NTOPT</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">EQUATION_MC</span><span class="plain-syntax">, </span><span class="identifier-syntax">Rvalues::from_equation</span><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">), </span><span class="identifier-syntax">Task::language_of_syntax</span><span class="plain-syntax">());</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::nonempty</span><span class="plain-syntax">(</span><span class="identifier-syntax">NA</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="function-syntax">&lt;s-type-expression-or-value&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">NA</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_wording_as_source</span><span class="plain-syntax">(1, </span><span class="identifier-syntax">NA</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::handmade_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(), </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationMisnamed</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::issue_problem_segment</span><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="string-syntax">"The equation name %1 will have to be disallowed as it is text "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"which already has a meaning to Inform. For instance, creating "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"an equation called 'Equation - 2 + 2' would be disallowed "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"because Inform would read '2 + 2' as arithmetic, not a name."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::issue_problem_end</span><span class="plain-syntax">();</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Nouns::new_proper_noun</span><span class="plain-syntax">(</span><span class="identifier-syntax">NA</span><span class="plain-syntax">, </span><span class="identifier-syntax">NEUTER_GENDER</span><span class="plain-syntax">, </span><span class="identifier-syntax">ADD_TO_LEXICON_NTOPT</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">EQUATION_MC</span><span class="plain-syntax">, </span><span class="identifier-syntax">Rvalues::from_equation</span><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">), </span><span class="identifier-syntax">Task::language_of_syntax</span><span class="plain-syntax">());</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">word_assemblage</span><span class="plain-syntax"> </span><span class="identifier-syntax">wa</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PreformUtilities::merge</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;equation-names-construction&gt;</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WordAssemblages::from_wording</span><span class="plain-syntax">(</span><span class="identifier-syntax">NA</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">AW</span><span class="plain-syntax"> = </span><span class="identifier-syntax">WordAssemblages::to_wording</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">wa</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Nouns::new_proper_noun</span><span class="plain-syntax">(</span><span class="identifier-syntax">AW</span><span class="plain-syntax">, </span><span class="identifier-syntax">NEUTER_GENDER</span><span class="plain-syntax">, </span><span class="identifier-syntax">ADD_TO_LEXICON_NTOPT</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">EQUATION_MC</span><span class="plain-syntax">, </span><span class="identifier-syntax">Rvalues::from_equation</span><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">), </span><span class="identifier-syntax">Task::language_of_syntax</span><span class="plain-syntax">());</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP8_1">&#167;8.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>&#167;9. </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="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::set_wherewithal</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">Equations::set_wherewithal</span></span>:<br/><a href="7-eqt.html#SP8_1">&#167;8.1</a>, <a href="7-eqt.html#SP43">&#167;43</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">where_text</span><span class="plain-syntax"> = </span><span class="identifier-syntax">W</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP10" class="paragraph-anchor"></a><b>&#167;10. Parsing equations. </b>So now it's later on. We can run through all the equations displayed in the
source text:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::traverse_to_stock</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="reserved-syntax">equation</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">equation_created_at</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP11" class="function-link"><span class="function-syntax">Equations::examine</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP11" class="paragraph-anchor"></a><b>&#167;11. </b>And, as with creation, <span class="extract"><span class="extract-syntax">Equations::examine</span></span> 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="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::examine</span><button class="popup" onclick="togglePopup('usagePopup4')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup4">Usage of <span class="code-font"><span class="function-syntax">Equations::examine</span></span>:<br/><a href="7-eqt.html#SP10">&#167;10</a>, <a href="7-eqt.html#SP43">&#167;43</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">examined_already</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">examined_already</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP13" class="function-link"><span class="function-syntax">Equations::eqn_declare_symbols</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP19" class="function-link"><span class="function-syntax">Equations::eqn_declare_standard_symbols</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP26" class="function-link"><span class="function-syntax">Equations::eqn_parse</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP37" class="function-link"><span class="function-syntax">Equations::eqn_typecheck</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP25" class="function-link"><span class="function-syntax">Equations::log_equation_node</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP12" class="paragraph-anchor"></a><b>&#167;12. 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="commentary">At the earlier stages of parsing, we simply split the "where" text away
using this:
</p>
<pre class="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-function-syntax">&lt;equation-where&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">where</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span>
</pre>
<ul class="endnotetexts"><li>This is <a href="../words-module/4-ap.html" class="internal">Preform grammar</a>, not regular C code.</li></ul>
<p class="commentary firstcommentary"><a id="SP13" class="paragraph-anchor"></a><b>&#167;13. </b>For a displayed equation, the following parses the "where..." text, which
is expected to declare every symbol occurring in it.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::eqn_declare_symbols</span><button class="popup" onclick="togglePopup('usagePopup5')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup5">Usage of <span class="code-font"><span class="function-syntax">Equations::eqn_declare_symbols</span></span>:<br/><a href="7-eqt.html#SP11">&#167;11</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::empty</span><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">where_text</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">result</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP16" class="function-link"><span class="function-syntax">Equations::eqn_declare_variables_inner</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">where_text</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">changed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">changed</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">changed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">symbol_list</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">var_kind</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_symbol_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">BelievedImpossible</span><span class="plain-syntax">),</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">where_text</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"each symbol in a equation has to be declared with a kind of "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"value or else an actual value. So '...where N = 1701.' or "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"'...where N, M are numbers.' would be fine."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">result</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">var_kind</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">var_kind</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">var_const</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">var_const</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">changed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">result</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP14" class="paragraph-anchor"></a><b>&#167;14. </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="commentary">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="commentary">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 <span class="extract"><span class="extract-syntax">TRUE</span></span> if all went well, or <span class="extract"><span class="extract-syntax">FALSE</span></span> if problem messages had to be
issued.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">equation_being_declared</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">equation_declared_temporarily</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">eq_symbol_wn</span><span class="plain-syntax"> = -1;</span>
</pre>
<p class="commentary firstcommentary"><a id="SP15" class="paragraph-anchor"></a><b>&#167;15. </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="commentary">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="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-function-syntax">&lt;equation-where-list&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP15_1" class="named-paragraph-link"><span class="named-paragraph">Match only when looking ahead</span><span class="named-paragraph-number">15.1</span></a></span>
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;equation-where-setting-entry&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;equation-where-tail&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> { 0, - }</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;equation-where-setting-entry&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> { 0, - }</span>
<span class="Preform-function-syntax">&lt;equation-where-tail&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">,</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">_and</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;equation-where-list&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> { 0, - }</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">_,/and</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;equation-where-list&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> { 0, - }</span>
<span class="Preform-function-syntax">&lt;equation-where-setting-entry&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> { lookahead }</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;equation-where-setting&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP15_2" class="named-paragraph-link"><span class="named-paragraph">Declare an equation variable</span><span class="named-paragraph-number">15.2</span></a></span>
<span class="Preform-function-syntax">&lt;equation-where-setting&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;equation-symbol&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">is/are</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;k-kind&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> { EQW_IDENTIFIES_KIND, RP[2] }; eq_symbol_wn = R[1];</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;equation-symbol&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">is/are</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;s-value&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> { EQW_IDENTIFIES_VALUE, RP[2] }; eq_symbol_wn = R[1];</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;equation-symbol&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">is/are</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP15_3" class="named-paragraph-link"><span class="named-paragraph">Issue PM_EquationSymbolNonValue problem</span><span class="named-paragraph-number">15.3</span></a></span>
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;equation-symbol&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">=</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;k-kind&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP15_4" class="named-paragraph-link"><span class="named-paragraph">Issue PM_EquationSymbolEqualsKOV problem</span><span class="named-paragraph-number">15.4</span></a></span>
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;equation-symbol&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">=</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;s-value&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> { EQW_IDENTIFIES_VALUE, RP[2] }; eq_symbol_wn = R[1];</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;equation-symbol&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">=</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP15_3" class="named-paragraph-link"><span class="named-paragraph">Issue PM_EquationSymbolNonValue problem</span><span class="named-paragraph-number">15.3</span></a></span>
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;equation-symbol&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> { EQW_IDENTIFIES_NOTHING, NULL }; eq_symbol_wn = R[1];</span>
<span class="Preform-function-syntax">&lt;equation-symbol&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;valid-equation-symbol&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> { pass 1 }</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">###</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP15_5" class="named-paragraph-link"><span class="named-paragraph">Issue PM_EquationSymbolMalformed problem</span><span class="named-paragraph-number">15.5</span></a></span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP15_6" class="named-paragraph-link"><span class="named-paragraph">Issue PM_EquationSymbolMisdeclared problem</span><span class="named-paragraph-number">15.6</span></a></span>
</pre>
<ul class="endnotetexts"><li>This is <a href="../words-module/4-ap.html" class="internal">Preform grammar</a>, not regular C code.</li></ul>
<p class="commentary firstcommentary"><a id="SP15_1" class="paragraph-anchor"></a><b>&#167;15.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Match only when looking ahead</span><span class="named-paragraph-number">15.1</span></span><span class="Preform-comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">eq_symbol_wn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> ==&gt; { </span><span class="constant-syntax">0</span><span class="plain-syntax">, - };</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">preform_lookahead_mode</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP15">&#167;15</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP15_2" class="paragraph-anchor"></a><b>&#167;15.2. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Declare an equation variable</span><span class="named-paragraph-number">15.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><a href="7-eqt.html#SP16" class="function-link"><span class="function-syntax">Equations::eqn_dec_var</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">equation_being_declared</span><span class="plain-syntax">, </span><span class="identifier-syntax">Wordings::one_word</span><span class="plain-syntax">(</span><span class="identifier-syntax">eq_symbol_wn</span><span class="plain-syntax">), </span><span class="identifier-syntax">R</span><span class="plain-syntax">[1], </span><span class="identifier-syntax">RP</span><span class="plain-syntax">[1]);</span>
<span class="plain-syntax"> ==&gt; { -, - };</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP15">&#167;15</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP15_3" class="paragraph-anchor"></a><b>&#167;15.3. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Issue PM_EquationSymbolNonValue problem</span><span class="named-paragraph-number">15.3</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (!</span><span class="identifier-syntax">preform_lookahead_mode</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_symbol_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationSymbolNonValue</span><span class="plain-syntax">),</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">equation_being_declared</span><span class="plain-syntax">, </span><span class="identifier-syntax">Wordings::one_word</span><span class="plain-syntax">(</span><span class="identifier-syntax">R</span><span class="plain-syntax">[1]),</span>
<span class="plain-syntax"> </span><span class="string-syntax">"this has neither a kind of value nor an actual value."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> ==&gt; { </span><span class="constant-syntax">EQW_IDENTIFIES_PROBLEM</span><span class="plain-syntax">, - };</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP15">&#167;15</a> (twice).</li></ul>
<p class="commentary firstcommentary"><a id="SP15_4" class="paragraph-anchor"></a><b>&#167;15.4. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Issue PM_EquationSymbolEqualsKOV problem</span><span class="named-paragraph-number">15.4</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (!</span><span class="identifier-syntax">preform_lookahead_mode</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_symbol_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationSymbolEqualsKOV</span><span class="plain-syntax">),</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">equation_being_declared</span><span class="plain-syntax">, </span><span class="identifier-syntax">Wordings::one_word</span><span class="plain-syntax">(</span><span class="identifier-syntax">R</span><span class="plain-syntax">[1]),</span>
<span class="plain-syntax"> </span><span class="string-syntax">"'is' should be used, not '=', for a kind of value rather "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"than an actual value."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> ==&gt; { </span><span class="constant-syntax">EQW_IDENTIFIES_PROBLEM</span><span class="plain-syntax">, - };</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP15">&#167;15</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP15_5" class="paragraph-anchor"></a><b>&#167;15.5. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Issue PM_EquationSymbolMalformed problem</span><span class="named-paragraph-number">15.5</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (!</span><span class="identifier-syntax">preform_lookahead_mode</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_symbol_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationSymbolMalformed</span><span class="plain-syntax">),</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">equation_being_declared</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"a symbol in a equation has to be a sequence of one to ten "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"letters optionally followed by a number from 0 to 99, so "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"'G', 'm', 'pi' and 'KE1' are all legal symbol names. But "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"this one is not."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> ==&gt; { -1, - };</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP15">&#167;15</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP15_6" class="paragraph-anchor"></a><b>&#167;15.6. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Issue PM_EquationSymbolMisdeclared problem</span><span class="named-paragraph-number">15.6</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (!</span><span class="identifier-syntax">preform_lookahead_mode</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::sentence_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(),</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationSymbolMisdeclared</span><span class="plain-syntax">),</span>
<span class="plain-syntax"> </span><span class="string-syntax">"the symbols here are not declared properly"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"and should each be declared with a kind of value or else an "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"actual value."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> ==&gt; { -1, - };</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP15">&#167;15</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP16" class="paragraph-anchor"></a><b>&#167;16. </b></p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">EQW_IDENTIFIES_KIND</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">EQW_IDENTIFIES_VALUE</span><span class="plain-syntax"> </span><span class="constant-syntax">2</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">EQW_IDENTIFIES_NOTHING</span><span class="plain-syntax"> </span><span class="constant-syntax">3</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">EQW_IDENTIFIES_PROBLEM</span><span class="plain-syntax"> </span><span class="constant-syntax">4</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::eqn_declare_variables_inner</span><button class="popup" onclick="togglePopup('usagePopup6')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup6">Usage of <span class="code-font"><span class="function-syntax">Equations::eqn_declare_variables_inner</span></span>:<br/><a href="7-eqt.html#SP13">&#167;13</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">temp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">equation_being_declared</span><span class="plain-syntax"> = </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">equation_declared_temporarily</span><span class="plain-syntax"> = </span><span class="identifier-syntax">temp</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">pc</span><span class="plain-syntax"> = </span><span class="identifier-syntax">problem_count</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="function-syntax">&lt;equation-where-list&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">problem_count</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">pc</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::eqn_dec_var</span><button class="popup" onclick="togglePopup('usagePopup7')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup7">Usage of <span class="code-font"><span class="function-syntax">Equations::eqn_dec_var</span></span>:<br/><a href="7-eqt.html#SP15_2">&#167;15.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">XP</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">spec</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">temp</span><span class="plain-syntax"> = </span><span class="identifier-syntax">equation_declared_temporarily</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">X</span><span class="plain-syntax"> == </span><span class="constant-syntax">EQW_IDENTIFIES_PROBLEM</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">Wordings::empty</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">))) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">X</span><span class="plain-syntax"> != </span><span class="constant-syntax">EQW_IDENTIFIES_NOTHING</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP16_1" class="named-paragraph-link"><span class="named-paragraph">Find the actual value, or kind of value, which the symbol is to match</span><span class="named-paragraph-number">16.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">temp</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP16_2" class="named-paragraph-link"><span class="named-paragraph">Assign the given value to this symbol on a temporary basis</span><span class="named-paragraph-number">16.2</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><a href="7-eqt.html#SP20" class="function-link"><span class="function-syntax">Equations::eqn_add_symbol</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">spec</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP16_1" class="paragraph-anchor"></a><b>&#167;16.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="commentary">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="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Find the actual value, or kind of value, which the symbol is to match</span><span class="named-paragraph-number">16.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">spec</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">X</span><span class="plain-syntax"> == </span><span class="constant-syntax">EQW_IDENTIFIES_KIND</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><span class="identifier-syntax">XP</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">temp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_symbol_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationSymbolVague</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"when an equation is named for use in a 'let' "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"phrase, any variables listed under 'where...' have "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"to be given definite values, not just vaguely said "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"to have particular kinds. Otherwise, I can't do any "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"calculation with them."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">X</span><span class="plain-syntax"> == </span><span class="constant-syntax">EQW_IDENTIFIES_VALUE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">spec</span><span class="plain-syntax"> = </span><span class="identifier-syntax">XP</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Specifications::to_kind</span><span class="plain-syntax">(</span><span class="identifier-syntax">spec</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">K</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">Kinds::Behaviour::is_quasinumerical</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_symbol_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationSymbolNonNumeric</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"this has a kind of value on which arithmetic cannot be done, "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"so it can have no place in an equation."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP16">&#167;16</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP16_2" class="paragraph-anchor"></a><b>&#167;16.2. </b>At this point we know the user means the variable named at word <span class="extract"><span class="extract-syntax">wn</span></span>
to have the temporary value <span class="extract"><span class="extract-syntax">spec</span></span>, and we have to identify that as one
of the symbols:
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Assign the given value to this symbol on a temporary basis</span><span class="named-paragraph-number">16.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">symbol_list</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::match_cs</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Kinds::eq</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">var_kind</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_symbol_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationSymbolBadSub</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"you're using 'where' to substitute something into this "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"symbol which has the wrong kind of value."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">temp_constant</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">var_const</span><span class="plain-syntax"> = </span><span class="identifier-syntax">spec</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_symbol_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationSymbolSpurious</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"when 'where' is used to supply values to plug into a "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"named equation as part of a 'let' phrase, you can only "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"supply values for symbols actually used in that equation. "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"This one doesn't seem to occur there."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP16">&#167;16</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP17" class="paragraph-anchor"></a><b>&#167;17. </b>We won't want those temporary assignments hanging around, so once the
hurly-burly is done, the following is called:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::eqn_remove_temp_variables</span><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">symbol_list</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">temp_constant</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">var_const</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">temp_constant</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP18" class="paragraph-anchor"></a><b>&#167;18. </b>As we saw, permanent symbol declarations cause <span class="extract"><span class="extract-syntax">Equations::eqn_add_symbol</span></span> 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="commentary">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="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::declare_local_variables</span><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">stack_frame</span><span class="plain-syntax"> *</span><span class="identifier-syntax">frame</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Frames::current_stack_frame</span><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">frame</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">local_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">lvar</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER_LOCALS_IN_FRAME</span><span class="plain-syntax">(</span><span class="identifier-syntax">lvar</span><span class="plain-syntax">, </span><span class="identifier-syntax">frame</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">lvar</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">allocated</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP18" class="function-link"><span class="function-syntax">Equations::declare_local</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">lvar</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">current_usage</span><span class="plain-syntax">.</span><span class="identifier-syntax">varname</span><span class="plain-syntax">, </span><span class="identifier-syntax">lvar</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">current_usage</span><span class="plain-syntax">.</span><span class="identifier-syntax">kind_as_declared</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
<span class="comment-syntax"> which calls the following for each current local variable in turn:</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::declare_local</span><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><a href="7-eqt.html#SP22" class="function-link"><span class="function-syntax">Equations::equation_symbol_legal</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) &amp;&amp; (</span><span class="identifier-syntax">Kinds::Behaviour::is_quasinumerical</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">)))</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP20" class="function-link"><span class="function-syntax">Equations::eqn_add_symbol</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP19" class="paragraph-anchor"></a><b>&#167;19. </b>Next we add "e" and "pi". These are added last, so that any local
declarations will trump them.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::eqn_declare_standard_symbols</span><button class="popup" onclick="togglePopup('usagePopup8')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup8">Usage of <span class="code-font"><span class="function-syntax">Equations::eqn_declare_standard_symbols</span></span>:<br/><a href="7-eqt.html#SP11">&#167;11</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">standard_equation_symbols</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">TCW</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Feeds::feed_C_string</span><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"e pi"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_THROUGH_WORDING</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">, </span><span class="identifier-syntax">TCW</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">V</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Wordings::one_word</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="function-syntax">&lt;s-type-expression&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">V</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">spec</span><span class="plain-syntax"> = </span><span class="function-syntax">&lt;&lt;rp&gt;&gt;</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP20" class="function-link"><span class="function-syntax">Equations::eqn_add_symbol</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">V</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_real_number</span><span class="plain-syntax">, </span><span class="identifier-syntax">spec</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">id_body</span><span class="plain-syntax"> *</span><span class="identifier-syntax">idb</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">idb</span><span class="plain-syntax">, </span><span class="reserved-syntax">id_body</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><a href="5-tpf.html#SP11" class="function-link"><span class="function-syntax">ToPhraseFamily::get_equation_form</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">idb</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">head_of_defn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::nonempty</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP20" class="function-link"><span class="function-syntax">Equations::eqn_add_symbol</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_real_number</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">function_notated</span><span class="plain-syntax"> = </span><span class="identifier-syntax">idb</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP20" class="paragraph-anchor"></a><b>&#167;20. </b>And that about wraps up symbol declaration, except for the routine which
actually declares symbols:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="function-syntax">Equations::eqn_add_symbol</span><button class="popup" onclick="togglePopup('usagePopup9')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup9">Usage of <span class="code-font"><span class="function-syntax">Equations::eqn_add_symbol</span></span>:<br/><a href="7-eqt.html#SP16">&#167;16</a>, <a href="7-eqt.html#SP18">&#167;18</a>, <a href="7-eqt.html#SP19">&#167;19</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax">, </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">spec</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Wordings::first_word</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> **</span><span class="identifier-syntax">list_head</span><span class="plain-syntax"> = &amp;</span><span class="identifier-syntax">standard_equation_symbols</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">) </span><span class="identifier-syntax">list_head</span><span class="plain-syntax"> = &amp;(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">symbol_list</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ev</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = *</span><span class="identifier-syntax">list_head</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::match_cs</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">var_kind</span><span class="plain-syntax"> = </span><span class="identifier-syntax">K</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">function_notated</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">var_const</span><span class="plain-syntax"> = </span><span class="identifier-syntax">spec</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">list_head</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) *</span><span class="identifier-syntax">list_head</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ev</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">f</span><span class="plain-syntax"> = *</span><span class="identifier-syntax">list_head</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">f</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">f</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">)) </span><span class="identifier-syntax">f</span><span class="plain-syntax"> = </span><span class="identifier-syntax">f</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">f</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ev</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax"> = </span><span class="identifier-syntax">W</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">temp_constant</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">ev</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP21" class="paragraph-anchor"></a><b>&#167;21. </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 <span class="extract"><span class="extract-syntax">[A-Za-z]?{1,8}\d?{0,2}</span></span>.
</p>
<pre class="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-function-syntax">&lt;valid-equation-symbol&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">internal</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">if</span><span class="Preform-plain-syntax"> (</span><a href="7-eqt.html#SP22" class="function-link"><span class="Preform-function-syntax">Equations::equation_symbol_legal</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">)) {</span>
<span class="Preform-plain-syntax"> ==&gt; { </span><span class="Preform-identifier-syntax">Wordings::first_wn</span><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">), - };</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">return</span><span class="Preform-plain-syntax"> </span><span class="Preform-identifier-syntax">TRUE</span><span class="Preform-plain-syntax">;</span>
<span class="Preform-plain-syntax"> }</span>
<span class="Preform-plain-syntax"> ==&gt; { </span><span class="Preform-identifier-syntax">fail</span><span class="Preform-plain-syntax"> </span><span class="Preform-identifier-syntax">nonterminal</span><span class="Preform-plain-syntax"> };</span>
<span class="Preform-plain-syntax">}</span>
</pre>
<ul class="endnotetexts"><li>This is <a href="../words-module/4-ap.html" class="internal">Preform grammar</a>, not regular C code.</li></ul>
<p class="commentary firstcommentary"><a id="SP22" class="paragraph-anchor"></a><b>&#167;22. </b>Using:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::equation_symbol_legal</span><button class="popup" onclick="togglePopup('usagePopup10')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup10">Usage of <span class="code-font"><span class="function-syntax">Equations::equation_symbol_legal</span></span>:<br/><a href="7-eqt.html#SP18">&#167;18</a>, <a href="7-eqt.html#SP21">&#167;21</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::length</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">) == </span><span class="constant-syntax">1</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lexer::word_raw_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">j</span><span class="plain-syntax">, </span><span class="identifier-syntax">letters</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">digits</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">name_legal</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">j</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">]; </span><span class="identifier-syntax">j</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Characters::isdigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">c</span><span class="plain-syntax">)) </span><span class="identifier-syntax">digits</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Characters::isalpha</span><span class="plain-syntax">(</span><span class="identifier-syntax">c</span><span class="plain-syntax">)) { </span><span class="identifier-syntax">letters</span><span class="plain-syntax">++; </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">digits</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">name_legal</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">name_legal</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">j</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">13</span><span class="plain-syntax">) </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">letters</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">10</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">digits</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">2</span><span class="plain-syntax">)) </span><span class="identifier-syntax">name_legal</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">name_legal</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP23" class="paragraph-anchor"></a><b>&#167;23. Equation nodes. </b>The parsed equation is a tree full of nodes, so we need routines to make
and examine them.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="function-syntax">Equations::enode_new</span><button class="popup" onclick="togglePopup('usagePopup11')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup11">Usage of <span class="code-font"><span class="function-syntax">Equations::enode_new</span></span>:<br/><a href="7-eqt.html#SP24">&#167;24</a>, <a href="7-eqt.html#SP26">&#167;26</a>, <a href="7-eqt.html#SP26_1_3">&#167;26.1.3</a>, <a href="7-eqt.html#SP30">&#167;30</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">enode</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">equation_node</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">eqn_type</span><span class="plain-syntax"> = </span><span class="identifier-syntax">t</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">eqn_operation</span><span class="plain-syntax"> = -1;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">enode_arity</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">leaf_constant</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">leaf_symbol</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">gK_before</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::new_gk</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_value</span><span class="plain-syntax">); </span><span class="comment-syntax"> unknown for now</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">gK_after</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::new_gk</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_value</span><span class="plain-syntax">); </span><span class="comment-syntax"> unknown for now</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">enode_promotion</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">rational_n</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">rational_m</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP24" class="paragraph-anchor"></a><b>&#167;24. </b>This is how we make the three kinds of enode permitted in the final compiled
equation. (The other kinds can be created using <span class="extract"><span class="extract-syntax">Equations::enode_new</span></span> directly.)
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="function-syntax">Equations::enode_new_op</span><button class="popup" onclick="togglePopup('usagePopup12')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup12">Usage of <span class="code-font"><span class="function-syntax">Equations::enode_new_op</span></span>:<br/><a href="7-eqt.html#SP26_1_3">&#167;26.1.3</a>, <a href="7-eqt.html#SP26_2">&#167;26.2</a>, <a href="7-eqt.html#SP41_3_1">&#167;41.3.1</a>, <a href="7-eqt.html#SP41_4">&#167;41.4</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">op</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">enode</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP23" class="function-link"><span class="function-syntax">Equations::enode_new</span></a><span class="plain-syntax">(</span><span class="constant-syntax">OPERATION_EQN</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">eqn_operation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">op</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="function-syntax">Equations::enode_new_symbol</span><button class="popup" onclick="togglePopup('usagePopup13')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup13">Usage of <span class="code-font"><span class="function-syntax">Equations::enode_new_symbol</span></span>:<br/><a href="7-eqt.html#SP26_1_1_1">&#167;26.1.1.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ev</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">enode</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP23" class="function-link"><span class="function-syntax">Equations::enode_new</span></a><span class="plain-syntax">(</span><span class="constant-syntax">SYMBOL_EQN</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">leaf_symbol</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ev</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="function-syntax">Equations::enode_new_constant</span><button class="popup" onclick="togglePopup('usagePopup14')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup14">Usage of <span class="code-font"><span class="function-syntax">Equations::enode_new_constant</span></span>:<br/><a href="7-eqt.html#SP26_1_2">&#167;26.1.2</a>, <a href="7-eqt.html#SP41_3_1">&#167;41.3.1</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">spec</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">enode</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP23" class="function-link"><span class="function-syntax">Equations::enode_new</span></a><span class="plain-syntax">(</span><span class="constant-syntax">CONSTANT_EQN</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">leaf_constant</span><span class="plain-syntax"> = </span><span class="identifier-syntax">spec</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">enode</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP25" class="paragraph-anchor"></a><b>&#167;25. </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="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::log_equation_node</span><button class="popup" onclick="togglePopup('usagePopup15')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup15">Usage of <span class="code-font"><span class="function-syntax">Equations::log_equation_node</span></span>:<br/><a href="7-eqt.html#SP11">&#167;11</a>, <a href="7-eqt.html#SP29">&#167;29</a>, <a href="7-eqt.html#SP39_4">&#167;39.4</a>, <a href="7-eqt.html#SP41_3_2">&#167;41.3.2</a>, <a href="7-eqt.html#SP44">&#167;44</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP25" class="function-link"><span class="function-syntax">Equations::log_equation_node_inner</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::log_equation_node_inner</span><span class="plain-syntax">(</span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">d</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">d</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax">+1&lt;</span><span class="identifier-syntax">d</span><span class="plain-syntax">) </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">" "</span><span class="plain-syntax">); </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"+---"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;NULL&gt;\n"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax"> == </span><span class="constant-syntax">OPERATION_EQN</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">PLUS_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;add&gt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">MINUS_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;subtract&gt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">DIVIDE_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;divide&gt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">TIMES_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;multiply&gt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">IMPLICIT_TIMES_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;implicitly multiply&gt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">IMPLICIT_APPLICATION_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;apply function&gt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">EQUALS_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;set equal&gt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">ROOT_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;square root&gt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">REALROOT_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;real square root&gt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">CUBEROOT_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;cube root&gt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">POWER_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;to the power&gt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">UNARY_MINUS_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;unary subtraction&gt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;op-%d&gt;"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax"> == </span><span class="constant-syntax">SYMBOL_EQN</span><span class="plain-syntax">) </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;symbol-%W&gt;"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">leaf_symbol</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax"> == </span><span class="constant-syntax">CONSTANT_EQN</span><span class="plain-syntax">) </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;constant-$P&gt;"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">leaf_constant</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax"> == </span><span class="constant-syntax">OPEN_BRACKET_EQN</span><span class="plain-syntax">) </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;open-bracket&gt;"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax"> == </span><span class="constant-syntax">CLOSE_BRACKET_EQN</span><span class="plain-syntax">) </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;close-bracket&gt;"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax"> == </span><span class="constant-syntax">END_EQN</span><span class="plain-syntax">) </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;end&gt;"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> { </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;bad-eqn&gt;\n"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">" : "</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::log_gk</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">", "</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::log_gk</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"\n"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax"> == </span><span class="constant-syntax">OPERATION_EQN</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="function-syntax">&lt;tok-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP25" class="function-link"><span class="function-syntax">Equations::log_equation_node_inner</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">d</span><span class="plain-syntax">+1);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP26" class="paragraph-anchor"></a><b>&#167;26. 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 <span class="extract"><span class="extract-syntax">+</span></span>, and boundaries can
also occur in runs of alphanumerics if we spot symbol names: thus <span class="extract"><span class="extract-syntax">mv^21</span></span>
will be divided into tokens <span class="extract"><span class="extract-syntax">m</span></span>, <span class="extract"><span class="extract-syntax">v</span></span>, <span class="extract"><span class="extract-syntax">^</span></span>, <span class="extract"><span class="extract-syntax">21</span></span>.
</p>
<p class="commentary">The following routine sends each token in turn to the shift/reduce parser
below, encoding each token as an enode. We return <span class="extract"><span class="extract-syntax">NULL</span></span> if a problem message
has to be issued, or else a pointer to the parsed tree if we succeed.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">MAX_ENODES_IN_EXPRESSION</span><span class="plain-syntax"> </span><span class="constant-syntax">100</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="function-syntax">Equations::eqn_parse</span><button class="popup" onclick="togglePopup('usagePopup16')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup16">Usage of <span class="code-font"><span class="function-syntax">Equations::eqn_parse</span></span>:<br/><a href="7-eqt.html#SP11">&#167;11</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">equation_text</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP30" class="function-link"><span class="function-syntax">Equations::enode_sr_start</span></a><span class="plain-syntax">(); </span><span class="comment-syntax"> start the shift-reduce parser</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">previous_token</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">enode_count</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="comment-syntax"> number of tokens shipped so far</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">bl</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="comment-syntax"> bracket nesting level</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">), </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">wn</span><span class="plain-syntax"> &lt;= </span><span class="identifier-syntax">Wordings::last_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) || (</span><span class="identifier-syntax">p</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lexer::word_raw_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">++); }</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> we are now at character </span><span class="extract"><span class="extract-syntax">i</span></span><span class="comment-syntax"> in string </span><span class="extract"><span class="extract-syntax">p</span></span><span class="comment-syntax">, while </span><span class="extract"><span class="extract-syntax">wn</span></span><span class="comment-syntax"> is the next word</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">token</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP26_1" class="named-paragraph-link"><span class="named-paragraph">Break off a token from the current position</span><span class="named-paragraph-number">26.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP26_2" class="named-paragraph-link"><span class="named-paragraph">Issue the token to the shift-reduce parser</span><span class="named-paragraph-number">26.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">previous_token</span><span class="plain-syntax"> = </span><span class="identifier-syntax">token</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP32" class="function-link"><span class="function-syntax">Equations::enode_sr_token</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><a href="7-eqt.html#SP23" class="function-link"><span class="function-syntax">Equations::enode_new</span></a><span class="plain-syntax">(</span><span class="constant-syntax">END_EQN</span><span class="plain-syntax">)) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP26_3" class="named-paragraph-link"><span class="named-paragraph">Equation fails in the shift-reduce parser</span><span class="named-paragraph-number">26.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">result</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP31" class="function-link"><span class="function-syntax">Equations::enode_sr_result</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bl</span><span class="plain-syntax"> != </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">BelievedImpossible</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="string-syntax">""</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"this seems to use brackets in a mismatched way, since there "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"are different numbers of left and right brackets '(' and ')'."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">result</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP26_1" class="paragraph-anchor"></a><b>&#167;26.1. </b>Note that symbol names can't begin with a digit.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Break off a token from the current position</span><span class="named-paragraph-number">26.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Characters::isalpha</span><span class="plain-syntax">(</span><span class="identifier-syntax">c</span><span class="plain-syntax">)) </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP26_1_1" class="named-paragraph-link"><span class="named-paragraph">Break off a symbol name as a token</span><span class="named-paragraph-number">26.1.1</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Characters::isdigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">c</span><span class="plain-syntax">)) </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP26_1_2" class="named-paragraph-link"><span class="named-paragraph">Break off a numeric constant as a token</span><span class="named-paragraph-number">26.1.2</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP26_1_3" class="named-paragraph-link"><span class="named-paragraph">Break off an operator or a piece of punctuation as a token</span><span class="named-paragraph-number">26.1.3</span></a></span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP26">&#167;26</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP26_1_1" class="paragraph-anchor"></a><b>&#167;26.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 <span class="extract"><span class="extract-syntax">mc^2</span></span> as <span class="extract"><span class="extract-syntax">m</span></span> followed by <span class="extract"><span class="extract-syntax">c^2</span></span> if we know that <span class="extract"><span class="extract-syntax">m</span></span> and <span class="extract"><span class="extract-syntax">c</span></span> are symbols,
rather than <span class="extract"><span class="extract-syntax">mc</span></span>. (This is one reason why most programming languages don't
allow implicit multiplication.)
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Break off a symbol name as a token</span><span class="named-paragraph-number">26.1.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_symbol</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">j</span><span class="plain-syntax">; </span><span class="comment-syntax"> the length of the symbol name we try to break off</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">j</span><span class="plain-syntax">=0; (</span><span class="identifier-syntax">j</span><span class="plain-syntax">&lt;14) &amp;&amp; (</span><span class="identifier-syntax">Characters::isalnum</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">+</span><span class="identifier-syntax">j</span><span class="plain-syntax">])) &amp;&amp; (</span><span class="identifier-syntax">token</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">); </span><span class="identifier-syntax">j</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_symbol</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">+</span><span class="identifier-syntax">j</span><span class="plain-syntax">]);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">standard_equation_symbols</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP26_1_1_1" class="named-paragraph-link"><span class="named-paragraph">Look for this symbol name</span><span class="named-paragraph-number">26.1.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">token</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">j</span><span class="plain-syntax">=1; (</span><span class="identifier-syntax">j</span><span class="plain-syntax">&lt;15) &amp;&amp; (</span><span class="identifier-syntax">Characters::isalnum</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">+</span><span class="identifier-syntax">j</span><span class="plain-syntax">-1])) &amp;&amp; (</span><span class="identifier-syntax">token</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">); </span><span class="identifier-syntax">j</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> copy the first </span><span class="extract"><span class="extract-syntax">j</span></span><span class="comment-syntax"> characters into a C string:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Str::clear</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_symbol</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">k</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">k</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">j</span><span class="plain-syntax">; </span><span class="identifier-syntax">k</span><span class="plain-syntax">++) </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_symbol</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">+</span><span class="identifier-syntax">k</span><span class="plain-syntax">]);</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> try to identify this as one of the declared symbols:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ev</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">symbol_list</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP26_1_1_1" class="named-paragraph-link"><span class="named-paragraph">Look for this symbol name</span><span class="named-paragraph-number">26.1.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">token</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_problem_S</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationTokenUnrecognised</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">text_of_symbol</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"the symbol '%3' is one that I don't recognise. It doesn't "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"seem to be declared after the equation - for instance, "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"by adding 'where %3 is a number'."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_symbol</span><span class="plain-syntax">)</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP26_1">&#167;26.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP26_1_1_1" class="paragraph-anchor"></a><b>&#167;26.1.1.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Look for this symbol name</span><span class="named-paragraph-number">26.1.1.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::eq_wide_string</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_symbol</span><span class="plain-syntax">, </span><span class="identifier-syntax">Lexer::word_raw_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax">)))) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">token</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP24" class="function-link"><span class="function-syntax">Equations::enode_new_symbol</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">ev</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> += </span><span class="identifier-syntax">j</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP26_1_1">&#167;26.1.1</a> (twice).</li></ul>
<p class="commentary firstcommentary"><a id="SP26_1_2" class="paragraph-anchor"></a><b>&#167;26.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="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Break off a numeric constant as a token</span><span class="named-paragraph-number">26.1.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] == </span><span class="character-syntax">'0'</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">Characters::isdigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">+1]))) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationLeadingZero</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="string-syntax">""</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"a number in an equation isn't allowed to begin with a "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"'0' digit, so an equation like 'M = 007+Q' is against the rules."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_number</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP26_1_2_1" class="named-paragraph-link"><span class="named-paragraph">Copy the literal number into a C string, flanked by spaces</span><span class="named-paragraph-number">26.1.2.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> now sneakily add this to the word stream, and let the S-parser read it:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">NW</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Feeds::feed_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_number</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_number</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">spec</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="function-syntax">&lt;s-type-expression&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">NW</span><span class="plain-syntax">)) </span><span class="identifier-syntax">spec</span><span class="plain-syntax"> = </span><span class="function-syntax">&lt;&lt;rp&gt;&gt;</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">BelievedImpossible</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="string-syntax">""</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"there's a literal number in that equation which doesn't make "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"sense to me."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> this can only go wrong if there was an overflow, and a problem will have been issued for that:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::is</span><span class="plain-syntax">(</span><span class="identifier-syntax">spec</span><span class="plain-syntax">, </span><span class="identifier-syntax">CONSTANT_NT</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">token</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP24" class="function-link"><span class="function-syntax">Equations::enode_new_constant</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">spec</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP26_1">&#167;26.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP26_1_2_1" class="paragraph-anchor"></a><b>&#167;26.1.2.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Copy the literal number into a C string, flanked by spaces</span><span class="named-paragraph-number">26.1.2.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Characters::isdigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">])) </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_number</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++]);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] == </span><span class="character-syntax">'.'</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_number</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++]);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Characters::isdigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">])) </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_number</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++]);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">LiteralReals::ismultiplicationsign</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">])) &amp;&amp; (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">+1] == </span><span class="character-syntax">'1'</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">+2] == </span><span class="character-syntax">'0'</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">+3] == </span><span class="character-syntax">'^'</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_number</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++]);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_number</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++]);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_number</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++]);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_number</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++]);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Characters::isdigit</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">])) </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_number</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">++]);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_of_number</span><span class="plain-syntax">, </span><span class="character-syntax">' '</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP26_1_2">&#167;26.1.2</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP26_1_3" class="paragraph-anchor"></a><b>&#167;26.1.3. </b>Which leaves just the easiest case:
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Break off an operator or a piece of punctuation as a token</span><span class="named-paragraph-number">26.1.3</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'='</span><span class="plain-syntax">: </span><span class="identifier-syntax">token</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP24" class="function-link"><span class="function-syntax">Equations::enode_new_op</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">EQUALS_OPERATION</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'+'</span><span class="plain-syntax">: </span><span class="identifier-syntax">token</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP24" class="function-link"><span class="function-syntax">Equations::enode_new_op</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">PLUS_OPERATION</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'-'</span><span class="plain-syntax">:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">previous_token</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) ||</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">previous_token</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">eqn_type</span><span class="plain-syntax"> == </span><span class="constant-syntax">OPERATION_EQN</span><span class="plain-syntax">) ||</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">previous_token</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">eqn_type</span><span class="plain-syntax"> == </span><span class="constant-syntax">OPEN_BRACKET_EQN</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">token</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP24" class="function-link"><span class="function-syntax">Equations::enode_new_op</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">UNARY_MINUS_OPERATION</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">token</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP24" class="function-link"><span class="function-syntax">Equations::enode_new_op</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">MINUS_OPERATION</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'/'</span><span class="plain-syntax">: </span><span class="identifier-syntax">token</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP24" class="function-link"><span class="function-syntax">Equations::enode_new_op</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">DIVIDE_OPERATION</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'*'</span><span class="plain-syntax">: </span><span class="identifier-syntax">token</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP24" class="function-link"><span class="function-syntax">Equations::enode_new_op</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">TIMES_OPERATION</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'^'</span><span class="plain-syntax">: </span><span class="identifier-syntax">token</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP24" class="function-link"><span class="function-syntax">Equations::enode_new_op</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">POWER_OPERATION</span><span class="plain-syntax">); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'('</span><span class="plain-syntax">: </span><span class="identifier-syntax">token</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP23" class="function-link"><span class="function-syntax">Equations::enode_new</span></a><span class="plain-syntax">(</span><span class="constant-syntax">OPEN_BRACKET_EQN</span><span class="plain-syntax">); </span><span class="identifier-syntax">bl</span><span class="plain-syntax">++; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">')'</span><span class="plain-syntax">: </span><span class="identifier-syntax">token</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP23" class="function-link"><span class="function-syntax">Equations::enode_new</span></a><span class="plain-syntax">(</span><span class="constant-syntax">CLOSE_BRACKET_EQN</span><span class="plain-syntax">); </span><span class="identifier-syntax">bl</span><span class="plain-syntax">--; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">symbol</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">symbol</span><span class="plain-syntax">, (</span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="identifier-syntax">c</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_problem_S</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationOperatorUnrecognised</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">symbol</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"the symbol '%3' is one that I don't recognise. I was "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"expecting an arithmetic sign, '+', '-', '*','/', or '^', "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"or else '=' or a bracket '(' or ')'."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Bad operator '%S'\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">symbol</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">symbol</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">++;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP26_1">&#167;26.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP26_2" class="paragraph-anchor"></a><b>&#167;26.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 <span class="extract"><span class="extract-syntax">m</span></span> and <span class="extract"><span class="extract-syntax">c^2</span></span>
in <span class="extract"><span class="extract-syntax">E=mc^2</span></span>, we issue that as an <span class="extract"><span class="extract-syntax">IMPLICIT_TIMES_OPERATION</span></span> enode in
between; and in <span class="extract"><span class="extract-syntax">log pi</span></span> we issue an <span class="extract"><span class="extract-syntax">IMPLICIT_APPLICATION_OPERATION</span></span>.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Issue the token to the shift-reduce parser</span><span class="named-paragraph-number">26.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP28" class="function-link"><span class="function-syntax">Equations::application_is_implied</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">previous_token</span><span class="plain-syntax">, </span><span class="identifier-syntax">token</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP32" class="function-link"><span class="function-syntax">Equations::enode_sr_token</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><a href="7-eqt.html#SP24" class="function-link"><span class="function-syntax">Equations::enode_new_op</span></a><span class="plain-syntax">(</span><span class="constant-syntax">IMPLICIT_APPLICATION_OPERATION</span><span class="plain-syntax">)) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP26_3" class="named-paragraph-link"><span class="named-paragraph">Equation fails in the shift-reduce parser</span><span class="named-paragraph-number">26.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode_count</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP27" class="function-link"><span class="function-syntax">Equations::multiplication_is_implied</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">previous_token</span><span class="plain-syntax">, </span><span class="identifier-syntax">token</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP32" class="function-link"><span class="function-syntax">Equations::enode_sr_token</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><a href="7-eqt.html#SP24" class="function-link"><span class="function-syntax">Equations::enode_new_op</span></a><span class="plain-syntax">(</span><span class="constant-syntax">IMPLICIT_TIMES_OPERATION</span><span class="plain-syntax">)) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP26_3" class="named-paragraph-link"><span class="named-paragraph">Equation fails in the shift-reduce parser</span><span class="named-paragraph-number">26.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode_count</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP32" class="function-link"><span class="function-syntax">Equations::enode_sr_token</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">token</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP26_3" class="named-paragraph-link"><span class="named-paragraph">Equation fails in the shift-reduce parser</span><span class="named-paragraph-number">26.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">enode_count</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">enode_count</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">MAX_ENODES_IN_EXPRESSION</span><span class="plain-syntax"> - </span><span class="constant-syntax">2</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationTooComplex</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="string-syntax">""</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"this is too long and complex an equation."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP26">&#167;26</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP26_3" class="paragraph-anchor"></a><b>&#167;26.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="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Equation fails in the shift-reduce parser</span><span class="named-paragraph-number">26.3</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationMispunctuated</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="string-syntax">""</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"this seems to be wrongly punctuated, and doesn't make sense as a "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"mathematical formula."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP26">&#167;26</a>, <a href="7-eqt.html#SP26_2">&#167;26.2</a> (three times).</li></ul>
<p class="commentary firstcommentary"><a id="SP27" class="paragraph-anchor"></a><b>&#167;27. </b>Lastly, here is when multiplication is implied:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::multiplication_is_implied</span><button class="popup" onclick="togglePopup('usagePopup17')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup17">Usage of <span class="code-font"><span class="function-syntax">Equations::multiplication_is_implied</span></span>:<br/><a href="7-eqt.html#SP26_2">&#167;26.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">previous_token</span><span class="plain-syntax">, </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">token</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">lt</span><span class="plain-syntax">, </span><span class="identifier-syntax">rt</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">token</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">previous_token</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">lt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">previous_token</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax">; </span><span class="identifier-syntax">rt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">token</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (((</span><span class="identifier-syntax">lt</span><span class="plain-syntax"> == </span><span class="constant-syntax">SYMBOL_EQN</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">lt</span><span class="plain-syntax"> == </span><span class="constant-syntax">CONSTANT_EQN</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">lt</span><span class="plain-syntax"> == </span><span class="constant-syntax">CLOSE_BRACKET_EQN</span><span class="plain-syntax">)) &amp;&amp;</span>
<span class="plain-syntax"> ((</span><span class="identifier-syntax">rt</span><span class="plain-syntax"> == </span><span class="constant-syntax">SYMBOL_EQN</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">rt</span><span class="plain-syntax"> == </span><span class="constant-syntax">CONSTANT_EQN</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">rt</span><span class="plain-syntax"> == </span><span class="constant-syntax">OPEN_BRACKET_EQN</span><span class="plain-syntax">)))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP28" class="paragraph-anchor"></a><b>&#167;28. </b>And when function application is implied:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::application_is_implied</span><button class="popup" onclick="togglePopup('usagePopup18')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup18">Usage of <span class="code-font"><span class="function-syntax">Equations::application_is_implied</span></span>:<br/><a href="7-eqt.html#SP26_2">&#167;26.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">previous_token</span><span class="plain-syntax">, </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">token</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">lt</span><span class="plain-syntax">, </span><span class="identifier-syntax">rt</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">token</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">previous_token</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">lt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">previous_token</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax">; </span><span class="identifier-syntax">rt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">token</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">lt</span><span class="plain-syntax"> == </span><span class="constant-syntax">SYMBOL_EQN</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">previous_token</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">leaf_symbol</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">function_notated</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP29" class="paragraph-anchor"></a><b>&#167;29. 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="commentary">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 <span class="extract"><span class="extract-syntax">MAX_ENODES_IN_EXPRESSION</span></span> plus 2
(allowing for the end markers). So:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">SR_sp</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">SR_stack</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_ENODES_IN_EXPRESSION</span><span class="plain-syntax">+2];</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">emitter_sp</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">emitter_stack</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_ENODES_IN_EXPRESSION</span><span class="plain-syntax">+2];</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::log_sr_stacks</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"SR: "</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">SR_sp</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) { </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">" %d: "</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">); </span><a href="7-eqt.html#SP25" class="function-link"><span class="function-syntax">Equations::log_equation_node</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">SR_stack</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">]); }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"EMITTER: "</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">emitter_sp</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) { </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">" %d: "</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">); </span><a href="7-eqt.html#SP25" class="function-link"><span class="function-syntax">Equations::log_equation_node</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">emitter_stack</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">]); }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP30" class="paragraph-anchor"></a><b>&#167;30. </b>The start and finish are as follows. At the start, the emitter stack is
empty and the SR stack contains an <span class="extract"><span class="extract-syntax">END_EQN</span></span> 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 <span class="extract"><span class="extract-syntax">END_EQN</span></span> tokens in play.)
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::enode_sr_start</span><button class="popup" onclick="togglePopup('usagePopup19')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup19">Usage of <span class="code-font"><span class="function-syntax">Equations::enode_sr_start</span></span>:<br/><a href="7-eqt.html#SP26">&#167;26</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">SR_stack</span><span class="plain-syntax">[0] = </span><a href="7-eqt.html#SP23" class="function-link"><span class="function-syntax">Equations::enode_new</span></a><span class="plain-syntax">(</span><span class="constant-syntax">END_EQN</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">SR_sp</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">emitter_sp</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP31" class="paragraph-anchor"></a><b>&#167;31. </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="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="function-syntax">Equations::enode_sr_result</span><button class="popup" onclick="togglePopup('usagePopup20')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup20">Usage of <span class="code-font"><span class="function-syntax">Equations::enode_sr_result</span></span>:<br/><a href="7-eqt.html#SP26">&#167;26</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">emitter_stack</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP32" class="paragraph-anchor"></a><b>&#167;32. </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="commentary">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 <span class="extract"><span class="extract-syntax">4 + 5</span></span> then we don't know yet whether the <span class="extract"><span class="extract-syntax">+</span></span> will add the 4 to the 5;
if the next token is <span class="extract"><span class="extract-syntax">+</span></span> or <span class="extract"><span class="extract-syntax">END_EQN</span></span> then it will, but if the next token
is <span class="extract"><span class="extract-syntax">*</span></span> then it won't, because we're looking at something like <span class="extract"><span class="extract-syntax">4 + 5 * 6</span></span>.
</p>
<p class="commentary">If the next token is of lower precedence than <span class="extract"><span class="extract-syntax">+</span></span> then we "reduce" &mdash;
telling the emitter about the addition, which we now understand &mdash; but if
it's higher, as with <span class="extract"><span class="extract-syntax">*</span></span>, then we "shift", meaning, we postpone worrying
about the addition and start worrying about the multiplication instead;
our new problem, working out what <span class="extract"><span class="extract-syntax">*</span></span> applies to, sits on top of the
addition problem on the SR-stack.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::enode_sr_token</span><button class="popup" onclick="togglePopup('usagePopup21')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup21">Usage of <span class="code-font"><span class="function-syntax">Equations::enode_sr_token</span></span>:<br/><a href="7-eqt.html#SP26">&#167;26</a>, <a href="7-eqt.html#SP26_2">&#167;26.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">safety_cutout</span><span class="plain-syntax"> = </span><span class="constant-syntax">3</span><span class="plain-syntax">*</span><span class="constant-syntax">MAX_ENODES_IN_EXPRESSION</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">SR_sp</span><span class="plain-syntax"> &lt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"SR stack empty"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">SR_stack</span><span class="plain-syntax">[</span><span class="identifier-syntax">SR_sp</span><span class="plain-syntax">-1]-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax"> == </span><span class="constant-syntax">END_EQN</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax"> == </span><span class="constant-syntax">END_EQN</span><span class="plain-syntax">)) </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><a href="7-eqt.html#SP34" class="function-link"><span class="function-syntax">Equations::enode_lt</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">SR_stack</span><span class="plain-syntax">[</span><span class="identifier-syntax">SR_sp</span><span class="plain-syntax">-1], </span><span class="identifier-syntax">tok</span><span class="plain-syntax">)) || (</span><a href="7-eqt.html#SP34" class="function-link"><span class="function-syntax">Equations::enode_eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">SR_stack</span><span class="plain-syntax">[</span><span class="identifier-syntax">SR_sp</span><span class="plain-syntax">-1], </span><span class="identifier-syntax">tok</span><span class="plain-syntax">)))</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP32_1" class="named-paragraph-link"><span class="named-paragraph">Shift an enode onto the SR-stack</span><span class="named-paragraph-number">32.1</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP34" class="function-link"><span class="function-syntax">Equations::enode_gt</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">SR_stack</span><span class="plain-syntax">[</span><span class="identifier-syntax">SR_sp</span><span class="plain-syntax">-1], </span><span class="identifier-syntax">tok</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP32_2" class="named-paragraph-link"><span class="named-paragraph">Reduce some enodes from the SR-stack to the emitter stack</span><span class="named-paragraph-number">32.2</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">safety_cutout</span><span class="plain-syntax">-- &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"SR parser deadlocked"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">emitter_sp</span><span class="plain-syntax"> != </span><span class="constant-syntax">1</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">SR_sp</span><span class="plain-syntax"> != </span><span class="constant-syntax">1</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP32_1" class="paragraph-anchor"></a><b>&#167;32.1. </b>After shifting, we return a signal of success, which asks for the next
token to be sent.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Shift an enode onto the SR-stack</span><span class="named-paragraph-number">32.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">SR_stack</span><span class="plain-syntax">[</span><span class="identifier-syntax">SR_sp</span><span class="plain-syntax">++] = </span><span class="identifier-syntax">tok</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP32">&#167;32</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP32_2" class="paragraph-anchor"></a><b>&#167;32.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 <span class="extract"><span class="extract-syntax">FALSE</span></span>
on an underflow to be safe.
</p>
<p class="commentary">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="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Reduce some enodes from the SR-stack to the emitter stack</span><span class="named-paragraph-number">32.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">do</span><span class="plain-syntax"> { </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">SR_sp</span><span class="plain-syntax"> &lt;= </span><span class="constant-syntax">1</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP33" class="function-link"><span class="function-syntax">Equations::enode_emit</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">SR_stack</span><span class="plain-syntax">[--</span><span class="identifier-syntax">SR_sp</span><span class="plain-syntax">]) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">SR_sp</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">1</span><span class="plain-syntax">) &amp;&amp; (</span><a href="7-eqt.html#SP34" class="function-link"><span class="function-syntax">Equations::enode_lt</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">SR_stack</span><span class="plain-syntax">[</span><span class="identifier-syntax">SR_sp</span><span class="plain-syntax">-1], </span><span class="identifier-syntax">SR_stack</span><span class="plain-syntax">[</span><span class="identifier-syntax">SR_sp</span><span class="plain-syntax">]) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">));</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP32">&#167;32</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP33" class="paragraph-anchor"></a><b>&#167;33. </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 <span class="extract"><span class="extract-syntax">4 + 2 * 7</span></span> is emitted as <span class="extract"><span class="extract-syntax">4 2 7 * +</span></span>. 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="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::enode_emit</span><button class="popup" onclick="togglePopup('usagePopup22')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup22">Usage of <span class="code-font"><span class="function-syntax">Equations::enode_emit</span></span>:<br/><a href="7-eqt.html#SP32_2">&#167;32.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">SYMBOL_EQN:</span><span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">CONSTANT_EQN:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">emitter_stack</span><span class="plain-syntax">[</span><span class="identifier-syntax">emitter_sp</span><span class="plain-syntax">++] = </span><span class="identifier-syntax">tok</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">OPERATION_EQN:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax"> == </span><span class="constant-syntax">IMPLICIT_TIMES_OPERATION</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TIMES_OPERATION</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax"> == </span><span class="constant-syntax">IMPLICIT_APPLICATION_OPERATION</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Kinds::Dimensions::arithmetic_op_is_unary</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax"> - </span><span class="constant-syntax">1</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">--) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">emitter_sp</span><span class="plain-syntax">--;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">emitter_sp</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="identifier-syntax">emitter_stack</span><span class="plain-syntax">[</span><span class="identifier-syntax">emitter_sp</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">emitter_stack</span><span class="plain-syntax">[</span><span class="identifier-syntax">emitter_sp</span><span class="plain-syntax">++] = </span><span class="identifier-syntax">tok</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP34" class="paragraph-anchor"></a><b>&#167;34. </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 <span class="extract"><span class="extract-syntax">(</span></span>, which affects the stuff to the left very differently from
the stuff to the right. But it is also true of operators. <span class="extract"><span class="extract-syntax">+</span></span> may be
associative mathematically, but in computing there's a difference
between evaluating <span class="extract"><span class="extract-syntax">a + (b+c)</span></span> and <span class="extract"><span class="extract-syntax">(a+b) + c</span></span>.
</p>
<p class="commentary">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="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::enode_lt</span><button class="popup" onclick="togglePopup('usagePopup23')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup23">Usage of <span class="code-font"><span class="function-syntax">Equations::enode_lt</span></span>:<br/><a href="7-eqt.html#SP32">&#167;32</a>, <a href="7-eqt.html#SP32_2">&#167;32.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok1</span><span class="plain-syntax">, </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok2</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">f_left</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP35" class="function-link"><span class="function-syntax">Equations::f_function</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">tok1</span><span class="plain-syntax">), </span><span class="identifier-syntax">g_right</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP36" class="function-link"><span class="function-syntax">Equations::g_function</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">tok2</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">f_left</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">g_right</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::enode_eq</span><button class="popup" onclick="togglePopup('usagePopup24')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup24">Usage of <span class="code-font"><span class="function-syntax">Equations::enode_eq</span></span>:<br/><a href="7-eqt.html#SP32">&#167;32</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok1</span><span class="plain-syntax">, </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok2</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">f_left</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP35" class="function-link"><span class="function-syntax">Equations::f_function</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">tok1</span><span class="plain-syntax">), </span><span class="identifier-syntax">g_right</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP36" class="function-link"><span class="function-syntax">Equations::g_function</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">tok2</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">f_left</span><span class="plain-syntax"> == </span><span class="identifier-syntax">g_right</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::enode_gt</span><button class="popup" onclick="togglePopup('usagePopup25')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup25">Usage of <span class="code-font"><span class="function-syntax">Equations::enode_gt</span></span>:<br/><a href="7-eqt.html#SP32">&#167;32</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok1</span><span class="plain-syntax">, </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok2</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">f_left</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP35" class="function-link"><span class="function-syntax">Equations::f_function</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">tok1</span><span class="plain-syntax">), </span><span class="identifier-syntax">g_right</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP36" class="function-link"><span class="function-syntax">Equations::g_function</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">tok2</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">f_left</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">g_right</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP35" class="paragraph-anchor"></a><b>&#167;35. </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: <span class="extract"><span class="extract-syntax">a^2^3</span></span> evaluates \(a^8\), not
\(a^6\), because it is read as <span class="extract"><span class="extract-syntax">a^(2^3)</span></span>.
</p>
<p class="commentary">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
<span class="extract"><span class="extract-syntax">ab/cd</span></span> evaluates \((ab)/(cd)\) rather than \(a\cdot (b/c)\cdot d\).
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::f_function</span><button class="popup" onclick="togglePopup('usagePopup26')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup26">Usage of <span class="code-font"><span class="function-syntax">Equations::f_function</span></span>:<br/><a href="7-eqt.html#SP34">&#167;34</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">SYMBOL_EQN:</span><span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">CONSTANT_EQN:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">16</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">OPERATION_EQN:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">EQUALS_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">PLUS_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">MINUS_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">4</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">TIMES_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">DIVIDE_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">6</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">IMPLICIT_TIMES_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">8</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">POWER_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">9</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">IMPLICIT_APPLICATION_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">5</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">UNARY_MINUS_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"unknown operator precedence"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">OPEN_BRACKET_EQN:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">CLOSE_BRACKET_EQN:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">16</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">END_EQN:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"unknown f-value"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP36" class="paragraph-anchor"></a><b>&#167;36. </b>And symmetrically:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::g_function</span><button class="popup" onclick="togglePopup('usagePopup27')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup27">Usage of <span class="code-font"><span class="function-syntax">Equations::g_function</span></span>:<br/><a href="7-eqt.html#SP34">&#167;34</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">SYMBOL_EQN:</span><span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">CONSTANT_EQN:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">15</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">OPERATION_EQN:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">) </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">EQUALS_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">PLUS_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">MINUS_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">3</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">TIMES_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">DIVIDE_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">5</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">IMPLICIT_TIMES_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">7</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">POWER_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">10</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">IMPLICIT_APPLICATION_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">14</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">UNARY_MINUS_OPERATION:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">12</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"unknown operator precedence"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">OPEN_BRACKET_EQN:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">15</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">CLOSE_BRACKET_EQN:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">END_EQN:</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"unknown g-value"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP37" class="paragraph-anchor"></a><b>&#167;37. Typechecking equations. </b>The SR parser can generate trees for any syntactically valid equation, but
it may be something using <span class="extract"><span class="extract-syntax">=</span></span> inappropriately or not at all. We rule that
out first: we want the top node in the tree to be the unique <span class="extract"><span class="extract-syntax">=</span></span> operator.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::eqn_typecheck</span><button class="popup" onclick="togglePopup('usagePopup28')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup28">Usage of <span class="code-font"><span class="function-syntax">Equations::eqn_typecheck</span></span>:<br/><a href="7-eqt.html#SP11">&#167;11</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP38" class="function-link"><span class="function-syntax">Equations::enode_count_equals</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationDoesntEquate</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="string-syntax">""</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"this equation doesn't seem to contain an equals sign, and "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"without '=' there is no equating anything with anything."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax">:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP38" class="function-link"><span class="function-syntax">Equations::enode_is_equals</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationEquatesBadly</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="string-syntax">""</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"the equals sign '=' here seems to be buried inside the "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"formula, not at the surface. For instance, 'F = ma' is "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"fine, but 'F(m=a)' would not make sense - the '=' would "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"be inside brackets."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationEquatesMultiply</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="string-syntax">""</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"this equation seems to contain more than one equals "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"sign '='."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="7-eqt.html#SP39" class="function-link"><span class="function-syntax">Equations::enode_typecheck</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP38" class="paragraph-anchor"></a><b>&#167;38. </b>A recursive count of instances down the tree from <span class="extract"><span class="extract-syntax">tok</span></span>:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::enode_count_equals</span><button class="popup" onclick="togglePopup('usagePopup29')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup29">Usage of <span class="code-font"><span class="function-syntax">Equations::enode_count_equals</span></span>:<br/><a href="7-eqt.html#SP37">&#167;37</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP38" class="function-link"><span class="function-syntax">Equations::enode_is_equals</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">)) </span><span class="identifier-syntax">c</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="function-syntax">&lt;tok-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> += </span><a href="7-eqt.html#SP38" class="function-link"><span class="function-syntax">Equations::enode_count_equals</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">]);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::enode_is_equals</span><button class="popup" onclick="togglePopup('usagePopup30')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup30">Usage of <span class="code-font"><span class="function-syntax">Equations::enode_is_equals</span></span>:<br/><a href="7-eqt.html#SP37">&#167;37</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax"> == </span><span class="constant-syntax">OPERATION_EQN</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax"> == </span><span class="identifier-syntax">EQUALS_OPERATION</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP39" class="paragraph-anchor"></a><b>&#167;39. </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 <span class="extract"><span class="extract-syntax">FALSE</span></span> if we
are obliged to issue a problem message.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">float_terminal_nodes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::enode_typecheck</span><button class="popup" onclick="togglePopup('usagePopup31')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup31">Usage of <span class="code-font"><span class="function-syntax">Equations::enode_typecheck</span></span>:<br/><a href="7-eqt.html#SP37">&#167;37</a>, <a href="7-eqt.html#SP40">&#167;40</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">result</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">result</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG_INDENT</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="function-syntax">&lt;tok-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP39" class="function-link"><span class="function-syntax">Equations::enode_typecheck</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">]) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">result</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">result</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">SYMBOL_EQN:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::new_gk</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">leaf_symbol</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">var_kind</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">CONSTANT_EQN:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::new_gk</span><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Node::get_kind_of_value</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">leaf_constant</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_promotion</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">CompileValues::target_VM_supports_kind</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_real_number</span><span class="plain-syntax">)))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::to_real</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">OPERATION_EQN:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax"> == </span><span class="identifier-syntax">EQUALS_OPERATION</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP39_1" class="named-paragraph-link"><span class="named-paragraph">Typecheck the set-equals node at the top level</span><span class="named-paragraph-number">39.1</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax"> == </span><span class="identifier-syntax">POWER_OPERATION</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP39_2" class="named-paragraph-link"><span class="named-paragraph">Typecheck a raise-to-integer-power node</span><span class="named-paragraph-number">39.2</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax"> == </span><span class="constant-syntax">IMPLICIT_APPLICATION_OPERATION</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP39_3" class="named-paragraph-link"><span class="named-paragraph">Typecheck a function application node</span><span class="named-paragraph-number">39.3</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP39_4" class="named-paragraph-link"><span class="named-paragraph">Typecheck a general operation node</span><span class="named-paragraph-number">39.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"forbidden enode found in parsed equation"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax"> = </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">float_terminal_nodes</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP40" class="function-link"><span class="function-syntax">Equations::promote_subequation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">tok</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG_OUTDENT</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">result</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP39_1" class="paragraph-anchor"></a><b>&#167;39.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="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Typecheck the set-equals node at the top level</span><span class="named-paragraph-number">39.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">L</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::underlying</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">R</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::underlying</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">L</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::integer_equivalent</span><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">R</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::integer_equivalent</span><span class="plain-syntax">(</span><span class="identifier-syntax">R</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Kinds::eq</span><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="plain-syntax">, </span><span class="identifier-syntax">R</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">result</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Tried to equate %u and %u\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="plain-syntax">, </span><span class="identifier-syntax">R</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationIncomparable</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="string-syntax">""</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"this equation tries to set two values equal which have "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"different kinds from each other."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">lf</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::is_real</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">rf</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::is_real</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">lf</span><span class="plain-syntax"> == </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">rf</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP40" class="function-link"><span class="function-syntax">Equations::promote_subequation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1], </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">lf</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">rf</span><span class="plain-syntax"> == </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP40" class="function-link"><span class="function-syntax">Equations::demote_subequation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax"> = </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP39">&#167;39</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP39_2" class="paragraph-anchor"></a><b>&#167;39.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="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Typecheck a raise-to-integer-power node</span><span class="named-paragraph-number">39.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">base</span><span class="plain-syntax"> = </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">power</span><span class="plain-syntax"> = </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Kinds::Dimensions::dimensionless</span><span class="plain-syntax">(</span><span class="identifier-syntax">Kinds::FloatingPoint::underlying</span><span class="plain-syntax">(</span><span class="identifier-syntax">base</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">))) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax"> = </span><span class="identifier-syntax">base</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax"> = </span><span class="identifier-syntax">base</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP39_2_1" class="named-paragraph-link"><span class="named-paragraph">Take the dimensional power of the kind of the base</span><span class="named-paragraph-number">39.2.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">lf</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::is_real</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">rf</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::is_real</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">lf</span><span class="plain-syntax"> == </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">rf</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP40" class="function-link"><span class="function-syntax">Equations::promote_subequation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1], </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">lf</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">rf</span><span class="plain-syntax"> == </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP40" class="function-link"><span class="function-syntax">Equations::promote_subequation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0], </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">Kinds::FloatingPoint::is_real</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) &amp;&amp; ((</span><span class="identifier-syntax">lf</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">rf</span><span class="plain-syntax">))) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::to_real</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP39">&#167;39</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP39_3" class="paragraph-anchor"></a><b>&#167;39.3. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Typecheck a function application node</span><span class="named-paragraph-number">39.3</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">fn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">fn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax"> == </span><span class="constant-syntax">SYMBOL_EQN</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">fn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">leaf_symbol</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">function_notated</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">id_body</span><span class="plain-syntax"> *</span><span class="identifier-syntax">idb</span><span class="plain-syntax"> = </span><span class="identifier-syntax">fn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">leaf_symbol</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">function_notated</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">RK</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="5-ptd.html#SP24" class="function-link"><span class="function-syntax">IDTypeData::arithmetic_operation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">idb</span><span class="plain-syntax">) == </span><span class="identifier-syntax">REALROOT_OPERATION</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">OPK</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::underlying</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">RK</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain-syntax">(</span><span class="identifier-syntax">OPK</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">REALROOT_OPERATION</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">RK</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationCantRoot</span><span class="plain-syntax">-</span><span class="identifier-syntax">G</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="string-syntax">""</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"the square root function 'root' can only be used on quantities "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"whose dimensions are themselves a square - for example, the "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"root of the area 100 sq m makes sense (it's 10m), but the root "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"of 4m doesn't make sense, because what's a square root of a meter?"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">RK</span><span class="plain-syntax"> = </span><a href="5-ptd.html#SP10" class="function-link"><span class="function-syntax">IDTypeData::get_return_kind</span></a><span class="plain-syntax">(&amp;(</span><span class="identifier-syntax">idb</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">type_data</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::to_real</span><span class="plain-syntax">(</span><span class="identifier-syntax">Kinds::FloatingPoint::new_gk</span><span class="plain-syntax">(</span><span class="identifier-syntax">RK</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">rf</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::is_real</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">rf</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) </span><a href="7-eqt.html#SP40" class="function-link"><span class="function-syntax">Equations::promote_subequation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1], </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP39">&#167;39</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP39_2_1" class="paragraph-anchor"></a><b>&#167;39.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="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Take the dimensional power of the kind of the base</span><span class="named-paragraph-number">39.2.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">F</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::integer_equivalent</span><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::underlying</span><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">base</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">real</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Kinds::FloatingPoint::is_real</span><span class="plain-syntax">(</span><span class="identifier-syntax">base</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">)) </span><span class="identifier-syntax">real</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">n</span><span class="plain-syntax"> = -1, </span><span class="identifier-syntax">m</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">power</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">rational_m</span><span class="plain-syntax"> != </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">n</span><span class="plain-syntax"> = </span><span class="identifier-syntax">power</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">rational_n</span><span class="plain-syntax">; </span><span class="identifier-syntax">m</span><span class="plain-syntax"> = </span><span class="identifier-syntax">power</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">rational_m</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">m</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">1</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">real</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">result</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationCantPower2</span><span class="plain-syntax">-</span><span class="identifier-syntax">G</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="string-syntax">""</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"except for the special cases of squaring and cubing, the '^' "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"raise-to-power symbol can only be used to power a value using "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"real rather than integer arithmetic."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">Kinds::eq</span><span class="plain-syntax">(</span><span class="identifier-syntax">Kinds::FloatingPoint::underlying</span><span class="plain-syntax">(</span><span class="identifier-syntax">power</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">), </span><span class="identifier-syntax">K_number</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) ||</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">power</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax"> != </span><span class="constant-syntax">CONSTANT_EQN</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">result</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationDimensionPower</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="string-syntax">""</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"the '^' raise-to-power symbol can only be used to raise a value "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"with dimensions to a specific number. So 'mv^2' is fine, but not "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"'mv^n' or 'mv^(1+n)'. (This is because I would need to work out what "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"kind of value 'v^n' would be, and the answer would depend on 'n', "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"but I wouldn't know what 'n' is.)"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">n</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Rvalues::to_int</span><span class="plain-syntax">(</span><span class="identifier-syntax">power</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">leaf_constant</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">n</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">1</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::Dimensions::to_rational_power</span><span class="plain-syntax">(</span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="identifier-syntax">n</span><span class="plain-syntax">, </span><span class="identifier-syntax">m</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">K</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::equation_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">BelievedImpossible</span><span class="plain-syntax">), </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="string-syntax">""</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"this would involve taking a fractional power of an amount whose "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"dimensions are not of that power form - for example, the square "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"root of the area 100 sq m makes sense (it's 10m), but the square "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"root of 4m doesn't make sense, because what's a square root of "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"a meter?"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">real</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::to_real</span><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::new_gk</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::new_gk</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP39_2">&#167;39.2</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP39_4" class="paragraph-anchor"></a><b>&#167;39.4. </b>The following is easy because it was the content of the whole "Dimensions.w"
section:
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Typecheck a general operation node</span><span class="named-paragraph-number">39.4</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">O1</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::integer_equivalent</span><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::underlying</span><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">real</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Kinds::FloatingPoint::is_real</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">real</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Kinds::Dimensions::arithmetic_op_is_unary</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain-syntax">(</span><span class="identifier-syntax">O1</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">O2</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::integer_equivalent</span><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::underlying</span><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Kinds::FloatingPoint::is_real</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">real</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">K</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain-syntax">(</span><span class="identifier-syntax">O1</span><span class="plain-syntax">, </span><span class="identifier-syntax">O2</span><span class="plain-syntax">, </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">lf</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::is_real</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">rf</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::is_real</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">lf</span><span class="plain-syntax"> == </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">rf</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP40" class="function-link"><span class="function-syntax">Equations::promote_subequation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1], </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">lf</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">rf</span><span class="plain-syntax"> == </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP40" class="function-link"><span class="function-syntax">Equations::promote_subequation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0], </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">K</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">result</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::new_gk</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_value</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Failed at operation:\n"</span><span class="plain-syntax">); </span><a href="7-eqt.html#SP25" class="function-link"><span class="function-syntax">Equations::log_equation_node</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Kinds::Dimensions::arithmetic_op_is_unary</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP39_4_1" class="named-paragraph-link"><span class="named-paragraph">Issue unary equation typechecking problem message</span><span class="named-paragraph-number">39.4.1</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP39_4_2" class="named-paragraph-link"><span class="named-paragraph">Issue binary equation typechecking problem message</span><span class="named-paragraph-number">39.4.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">real</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::to_real</span><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::new_gk</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::new_gk</span><span class="plain-syntax">(</span><span class="identifier-syntax">K</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP39">&#167;39</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP39_4_1" class="paragraph-anchor"></a><b>&#167;39.4.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Issue unary equation typechecking problem message</span><span class="named-paragraph-number">39.4.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_source</span><span class="plain-syntax">(1, </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_kind</span><span class="plain-syntax">(4,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::underlying</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">UNARY_MINUS_OPERATION:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(6, </span><span class="string-syntax">"negating"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">ROOT_OPERATION:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(6, </span><span class="string-syntax">"taking the square root of"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">REALROOT_OPERATION:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(6, </span><span class="string-syntax">"taking the (real-valued) square root of"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">CUBEROOT_OPERATION:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(6, </span><span class="string-syntax">"taking the cube root of"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::handmade_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(), </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">BelievedImpossible</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::issue_problem_segment</span><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="string-syntax">"You wrote %1, but that equation seems to involve %6 %4, which is not "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"good arithmetic."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::issue_problem_end</span><span class="plain-syntax">();</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP39_4">&#167;39.4</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP39_4_2" class="paragraph-anchor"></a><b>&#167;39.4.2. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Issue binary equation typechecking problem message</span><span class="named-paragraph-number">39.4.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_source</span><span class="plain-syntax">(1, </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_kind</span><span class="plain-syntax">(4, </span><span class="identifier-syntax">Kinds::FloatingPoint::underlying</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_kind</span><span class="plain-syntax">(5, </span><span class="identifier-syntax">Kinds::FloatingPoint::underlying</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">PLUS_OPERATION:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(6, </span><span class="string-syntax">"adding"</span><span class="plain-syntax">); </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(7, </span><span class="string-syntax">"to"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">MINUS_OPERATION:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(6, </span><span class="string-syntax">"subtracting"</span><span class="plain-syntax">); </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(7, </span><span class="string-syntax">"from"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">TIMES_OPERATION:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(6, </span><span class="string-syntax">"multiplying"</span><span class="plain-syntax">); </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(7, </span><span class="string-syntax">"by"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">DIVIDE_OPERATION:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">REMAINDER_OPERATION:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(6, </span><span class="string-syntax">"dividing"</span><span class="plain-syntax">); </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(7, </span><span class="string-syntax">"by"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">POWER_OPERATION:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(6, </span><span class="string-syntax">"raising"</span><span class="plain-syntax">); </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(7, </span><span class="string-syntax">"to the power of"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(6, </span><span class="string-syntax">"combining"</span><span class="plain-syntax">); </span><span class="identifier-syntax">Problems::quote_text</span><span class="plain-syntax">(7, </span><span class="string-syntax">"with"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::handmade_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(), </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_EquationBadArithmetic</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::issue_problem_segment</span><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="string-syntax">"You wrote %1, but that equation seems to involve "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"%6 %4 %7 %5, which is not good arithmetic."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Problems::issue_problem_end</span><span class="plain-syntax">();</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP39_4">&#167;39.4</a>.</li></ul>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::promote_subequation</span><button class="popup" onclick="togglePopup('usagePopup32')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup32">Usage of <span class="code-font"><span class="function-syntax">Equations::promote_subequation</span></span>:<br/><a href="7-eqt.html#SP39">&#167;39</a>, <a href="7-eqt.html#SP39_1">&#167;39.1</a>, <a href="7-eqt.html#SP39_2">&#167;39.2</a>, <a href="7-eqt.html#SP39_3">&#167;39.3</a>, <a href="7-eqt.html#SP39_4">&#167;39.4</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">deeply</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">deeply</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">float_terminal_nodes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP39" class="function-link"><span class="function-syntax">Equations::enode_typecheck</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">tok</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">float_terminal_nodes</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::to_real</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::demote_subequation</span><button class="popup" onclick="togglePopup('usagePopup33')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup33">Usage of <span class="code-font"><span class="function-syntax">Equations::demote_subequation</span></span>:<br/><a href="7-eqt.html#SP39_1">&#167;39.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Kinds::FloatingPoint::to_integer</span><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP41" class="paragraph-anchor"></a><b>&#167;41. 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 <span class="extract"><span class="extract-syntax">FALSE</span></span>.
</p>
<p class="commentary">Everything we do will be reversible, which is important since we are
changing the <span class="extract"><span class="extract-syntax">parsed_equation</span></span> 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="commentary">Suppose we are solving for <span class="extract"><span class="extract-syntax">v</span></span>, which occurs in just one place in the equation.
Either it's at the top level under the <span class="extract"><span class="extract-syntax">=</span></span>, in which case we now have an
explicit formula for <span class="extract"><span class="extract-syntax">v</span></span>, or it's stuck underneath some operation node. We
rearrange the tree to move this operation over to the other side, which
allows <span class="extract"><span class="extract-syntax">v</span></span> to make progress &mdash; see below for a proof that this terminates.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::eqn_rearrange</span><button class="popup" onclick="togglePopup('usagePopup34')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup34">Usage of <span class="code-font"><span class="function-syntax">Equations::eqn_rearrange</span></span>:<br/><a href="7-eqt.html#SP43">&#167;43</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">to_solve</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP41_1" class="named-paragraph-link"><span class="named-paragraph">Swap the two sides if necessary so that v occurs only once and on the left</span><span class="named-paragraph-number">41.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax"> = </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">old_RHS</span><span class="plain-syntax"> = </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax"> != </span><span class="constant-syntax">OPERATION_EQN</span><span class="plain-syntax">) </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax"> == </span><span class="constant-syntax">2</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP41_3" class="named-paragraph-link"><span class="named-paragraph">Rearrange to move v upwards through this binary operator</span><span class="named-paragraph-number">41.3</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP41_4" class="named-paragraph-link"><span class="named-paragraph">Rearrange to move v upwards through this unary operator</span><span class="named-paragraph-number">41.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP41_1" class="paragraph-anchor"></a><b>&#167;41.1. </b>We have no ability to gather terms, so the variable <span class="extract"><span class="extract-syntax">v</span></span> we are solving for can only
occur once in the formula. In Inform's idea of equations, <span class="extract"><span class="extract-syntax">A = B</span></span> and <span class="extract"><span class="extract-syntax">B = A</span></span>
have the same meaning, so we'll place <span class="extract"><span class="extract-syntax">v</span></span> on the left.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Swap the two sides if necessary so that v occurs only once and on the left</span><span class="named-paragraph-number">41.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">lc</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP42" class="function-link"><span class="function-syntax">Equations::enode_count_var</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0], </span><span class="identifier-syntax">to_solve</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">rc</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP42" class="function-link"><span class="function-syntax">Equations::enode_count_var</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1], </span><span class="identifier-syntax">to_solve</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">lc</span><span class="plain-syntax"> + </span><span class="identifier-syntax">rc</span><span class="plain-syntax"> != </span><span class="constant-syntax">1</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">lc</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">swap</span><span class="plain-syntax"> = </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1];</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">swap</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP41">&#167;41</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP41_2" class="paragraph-anchor"></a><b>&#167;41.2. </b>The main loop above terminates because on each iteration, either
</p>
<ul class="items"><li>(i) the tree depth of <span class="extract"><span class="extract-syntax">v</span></span> below <span class="extract"><span class="extract-syntax">=</span></span> decreases by 1, or
</li><li>(ii) the tree depth of <span class="extract"><span class="extract-syntax">v</span></span> remains the same but the number of <span class="extract"><span class="extract-syntax">MINUS_OPERATION</span></span> or
<span class="extract"><span class="extract-syntax">DIVIDE_OPERATION</span></span> nodes in the tree decreases by 1.
</li></ul>
<p class="commentary">Since at any given time there are a finite number of <span class="extract"><span class="extract-syntax">MINUS_OPERATION</span></span> or
<span class="extract"><span class="extract-syntax">DIVIDE_OPERATION</span></span> 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 <span class="extract"><span class="extract-syntax">v</span></span> 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="commentary firstcommentary"><a id="SP41_3" class="paragraph-anchor"></a><b>&#167;41.3. </b>So the rearrangement moves have to make sure the "(i) or (ii)" property
always holds. The simplest case to understand is <span class="extract"><span class="extract-syntax">+</span></span>. Suppose we have:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> =</span>
<span class="plain-syntax"> +</span>
<span class="plain-syntax"> V</span>
<span class="plain-syntax"> E</span>
<span class="plain-syntax"> R</span>
</pre>
<p class="commentary">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 <span class="extract"><span class="extract-syntax">+</span></span> 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="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> =</span>
<span class="plain-syntax"> V</span>
<span class="plain-syntax"> -</span>
<span class="plain-syntax"> R</span>
<span class="plain-syntax"> E</span>
</pre>
<p class="commentary">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="commentary">But now consider <span class="extract"><span class="extract-syntax">-</span></span>. When we rearrange:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> =</span>
<span class="plain-syntax"> -</span>
<span class="plain-syntax"> E</span>
<span class="plain-syntax"> V</span>
<span class="plain-syntax"> R</span>
</pre>
<p class="commentary">representing \((E-V) = R\) we no longer have a choice of which operand of <span class="extract"><span class="extract-syntax">-</span></span>
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="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Rearrange to move v upwards through this binary operator</span><span class="named-paragraph-number">41.3</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="comment-syntax"> rearrange to move this operator</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">op</span><span class="plain-syntax"> = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">op</span><span class="plain-syntax"> == </span><span class="identifier-syntax">POWER_OPERATION</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP41_3_1" class="named-paragraph-link"><span class="named-paragraph">Rearrange to remove a power</span><span class="named-paragraph-number">41.3.1</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">op</span><span class="plain-syntax"> == </span><span class="constant-syntax">IMPLICIT_APPLICATION_OPERATION</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="7-eqt.html#SP41_3_2" class="named-paragraph-link"><span class="named-paragraph">Rearrange using the inverse of function</span><span class="named-paragraph-number">41.3.2</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">promote</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">new_op</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PLUS_OPERATION</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP42" class="function-link"><span class="function-syntax">Equations::enode_count_var</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1], </span><span class="identifier-syntax">to_solve</span><span class="plain-syntax">) &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">promote</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">op</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">PLUS_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">new_op</span><span class="plain-syntax"> = </span><span class="identifier-syntax">MINUS_OPERATION</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">MINUS_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">new_op</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PLUS_OPERATION</span><span class="plain-syntax">; </span><span class="identifier-syntax">promote</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">TIMES_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">new_op</span><span class="plain-syntax"> = </span><span class="identifier-syntax">DIVIDE_OPERATION</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">DIVIDE_OPERATION:</span><span class="plain-syntax"> </span><span class="identifier-syntax">new_op</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TIMES_OPERATION</span><span class="plain-syntax">; </span><span class="identifier-syntax">promote</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"%d\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">op</span><span class="plain-syntax">); </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"strange operator in rearrangement"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">E</span><span class="plain-syntax"> = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1 - </span><span class="identifier-syntax">promote</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> the new LHS is the promoted operand:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[</span><span class="identifier-syntax">promote</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> the new RHS is the operator which used to be the LHS...</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> ...the former RHS being the operand replacing the promoted one...</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_RHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">E</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> ...except that the operator reverses in "sense"</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">new_op</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP41">&#167;41</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP41_3_1" class="paragraph-anchor"></a><b>&#167;41.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 <span class="extract"><span class="extract-syntax">FALSE</span></span>.
</p>
<p class="commentary">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="commentary">Anyway, rearrangement for our easy cases is indeed easy:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> =</span>
<span class="plain-syntax"> ^</span>
<span class="plain-syntax"> V</span>
<span class="plain-syntax"> 2</span>
<span class="plain-syntax"> R</span>
</pre>
<p class="commentary">becomes
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> =</span>
<span class="plain-syntax"> V</span>
<span class="plain-syntax"> square-root</span>
<span class="plain-syntax"> R</span>
</pre>
<p class="commentary">and \(V\) is always promoted, so we achieve property (i); and similarly for
cube roots.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Rearrange to remove a power</span><span class="named-paragraph-number">41.3.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Rvalues::to_int</span><span class="plain-syntax">(</span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">leaf_constant</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax"> == </span><span class="constant-syntax">2</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ROOT_OPERATION</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_RHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax"> == </span><span class="constant-syntax">3</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CUBEROOT_OPERATION</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_RHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">POWER_OPERATION</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_RHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">the_power</span><span class="plain-syntax"> = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1];</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><a href="7-eqt.html#SP24" class="function-link"><span class="function-syntax">Equations::enode_new_op</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">DIVIDE_OPERATION</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><a href="7-eqt.html#SP24" class="function-link"><span class="function-syntax">Equations::enode_new_constant</span></a><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Rvalues::from_int</span><span class="plain-syntax">(1, </span><span class="identifier-syntax">EMPTY_WORDING</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0]-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::new_gk</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_number</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0]-&gt;</span><span class="element-syntax">enode_promotion</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">the_power</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::new_gk</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_number</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">enode_promotion</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">gK_before</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::new_gk</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_real_number</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">gK_after</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::FloatingPoint::new_gk</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_real_number</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">rational_n</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">rational_m</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CompileValues::note_that_kind_is_used</span><span class="plain-syntax">(</span><span class="identifier-syntax">K_real_number</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP41_3">&#167;41.3</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP41_3_2" class="paragraph-anchor"></a><b>&#167;41.3.2. </b>Here we have something like <span class="extract"><span class="extract-syntax">log x = y</span></span> and want to rewrite as <span class="extract"><span class="extract-syntax">x = exp y</span></span>,
which is only possible if we have an inverse available for our function &mdash;
in this case, <span class="extract"><span class="extract-syntax">exp</span></span> being the inverse of <span class="extract"><span class="extract-syntax">log</span></span>. Thus:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> =</span>
<span class="plain-syntax"> apply</span>
<span class="plain-syntax"> function</span>
<span class="plain-syntax"> V</span>
<span class="plain-syntax"> R</span>
</pre>
<p class="commentary">must become
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> =</span>
<span class="plain-syntax"> V</span>
<span class="plain-syntax"> apply</span>
<span class="plain-syntax"> inverse-of-function</span>
<span class="plain-syntax"> R</span>
</pre>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Rearrange using the inverse of function</span><span class="named-paragraph-number">41.3.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">fnode</span><span class="plain-syntax"> = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">fnode</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">leaf_symbol</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) ||</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">fnode</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">leaf_symbol</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">function_notated</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP25" class="function-link"><span class="function-syntax">Equations::log_equation_node</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">fnode</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"not a function being applied"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">id_body</span><span class="plain-syntax"> *</span><span class="identifier-syntax">f</span><span class="plain-syntax"> = </span><span class="identifier-syntax">fnode</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">leaf_symbol</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">function_notated</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">id_body</span><span class="plain-syntax"> *</span><span class="identifier-syntax">finv</span><span class="plain-syntax"> = </span><a href="5-tpf.html#SP11" class="function-link"><span class="function-syntax">ToPhraseFamily::inverse</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">f</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">head_of_defn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">finv</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">; </span><span class="comment-syntax"> no known inverse for this function</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ev</span><span class="plain-syntax">, *</span><span class="identifier-syntax">ev_inverse</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">standard_equation_symbols</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">function_notated</span><span class="plain-syntax"> == </span><span class="identifier-syntax">finv</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ev_inverse</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ev</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ev_inverse</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">; </span><span class="comment-syntax"> inverse can't be used in equations</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">fnode</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">leaf_symbol</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ev_inverse</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1];</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">old_RHS</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP41_3">&#167;41.3</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP41_4" class="paragraph-anchor"></a><b>&#167;41.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 <span class="extract"><span class="extract-syntax">v</span></span> again rises.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Rearrange to move v upwards through this unary operator</span><span class="named-paragraph-number">41.4</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">op</span><span class="plain-syntax"> = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">op</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">UNARY_MINUS_OPERATION:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_RHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">ROOT_OPERATION:</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">REALROOT_OPERATION:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TIMES_OPERATION</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_RHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">old_RHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">CUBEROOT_OPERATION:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_operation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TIMES_OPERATION</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_RHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><a href="7-eqt.html#SP24" class="function-link"><span class="function-syntax">Equations::enode_new_op</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">TIMES_OPERATION</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">old_RHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">old_LHS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1]-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">old_RHS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"unanticipated operator in rearrangement"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="7-eqt.html#SP41">&#167;41</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP42" class="paragraph-anchor"></a><b>&#167;42. </b>And that's the whole rearranger, except for the utility routine which
counts instances of the magic variable <span class="extract"><span class="extract-syntax">v</span></span> at or below a given point in the
equation tree.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::enode_count_var</span><button class="popup" onclick="togglePopup('usagePopup35')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup35">Usage of <span class="code-font"><span class="function-syntax">Equations::enode_count_var</span></span>:<br/><a href="7-eqt.html#SP41_1">&#167;41.1</a>, <a href="7-eqt.html#SP41_3">&#167;41.3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tok</span><span class="plain-syntax">, </span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">to_solve</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">tok</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">eqn_type</span><span class="plain-syntax"> == </span><span class="constant-syntax">SYMBOL_EQN</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">leaf_symbol</span><span class="plain-syntax"> == </span><span class="identifier-syntax">to_solve</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="function-syntax">&lt;tok-&gt;</span><span class="element-syntax">enode_arity</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> += </span><a href="7-eqt.html#SP42" class="function-link"><span class="function-syntax">Equations::enode_count_var</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">tok</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">enode_operands</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">to_solve</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP43" class="paragraph-anchor"></a><b>&#167;43. 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="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::perform_equation_internal_test</span><button class="popup" onclick="togglePopup('usagePopup36')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup36">Usage of <span class="code-font"><span class="function-syntax">Equations::perform_equation_internal_test</span></span>:<br/>Assertions Module - <a href="1-am.html#SP2">&#167;2</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal_test_case</span><span class="plain-syntax"> *</span><span class="identifier-syntax">itc</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">E</span><span class="plain-syntax"> = </span><span class="identifier-syntax">itc</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">text_supplying_the_case</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">WH</span><span class="plain-syntax"> = </span><span class="identifier-syntax">EMPTY_WORDING</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="function-syntax">&lt;equation-where&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">E</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">E</span><span class="plain-syntax"> = </span><span class="identifier-syntax">GET_RW</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;equation-where&gt;</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WH</span><span class="plain-syntax"> = </span><span class="identifier-syntax">GET_RW</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;equation-where&gt;</span><span class="plain-syntax">, </span><span class="constant-syntax">2</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax"> = </span><a href="7-eqt.html#SP8_1" class="function-link"><span class="function-syntax">Equations::new</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">E</span><span class="plain-syntax">, </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP9" class="function-link"><span class="function-syntax">Equations::set_wherewithal</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">WH</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP11" class="function-link"><span class="function-syntax">Equations::examine</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP44" class="function-link"><span class="function-syntax">Equations::log_equation_parsed</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">equation_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ev</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">symbol_list</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax">; </span><span class="identifier-syntax">ev</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="7-eqt.html#SP41" class="function-link"><span class="function-syntax">Equations::eqn_rearrange</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">, </span><span class="identifier-syntax">ev</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Too hard to rearrange to solve for %W\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Rearranged to solve for %W:\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">ev</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="7-eqt.html#SP44" class="function-link"><span class="function-syntax">Equations::log_equation_parsed</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP44" class="paragraph-anchor"></a><b>&#167;44. Logging. </b>And finally:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::log</span><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"{%W}"</span><span class="plain-syntax">, </span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">equation_text</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Equations::log_equation_parsed</span><button class="popup" onclick="togglePopup('usagePopup37')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup37">Usage of <span class="code-font"><span class="function-syntax">Equations::log_equation_parsed</span></span>:<br/><a href="7-eqt.html#SP43">&#167;43</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">equation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">eqn</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;null&gt;\n"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><a href="7-eqt.html#SP25" class="function-link"><span class="function-syntax">Equations::log_equation_node</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">eqn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_equation</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="7-tbl.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-am.html">1</a></li><li class="progresschapter"><a href="2-bv.html">2</a></li><li class="progresschapter"><a href="3-dlr.html">3</a></li><li class="progresschapter"><a href="4-nr.html">4</a></li><li class="progresschapter"><a href="5-id.html">5</a></li><li class="progresschapter"><a href="6-rls.html">6</a></li><li class="progresscurrentchapter">7</li><li class="progresssection"><a href="7-tc.html">tc</a></li><li class="progresssection"><a href="7-tbl.html">tbl</a></li><li class="progresscurrent">eqt</li><li class="progresschapter"><a href="8-kpr.html">8</a></li><li class="progressnext"><a href="8-kpr.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>