1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-03 07:24:58 +03:00
inform7/docs/syntax-module/2-tv.html

280 lines
42 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Tree Verification</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>
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">
</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="../compiler.html">compiler tools</a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul><h2>Compiler Webs</h2><ul>
<li><a href="../inbuild/index.html">inbuild</a></li>
<li><a href="../inform7/index.html">inform7</a></li>
<li><a href="../inter/index.html">inter</a></li>
</ul><h2>Inbuild Modules</h2><ul>
<li><a href="../supervisor-module/index.html">supervisor</a></li>
</ul><h2>Inform7 Modules</h2><ul>
<li><a href="../core-module/index.html">core</a></li>
<li><a href="../assertions-module/index.html">assertions</a></li>
<li><a href="../values-module/index.html">values</a></li>
<li><a href="../knowledge-module/index.html">knowledge</a></li>
<li><a href="../imperative-module/index.html">imperative</a></li>
<li><a href="../runtime-module/index.html">runtime</a></li>
<li><a href="../if-module/index.html">if</a></li>
<li><a href="../multimedia-module/index.html">multimedia</a></li>
<li><a href="../index-module/index.html">index</a></li>
</ul><h2>Inter Modules</h2><ul>
<li><a href="../bytecode-module/index.html">bytecode</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../pipeline-module/index.html">pipeline</a></li>
<li><a href="../final-module/index.html">final</a></li>
</ul><h2>Services</h2><ul>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../calculus-module/index.html">calculus</a></li>
<li><a href="../html-module/index.html">html</a></li>
<li><a href="../inflections-module/index.html">inflections</a></li>
<li><a href="../kinds-module/index.html">kinds</a></li>
<li><a href="../linguistics-module/index.html">linguistics</a></li>
<li><a href="../problems-module/index.html">problems</a></li>
<li><a href="index.html"><span class="selectedlink">syntax</span></a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Tree Verification' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../compiler.html">Services</a></li><li><a href="index.html">syntax</a></li><li><a href="index.html#2">Chapter 2: The Parse Tree</a></li><li><b>Tree Verification</b></li></ul></div>
<p class="purpose">Did we go wrong anywhere? This section is purely defensive, and tests whether Inform contains bugs of a kind which lead to malformed syntax trees: that should never happen even if the source text being compiled is a dumpster fire.</p>
<ul class="toc"><li><a href="2-tv.html#SP1">&#167;1. Verify integrity</a></li><li><a href="2-tv.html#SP3">&#167;3. Verify structure</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Verify integrity. </b>We can perform two different checks.
</p>
<p class="commentary">The first duty of a tree is to contain no loops, and the following checks
that (rejecting even undirected loops). In addition, it checks that each
node has an enumerated node type, rather than a meaning code.
</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">tree_stats_size</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">tree_stats_depth</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">tree_stats_width</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">VerifyTree::verify_integrity</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</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">tree_stats_size</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">tree_stats_depth</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">tree_stats_width</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="2-tv.html#SP1" class="function-link"><span class="function-syntax">VerifyTree::verify_integrity_below</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</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">VerifyTree::verify_integrity_below</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">VerifyTree::verify_integrity_below</span></span>:<br/><a href="2-tv.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="2-tv.html#SP2" class="function-link"><span class="function-syntax">VerifyTree::verify_integrity_r</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="string-syntax">"down"</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><a href="2-st.html#SP21" class="function-link"><span class="function-syntax">SyntaxTree::new_traverse_token</span></a><span class="plain-syntax">());</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>The verification traverse is a very cautious manoeuvre: we step through
the tree, testing each branch with our outstretched foot. At the first sign
of trouble we panic.
</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">VerifyTree::verify_integrity_r</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">VerifyTree::verify_integrity_r</span></span>:<br/><a href="2-tv.html#SP1">&#167;1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</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">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">way</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">depth</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">traverse_token</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">width</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">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">, </span><span class="identifier-syntax">width</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">-&gt;</span><span class="element-syntax">last_seen_on_traverse</span><span class="plain-syntax"> == </span><span class="identifier-syntax">traverse_token</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">"Cycle found in parse tree, found %s from:\n$P"</span><span class="plain-syntax">, </span><span class="identifier-syntax">way</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Errors::set_internal_handler</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">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Cycle found in parse tree"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">last_seen_on_traverse</span><span class="plain-syntax"> = </span><span class="identifier-syntax">traverse_token</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax"> = </span><a href="2-pn.html#SP5" class="function-link"><span class="function-syntax">Node::get_type</span></a><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><a href="2-nt.html#SP2" class="function-link"><span class="function-syntax">NodeType::is_enumerated</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">)) </span><span class="identifier-syntax">tree_stats_size</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">"Invalid node type (%08x) found %s from:\n$P"</span><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="identifier-syntax">way</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Errors::set_internal_handler</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">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Link broken in parse tree"</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">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="2-tv.html#SP2" class="function-link"><span class="function-syntax">VerifyTree::verify_integrity_r</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="string-syntax">"alt"</span><span class="plain-syntax">, </span><span class="identifier-syntax">depth</span><span class="plain-syntax">, </span><span class="identifier-syntax">traverse_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">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="2-tv.html#SP2" class="function-link"><span class="function-syntax">VerifyTree::verify_integrity_r</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="string-syntax">"down"</span><span class="plain-syntax">, </span><span class="identifier-syntax">depth</span><span class="plain-syntax">+1, </span><span class="identifier-syntax">traverse_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">width</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">tree_stats_width</span><span class="plain-syntax">) </span><span class="identifier-syntax">tree_stats_width</span><span class="plain-syntax"> = </span><span class="identifier-syntax">width</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">depth</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">tree_stats_depth</span><span class="plain-syntax">) </span><span class="identifier-syntax">tree_stats_depth</span><span class="plain-syntax"> = </span><span class="identifier-syntax">depth</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. Verify structure. </b>The parse tree is a complicated structure, arbitrarily wide and deep, and
containing many different node types, each subject to its own rules of usage.
In this second check, we ensure that nodes have acceptable parentage and
annotations &mdash; that is, parentage and annotations which fall within the
permissions set up when their node types were created.
</p>
<p class="commentary">If any test fails, Inform will stop with an internal error. (If there are
multiple failures, we itemise them to the debugging log, and only produce
a single internal error at the end.)
</p>
<p class="commentary">We protect ourselves by first checking that the tree is intact as a
structure: once we know the tree is safe to climb over, we can wander
about counting branches with impunity.
</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">VerifyTree::verify_structure</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</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">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">root_node</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">Errors::set_internal_handler</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">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Root of parse tree NULL"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><a href="2-tv.html#SP3" class="function-link"><span class="function-syntax">VerifyTree::verify_structure_from</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</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">VerifyTree::verify_structure_from</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">VerifyTree::verify_structure_from</span></span>:<br/>Simple Preform Cache - <a href="2-spc.html#SP2">&#167;2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="2-tv.html#SP1" class="function-link"><span class="function-syntax">VerifyTree::verify_integrity_below</span></a><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">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">errors_found</span><span class="plain-syntax"> = </span><a href="2-tv.html#SP4" class="function-link"><span class="function-syntax">VerifyTree::verify_structure_r</span></a><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="constant-syntax">0</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">errors_found</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="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"[Verification failed: %d node errors]\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">errors_found</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Errors::set_internal_handler</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">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Parse tree broken"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>Note that on every call to the following routine, (i) <span class="extract"><span class="extract-syntax">p</span></span> is a valid
parse node and (ii) either <span class="extract"><span class="extract-syntax">p</span></span> is the tree root, in which case <span class="extract"><span class="extract-syntax">parent</span></span> is
<span class="extract"><span class="extract-syntax">NULL</span></span>, or <span class="extract"><span class="extract-syntax">parent</span></span> is the unique node having <span class="extract"><span class="extract-syntax">p</span></span> (or an alternative to <span class="extract"><span class="extract-syntax">p</span></span>)
among its children.
</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">VerifyTree::verify_structure_r</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">VerifyTree::verify_structure_r</span></span>:<br/><a href="2-tv.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">parent</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">ec</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax"> = </span><a href="2-pn.html#SP5" class="function-link"><span class="function-syntax">Node::get_type</span></a><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">node_type_metadata</span><span class="plain-syntax"> *</span><span class="identifier-syntax">metadata</span><span class="plain-syntax"> = </span><a href="2-nt.html#SP7" class="function-link"><span class="function-syntax">NodeType::get_metadata</span></a><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">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">metadata</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"broken tree should have been reported"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tv.html#SP4_1" class="named-paragraph-link"><span class="named-paragraph">Check rule (1) of the invariant</span><span class="named-paragraph-number">4.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tv.html#SP4_2" class="named-paragraph-link"><span class="named-paragraph">Check rule (2) of the invariant</span><span class="named-paragraph-number">4.2</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">parent</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="2-tv.html#SP4_3" class="named-paragraph-link"><span class="named-paragraph">Check rule (3) of the invariant</span><span class="named-paragraph-number">4.3</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">children_count</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">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">q</span><span class="plain-syntax">=</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">; </span><span class="identifier-syntax">q</span><span class="plain-syntax">; </span><span class="identifier-syntax">q</span><span class="plain-syntax">=</span><span class="identifier-syntax">q</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">, </span><span class="identifier-syntax">children_count</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ec</span><span class="plain-syntax"> += </span><a href="2-tv.html#SP4" class="function-link"><span class="function-syntax">VerifyTree::verify_structure_r</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">q</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="identifier-syntax">ec</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tv.html#SP4_4" class="named-paragraph-link"><span class="named-paragraph">Check rule (4) of the invariant</span><span class="named-paragraph-number">4.4</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">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ec</span><span class="plain-syntax"> += </span><a href="2-tv.html#SP4" class="function-link"><span class="function-syntax">VerifyTree::verify_structure_r</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">, </span><span class="identifier-syntax">parent</span><span class="plain-syntax">, </span><span class="identifier-syntax">ec</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">ec</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4_1" class="paragraph-anchor"></a><b>&#167;4.1. </b>Rule (1): no INVALID nodes.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Check rule (1) of the invariant</span><span class="named-paragraph-number">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="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">t</span><span class="plain-syntax"> == </span><span class="constant-syntax">INVALID_NT</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%d is $N, which is not allowed except temporarily\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">allocation_id</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tv.html#SP4_1_1" class="named-paragraph-link"><span class="named-paragraph">Log this invariant failure</span><span class="named-paragraph-number">4.1.1</span></a></span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-tv.html#SP4">&#167;4</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_2" class="paragraph-anchor"></a><b>&#167;4.2. </b>Rule (2): all annotations must be legal for the given node type.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Check rule (2) of the invariant</span><span class="named-paragraph-number">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="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (!(</span><a href="2-na.html#SP15" class="function-link"><span class="function-syntax">Annotations::is_allowed</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotation_id</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%d is $N, which is not allowed to have annotation %d\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">allocation_id</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotation_id</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">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Node %08x, ann %d\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotation_id</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tv.html#SP4_1_1" class="named-paragraph-link"><span class="named-paragraph">Log this invariant failure</span><span class="named-paragraph-number">4.1.1</span></a></span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-tv.html#SP4">&#167;4</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_3" class="paragraph-anchor"></a><b>&#167;4.3. </b>Rule (3): can this combination of parent and child exist?
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Check rule (3) of the invariant</span><span class="named-paragraph-number">4.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="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t_parent</span><span class="plain-syntax"> = </span><a href="2-pn.html#SP5" class="function-link"><span class="function-syntax">Node::get_type</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">parent</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (!(</span><a href="2-nt.html#SP13" class="function-link"><span class="function-syntax">NodeType::parentage_allowed</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t_parent</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">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"N%d is $N: should not be a child of $N\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">allocation_id</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">t_parent</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tv.html#SP4_1_1" class="named-paragraph-link"><span class="named-paragraph">Log this invariant failure</span><span class="named-paragraph-number">4.1.1</span></a></span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-tv.html#SP4">&#167;4</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_4" class="paragraph-anchor"></a><b>&#167;4.4. </b>Rule (4): The number of children has to be within the given extrema.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Check rule (4) of the invariant</span><span class="named-paragraph-number">4.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">children_count</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">metadata</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">min_children</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%d has %d children, but min for $N is %d:\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">allocation_id</span><span class="plain-syntax">, </span><span class="identifier-syntax">children_count</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">metadata</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">min_children</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tv.html#SP4_1_1" class="named-paragraph-link"><span class="named-paragraph">Log this invariant failure</span><span class="named-paragraph-number">4.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">children_count</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">metadata</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">max_children</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%d has %d children, but max for $N is %d:\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">allocation_id</span><span class="plain-syntax">, </span><span class="identifier-syntax">children_count</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">metadata</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">max_children</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-tv.html#SP4_1_1" class="named-paragraph-link"><span class="named-paragraph">Log this invariant failure</span><span class="named-paragraph-number">4.1.1</span></a></span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-tv.html#SP4">&#167;4</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_1_1" class="paragraph-anchor"></a><b>&#167;4.1.1. </b>(Logging the root node produces an absolutely enormous output.)
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Log this invariant failure</span><span class="named-paragraph-number">4.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><a href="2-pn.html#SP5" class="function-link"><span class="function-syntax">Node::is</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">parent</span><span class="plain-syntax">, </span><span class="constant-syntax">ROOT_NT</span><span class="plain-syntax">)) </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Failing subtree:\n$T"</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">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Failing subtree:\n$T"</span><span class="plain-syntax">, </span><span class="identifier-syntax">parent</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ec</span><span class="plain-syntax">++;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-tv.html#SP4_1">&#167;4.1</a>, <a href="2-tv.html#SP4_2">&#167;4.2</a>, <a href="2-tv.html#SP4_3">&#167;4.3</a>, <a href="2-tv.html#SP4_4">&#167;4.4</a> (twice).</li></ul>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="2-na.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-sm.html">1</a></li><li class="progresscurrentchapter">2</li><li class="progresssection"><a href="2-st.html">st</a></li><li class="progresssection"><a href="2-nt.html">nt</a></li><li class="progresssection"><a href="2-pn.html">pn</a></li><li class="progresssection"><a href="2-na.html">na</a></li><li class="progresscurrent">tv</li><li class="progresssection"><a href="2-spc.html">spc</a></li><li class="progresschapter"><a href="3-snt.html">3</a></li><li class="progressnext"><a href="2-spc.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>