1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 16:44:21 +03:00
inform7/docs/calculus-module/3-cs.html

326 lines
50 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Compilation Schemas</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="../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 'Compilation Schemas' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../services.html">Services</a></li><li><a href="index.html">calculus</a></li><li><a href="index.html#3">Chapter 3: Binary Predicates</a></li><li><b>Compilation Schemas</b></li></ul></div>
<p class="purpose">To manage prototype pieces of code for use in code-generation.</p>
<ul class="toc"><li><a href="3-cs.html#SP1">&#167;1. Schemas</a></li><li><a href="3-cs.html#SP3">&#167;3. Annotated schemas</a></li><li><a href="3-cs.html#SP5">&#167;5. Building schemas</a></li><li><a href="3-cs.html#SP6">&#167;6. Emptiness</a></li><li><a href="3-cs.html#SP7">&#167;7. Logging schemas</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Schemas. </b>The calculus module should not in any direct way be involved in code
generation; on the other hand, predicates and quantifiers need eventually to
result in compiled code, and that code will look different for different
predicates. There has to be some way to systematically handle those differences.
</p>
<p class="commentary">Code in the Inform compiler is generated largely from "schemas", which are
small model pieces of code used with variations in different settings. There
are two different data structures for these:
</p>
<ul class="items"><li>(a) An <span class="extract"><span class="extract-syntax">i6_schema</span></span> uses textual notation based on the syntax of the C-like
language Inform 6; to be used, this must be converted to
</li><li>(b) An <span class="extract"><span class="extract-syntax">inter_schema</span></span>, which is a partly compiled form of the same, and
has a tree structure closer to the final Inter code.
</li></ul>
<p class="commentary">For inter schemas and how the conversion of (a) to (b) is done, see the
Inform compiler source at <a href="../building-module/2-is.html" class="internal">Inter Schemas (in building)</a>. If this calculus
module is used outside of Inform, of course, no <span class="extract"><span class="extract-syntax">inter_schema</span></span> will exist.
</p>
<p class="commentary">A simple example of an <span class="extract"><span class="extract-syntax">i6_schema</span></span> might use the notation <span class="extract"><span class="extract-syntax">*1 == *2</span></span>; this
will ultimately compile to a test that two quantities are numerically equal.
As this example shows, <span class="extract"><span class="extract-syntax">*</span></span> is an escape character. See <a href="../building-module/2-is.html" class="internal">Inter Schemas (in building)</a>;
<span class="extract"><span class="extract-syntax">*1</span></span> is an example of what is called an "abbreviated command" there.
</p>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>The <a href="3-cs.html#SP2" class="internal">i6_schema</a> structure is very simple, then. Schemas can be of unlimited
length, but we want to be able to create and dispose of them quickly and to
avoid unnecessary stream memory claims. So each <span class="extract"><span class="extract-syntax">i6_schema</span></span> structure contains
a fixed block of storage for the first few characters. (In fact, long ones are
never needed in practice, but we must avoid any risk of buffer overrun for safety.)
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">TYPICAL_I6_SCHEMA_LENGTH</span><span class="plain-syntax"> </span><span class="constant-syntax">128</span><span class="plain-syntax"> </span><span class="comment-syntax"> in practice 40 is plenty</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">i6_schema</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">prototype_storage</span><span class="plain-syntax">[</span><span class="constant-syntax">TYPICAL_I6_SCHEMA_LENGTH</span><span class="plain-syntax">]; </span><span class="comment-syntax"> used just to make space for...</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> </span><span class="identifier-syntax">prototype</span><span class="plain-syntax">; </span><span class="comment-syntax"> ...this</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_quoted_inames</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">inter_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">compiled</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">inter_name</span><span class="plain-syntax"> *</span><span class="identifier-syntax">quoted_inames</span><span class="plain-syntax">[2];</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure i6_schema is private to this section.</li></ul>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. Annotated schemas. </b>It is sometimes convenient to carry around a schema together with calculus
terms for what will go into <span class="extract"><span class="extract-syntax">*1</span></span> and <span class="extract"><span class="extract-syntax">*2</span></span> when it is expanded, and with a
few other contextual details.
</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">annotated_i6_schema</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">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">schema</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">negate_schema</span><span class="plain-syntax">; </span><span class="comment-syntax"> true if atom is to be tested with the opposite parity</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">pcalc_term</span><span class="plain-syntax"> </span><span class="identifier-syntax">pt0</span><span class="plain-syntax">; </span><span class="comment-syntax"> terms on which the I6 schema is to be expanded</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">pcalc_term</span><span class="plain-syntax"> </span><span class="identifier-syntax">pt1</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">involves_action_variables</span><span class="plain-syntax">;</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">annotated_i6_schema</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure annotated_i6_schema is accessed in 3/bpf and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>And here it is, before being annotated...
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">annotated_i6_schema</span><span class="plain-syntax"> </span><span class="function-syntax">Calculus::Schemas::blank_asch</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">annotated_i6_schema</span><span class="plain-syntax"> </span><span class="identifier-syntax">asch</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">asch</span><span class="plain-syntax">.</span><span class="element-syntax">schema</span><span class="plain-syntax"> = </span><a href="3-cs.html#SP5" class="function-link"><span class="function-syntax">Calculus::Schemas::new</span></a><span class="plain-syntax">(</span><span class="string-syntax">" "</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">asch</span><span class="plain-syntax">.</span><span class="element-syntax">negate_schema</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">asch</span><span class="plain-syntax">.</span><span class="element-syntax">pt0</span><span class="plain-syntax"> = </span><a href="4-trm.html#SP4" class="function-link"><span class="function-syntax">Terms::new_variable</span></a><span class="plain-syntax">(0);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">asch</span><span class="plain-syntax">.</span><span class="element-syntax">pt1</span><span class="plain-syntax"> = </span><a href="4-trm.html#SP4" class="function-link"><span class="function-syntax">Terms::new_variable</span></a><span class="plain-syntax">(0);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">asch</span><span class="plain-syntax">.</span><span class="element-syntax">involves_action_variables</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">asch</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. Building schemas. </b>When schemas are generated inside Inform, they often look as if they have an
even more elaborate syntax, with escapes like <span class="extract"><span class="extract-syntax">%s</span></span> in them. But this is because
they are generated with the following <span class="extract"><span class="extract-syntax">printf</span></span>-style function. Those <span class="extract"><span class="extract-syntax">%</span></span> escapes
are expanded now, when the schema is created, and not later when code is generated
from it. For example, the function call:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">Calculus::Schemas::new</span><span class="plain-syntax">(</span><span class="string-syntax">"*1.%n = *2.%n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="identifier-syntax">Y</span><span class="plain-syntax">)</span>
</pre>
<p class="commentary">might produce a schema whose <span class="extract"><span class="extract-syntax">prototype</span></span> text came out as
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">*1.x100 = *2.y62</span>
</pre>
<p class="commentary">...supposing that <span class="extract"><span class="extract-syntax">x100</span></span> and <span class="extract"><span class="extract-syntax">y62</span></span> were the Inter identifiers for whatever was
referred to by the <span class="extract"><span class="extract-syntax">inter_name</span></span> values <span class="extract"><span class="extract-syntax">X</span></span> and <span class="extract"><span class="extract-syntax">Y</span></span> supplied in the arguments.
Here then is that <span class="extract"><span class="extract-syntax">printf</span></span>-like function:
</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">unique_qi_counter</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="comment-syntax"> quoted iname count</span>
<span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="function-syntax">Calculus::Schemas::new</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">Calculus::Schemas::new</span></span>:<br/><a href="3-cs.html#SP4">&#167;4</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">fmt</span><span class="plain-syntax">, ...) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">va_list</span><span class="plain-syntax"> </span><span class="identifier-syntax">ap</span><span class="plain-syntax">; </span><span class="comment-syntax"> the variable argument list signified by the dots</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sch</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">prototype</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Streams::new_buffer</span><span class="plain-syntax">(</span><span class="constant-syntax">TYPICAL_I6_SCHEMA_LENGTH</span><span class="plain-syntax">, </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">prototype_storage</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_quoted_inames</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">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">OUT</span><span class="plain-syntax"> = &amp;(</span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">prototype</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="3-cs.html#SP5_3" class="named-paragraph-link"><span class="named-paragraph">Process the varargs into schema prototype text</span><span class="named-paragraph-number">5.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">va_end</span><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">); </span><span class="comment-syntax"> macro to end variable argument processing</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">compiled</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ParsingSchemas::from_i6s</span><span class="plain-syntax">(&amp;(</span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">prototype</span><span class="plain-syntax">),</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_quoted_inames</span><span class="plain-syntax">, (</span><span class="reserved-syntax">void</span><span class="plain-syntax"> **) </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">quoted_inames</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">sch</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5_1" class="paragraph-anchor"></a><b>&#167;5.1. </b>And this is a variation for modifying an existing schema:
</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">Calculus::Schemas::modify</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">Calculus::Schemas::modify</span></span>:<br/>Binary Predicates - <a href="3-bp.html#SP18_1">&#167;18.1</a>, <a href="3-bp.html#SP18_2">&#167;18.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sch</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">fmt</span><span class="plain-syntax">, ...) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">va_list</span><span class="plain-syntax"> </span><span class="identifier-syntax">ap</span><span class="plain-syntax">; </span><span class="comment-syntax"> the variable argument list signified by the dots</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">prototype</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Streams::new_buffer</span><span class="plain-syntax">(</span><span class="constant-syntax">TYPICAL_I6_SCHEMA_LENGTH</span><span class="plain-syntax">, </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">prototype_storage</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_quoted_inames</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">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">OUT</span><span class="plain-syntax"> = &amp;(</span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">prototype</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="3-cs.html#SP5_3" class="named-paragraph-link"><span class="named-paragraph">Process the varargs into schema prototype text</span><span class="named-paragraph-number">5.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">va_end</span><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">); </span><span class="comment-syntax"> macro to end variable argument processing</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">compiled</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ParsingSchemas::from_i6s</span><span class="plain-syntax">(&amp;(</span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">prototype</span><span class="plain-syntax">),</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_quoted_inames</span><span class="plain-syntax">, (</span><span class="reserved-syntax">void</span><span class="plain-syntax"> **) </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">quoted_inames</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5_2" class="paragraph-anchor"></a><b>&#167;5.2. </b>And another:
</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">Calculus::Schemas::append</span><span class="plain-syntax">(</span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sch</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">fmt</span><span class="plain-syntax">, ...) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">va_list</span><span class="plain-syntax"> </span><span class="identifier-syntax">ap</span><span class="plain-syntax">; </span><span class="comment-syntax"> the variable argument list signified by the dots</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">OUT</span><span class="plain-syntax"> = &amp;(</span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">prototype</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="3-cs.html#SP5_3" class="named-paragraph-link"><span class="named-paragraph">Process the varargs into schema prototype text</span><span class="named-paragraph-number">5.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">va_end</span><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">); </span><span class="comment-syntax"> macro to end variable argument processing</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">compiled</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ParsingSchemas::from_i6s</span><span class="plain-syntax">(&amp;(</span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">prototype</span><span class="plain-syntax">),</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_quoted_inames</span><span class="plain-syntax">, (</span><span class="reserved-syntax">void</span><span class="plain-syntax"> **) </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">quoted_inames</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5_3" class="paragraph-anchor"></a><b>&#167;5.3. </b>Either way, the schema's prototype is written as follows:
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Process the varargs into schema prototype text</span><span class="named-paragraph-number">5.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">char</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">va_start</span><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">, </span><span class="identifier-syntax">fmt</span><span class="plain-syntax">); </span><span class="comment-syntax"> macro to begin variable argument processing</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">fmt</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="plain-syntax"> </span><span class="reserved-syntax">switch</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">case</span><span class="plain-syntax"> </span><span class="character-syntax">'%'</span><span class="plain-syntax">: </span><span class="named-paragraph-container code-font"><a href="3-cs.html#SP5_3_1" class="named-paragraph-link"><span class="named-paragraph">Recognise schema-format escape sequences</span><span class="named-paragraph-number">5.3.1</span></a></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">PUT</span><span class="plain-syntax">(*</span><span class="identifier-syntax">p</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>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-cs.html#SP5">&#167;5</a>, <a href="3-cs.html#SP5_1">&#167;5.1</a>, <a href="3-cs.html#SP5_2">&#167;5.2</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_3_1" class="paragraph-anchor"></a><b>&#167;5.3.1. </b>We recognise only a few escapes here: <span class="extract"><span class="extract-syntax">%%</span></span>, a literal percentage sign; <span class="extract"><span class="extract-syntax">%d</span></span>,
an integer; <span class="extract"><span class="extract-syntax">%s</span></span>, a C string; <span class="extract"><span class="extract-syntax">%S</span></span>, a text stream; and three which are higher-level:
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">%k</span></span> takes a <span class="extract"><span class="extract-syntax">kind</span></span> parameter and expands to its weak ID;
</li><li>(b) <span class="extract"><span class="extract-syntax">%L</span></span> takes a <span class="extract"><span class="extract-syntax">local_variable</span></span> and expands to its identifier;
</li><li>(c) <span class="extract"><span class="extract-syntax">%n</span></span> takes an <span class="extract"><span class="extract-syntax">inter_name</span></span>, which expands more cautiously in a way which
stores the actual <span class="extract"><span class="extract-syntax">inter_name</span></span> reference: it is possible for two different
global values to have different <span class="extract"><span class="extract-syntax">inter_name</span></span>s but the same identifier text,
so it would not be safe to store only the textual identifier.
</li></ul>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Recognise schema-format escape sequences</span><span class="named-paragraph-number">5.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="identifier-syntax">p</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">p</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">'d'</span><span class="plain-syntax">: </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"%d"</span><span class="plain-syntax">, </span><span class="identifier-syntax">va_arg</span><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</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">'k'</span><span class="plain-syntax">:</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">RTKindIDs::write_weak_identifier</span><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">va_arg</span><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">, </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *));</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifndef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"{%u}"</span><span class="plain-syntax">, </span><span class="identifier-syntax">va_arg</span><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">, </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *));</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</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">'L'</span><span class="plain-syntax">:</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"%~L"</span><span class="plain-syntax">, </span><span class="identifier-syntax">va_arg</span><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">, </span><span class="identifier-syntax">local_variable</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">endif</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifndef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"%08x"</span><span class="plain-syntax">, </span><span class="identifier-syntax">va_arg</span><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</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">endif</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">'n'</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"> = </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_quoted_inames</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">2</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"too many inter_name quotes"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">quoted_inames</span><span class="plain-syntax">[</span><span class="identifier-syntax">N</span><span class="plain-syntax">] = (</span><span class="identifier-syntax">inter_name</span><span class="plain-syntax"> *) </span><span class="identifier-syntax">va_arg</span><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">, </span><span class="identifier-syntax">inter_name</span><span class="plain-syntax"> *);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"QUOTED_INAME_%d_%08x"</span><span class="plain-syntax">, </span><span class="identifier-syntax">N</span><span class="plain-syntax">, </span><span class="identifier-syntax">unique_qi_counter</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">case</span><span class="plain-syntax"> </span><span class="character-syntax">'N'</span><span class="plain-syntax">: </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"%N"</span><span class="plain-syntax">, </span><span class="identifier-syntax">va_arg</span><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</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">'s'</span><span class="plain-syntax">: </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"%s"</span><span class="plain-syntax">, </span><span class="identifier-syntax">va_arg</span><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</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">'S'</span><span class="plain-syntax">: </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"%S"</span><span class="plain-syntax">, </span><span class="identifier-syntax">va_arg</span><span class="plain-syntax">(</span><span class="identifier-syntax">ap</span><span class="plain-syntax">, </span><span class="identifier-syntax">text_stream</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">PUT</span><span class="plain-syntax">(</span><span class="character-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">fprintf</span><span class="plain-syntax">(</span><span class="identifier-syntax">stderr</span><span class="plain-syntax">, </span><span class="string-syntax">"*** Bad schema format: &lt;%s&gt; ***\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">fmt</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 % string escape in schema format"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-cs.html#SP5_3">&#167;5.3</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. Emptiness. </b>A schema is empty if its prototype is the empty text.
</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">Calculus::Schemas::empty</span><span class="plain-syntax">(</span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sch</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">sch</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">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">Str::len</span><span class="plain-syntax">(&amp;(</span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">prototype</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">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="SP7" class="paragraph-anchor"></a><b>&#167;7. Logging schemas. </b>The fact that I6 schemas are not much more than string makes them easy to log:
</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">Calculus::Schemas::log</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">Calculus::Schemas::log</span></span>:<br/>Calculus Module - <a href="1-cm.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sch</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="3-cs.html#SP7" class="function-link"><span class="function-syntax">Calculus::Schemas::write</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">DL</span><span class="plain-syntax">, </span><span class="identifier-syntax">sch</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">Calculus::Schemas::write</span><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sch</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">sch</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;null schema&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">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;schema: %S&gt;"</span><span class="plain-syntax">, &amp;(</span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">prototype</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">Calculus::Schemas::log_applied</span><span class="plain-syntax">(</span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sch</span><span class="plain-syntax">, </span><span class="reserved-syntax">pcalc_term</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pt1</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="3-cs.html#SP7" class="function-link"><span class="function-syntax">Calculus::Schemas::write_applied</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">DL</span><span class="plain-syntax">, </span><span class="identifier-syntax">sch</span><span class="plain-syntax">, </span><span class="identifier-syntax">pt1</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">Calculus::Schemas::write_applied</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">Calculus::Schemas::write_applied</span></span>:<br/>Terms - <a href="4-trm.html#SP11">&#167;11</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sch</span><span class="plain-syntax">, </span><span class="reserved-syntax">pcalc_term</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pt1</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">sch</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;null schema&gt;"</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">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;%S : "</span><span class="plain-syntax">, &amp;(</span><span class="identifier-syntax">sch</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">prototype</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><a href="4-trm.html#SP11" class="function-link"><span class="function-syntax">Terms::write</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">pt1</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"&gt;"</span><span class="plain-syntax">);</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="3-ter.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-cm.html">1</a></li><li class="progresschapter"><a href="2-up.html">2</a></li><li class="progresscurrentchapter">3</li><li class="progresssection"><a href="3-bpf.html">bpf</a></li><li class="progresssection"><a href="3-bptd.html">bptd</a></li><li class="progresssection"><a href="3-bp.html">bp</a></li><li class="progresssection"><a href="3-ter.html">ter</a></li><li class="progresscurrent">cs</li><li class="progresschapter"><a href="4-trm.html">4</a></li><li class="progresschapter"><a href="5-sc.html">5</a></li><li class="progressnext"><a href="4-trm.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>