1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/core-module/26-jl.html
2019-08-24 11:21:48 +01:00

192 lines
22 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>26/lt</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<!--Weave of '26/jl' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">core</a></li><li><a href="index.html#26">Chapter 26: Compilation Utilities</a></li><li><b>Jump Labels</b></li></ul><p class="purpose">I7 is has no Dijkstra-like conscience about compiling code which is full of |jump| statements, and these require labels to jump to. This section provides those labels, and other related unique-ID-number counters.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Definitions. </b></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>For clarity we give each label in the compiled code its own unique name
(even though this is not strictly necessary since I6 labels have only local
scope to their routines), and this means allowing for sets of labels with
a unique ID number providing guaranteed-previously-unused new labels in
every set.
</p>
<p class="inwebparagraph">So: each set of labels is identified with a name, and the labels written take
the form <code class="display"><span class="extract">L_NameNumber</span></code>. For instance, <code class="display"><span class="extract">L_Marble17</span></code> is the 18th label in
namespace <code class="display"><span class="extract">Marble</span></code>. Every label namespace's name must differ from every
other. It is legal for a namespace's name to be the empty string, which
generates labels <code class="display"><span class="extract">L_0</span></code>, <code class="display"><span class="extract">L_1</span></code>, ...
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_NAMESPACE_PREFIX_LENGTH</span><span class="plain"> 20 </span> <span class="comment">when <code class="display"><span class="extract">L_</span></code> and a number are added, we are within 31 chars</span>
</pre>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">label_namespace</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">label_prefix</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">label_counter</span><span class="plain">; </span> <span class="comment">next free ID number for this label namespace</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">allocate_storage</span><span class="plain">; </span> <span class="comment">number of words of memory to reserve for each label</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">label_storage_iname</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">compilation_module</span><span class="plain"> *</span><span class="identifier">module</span><span class="plain">;</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">label_namespace</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure label_namespace is private to this section.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>The creator for new label namespaces. Note that, by default, a label namespace
reserves no memory.
</p>
<pre class="display">
<span class="reserved">label_namespace</span><span class="plain"> *</span><span class="functiontext">JumpLabels::new_namespace</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">compilation_module</span><span class="plain"> *</span><span class="identifier">cm</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">) &gt; </span><span class="constant">MAX_NAMESPACE_PREFIX_LENGTH</span><span class="plain">) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="constant">CORE_MODULE</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_LabelNamespaceTooLong</span><span class="plain">),</span>
<span class="string">"a label namespace prefix is too long"</span><span class="plain">,</span>
<span class="string">"and should be shortened to a few alphabetic characters."</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">#</span><span class="identifier">ifndef</span><span class="plain"> </span><span class="constant">CORE_MODULE</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"namespace prefix too long"</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">}</span>
<span class="reserved">label_namespace</span><span class="plain"> *</span><span class="identifier">lns</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">label_namespace</span><span class="plain">);</span>
<span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;label_prefix</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">);</span>
<span class="identifier">package_request</span><span class="plain"> *</span><span class="identifier">PR2</span><span class="plain"> = </span><span class="functiontext">Hierarchy::synoptic_package</span><span class="plain">(</span><span class="constant">LABEL_STORAGES_HAP</span><span class="plain">);</span>
<span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;label_storage_iname</span><span class="plain"> = </span><span class="functiontext">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="constant">LABEL_ASSOCIATED_STORAGE_HL</span><span class="plain">, </span><span class="identifier">PR2</span><span class="plain">);</span>
<span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;label_counter</span><span class="plain"> = 0;</span>
<span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;allocate_storage</span><span class="plain"> = 0;</span>
<span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;module</span><span class="plain"> = </span><span class="identifier">cm</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">lns</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function JumpLabels::new_namespace is used in <a href="#SP4">&#167;4</a>.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>The rest of Inform tends not to store pointers to namespaces: instead it
must access them by searching on the name. This is inefficient, but there are
few namespaces and it happens fairly seldom, so there is no point in
optimising.
</p>
<pre class="display">
<span class="reserved">label_namespace</span><span class="plain"> *</span><span class="functiontext">JumpLabels::namespace_by_prefix</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">compilation_module</span><span class="plain"> *</span><span class="identifier">cm</span><span class="plain">) {</span>
<span class="reserved">label_namespace</span><span class="plain"> *</span><span class="identifier">lns</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">lns</span><span class="plain">, </span><span class="reserved">label_namespace</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;module</span><span class="plain"> == </span><span class="identifier">cm</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;label_prefix</span><span class="plain">)))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">lns</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">label_namespace</span><span class="plain"> *</span><span class="functiontext">JumpLabels::read_or_create_namespace</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">) {</span>
<span class="identifier">compilation_module</span><span class="plain"> *</span><span class="identifier">cm</span><span class="plain"> = </span><span class="functiontext">Modules::current</span><span class="plain">();</span>
<span class="reserved">label_namespace</span><span class="plain"> *</span><span class="identifier">lns</span><span class="plain"> = </span><span class="functiontext">JumpLabels::namespace_by_prefix</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">cm</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lns</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">lns</span><span class="plain"> = </span><span class="functiontext">JumpLabels::new_namespace</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">cm</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">lns</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function JumpLabels::namespace_by_prefix appears nowhere else.</p>
<p class="endnote">The function JumpLabels::read_or_create_namespace is used in <a href="#SP5">&#167;5</a>, <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>The rest of Inform is allowed only to call for a label in a given namespace,
advancing the counter or not as it pleases; or to call for the current
counter value.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">JumpLabels::read_counter</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">namespace</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">advance_flag</span><span class="plain">) {</span>
<span class="reserved">label_namespace</span><span class="plain"> *</span><span class="identifier">lns</span><span class="plain"> = </span><span class="functiontext">JumpLabels::read_or_create_namespace</span><span class="plain">(</span><span class="identifier">namespace</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;label_counter</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">advance_flag</span><span class="plain"> == </span><span class="identifier">TRUE</span><span class="plain">) </span><span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;label_counter</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">advance_flag</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;label_counter</span><span class="plain">--;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;label_counter</span><span class="plain"> &lt; 0) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"label counter negative"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">c</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">JumpLabels::write</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">namespace</span><span class="plain">) {</span>
<span class="reserved">label_namespace</span><span class="plain"> *</span><span class="identifier">lns</span><span class="plain"> = </span><span class="functiontext">JumpLabels::read_or_create_namespace</span><span class="plain">(</span><span class="identifier">namespace</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"L_%S%d"</span><span class="plain">, </span><span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;label_prefix</span><span class="plain">, </span><span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;label_counter</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="functiontext">JumpLabels::storage</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">namespace</span><span class="plain">) {</span>
<span class="reserved">label_namespace</span><span class="plain"> *</span><span class="identifier">lns</span><span class="plain"> = </span><span class="functiontext">JumpLabels::read_or_create_namespace</span><span class="plain">(</span><span class="identifier">namespace</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;label_storage_iname</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function JumpLabels::read_counter is used in 25/cii (<a href="25-cii.html#SP3_4_2">&#167;3.4.2</a>, <a href="25-cii.html#SP3_4_4">&#167;3.4.4</a>, <a href="25-cii.html#SP3_4_5">&#167;3.4.5</a>), 25/cp (<a href="25-cp.html#SP5_4_3">&#167;5.4.3</a>), 26/iti (<a href="26-iti.html#SP7_8_3">&#167;7.8.3</a>).</p>
<p class="endnote">The function JumpLabels::write is used in 25/cii (<a href="25-cii.html#SP3_4_1">&#167;3.4.1</a>), 25/cp (<a href="25-cp.html#SP5_4_3">&#167;5.4.3</a>).</p>
<p class="endnote">The function JumpLabels::storage is used in 25/cii (<a href="25-cii.html#SP3_4_3">&#167;3.4.3</a>).</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>It is possible to mark a namespace as requiring 1 or more words of storage.
If so, the namespace <code class="display"><span class="extract">Whatsit</span></code> makes a word array called <code class="display"><span class="extract">I7_ST_Whatsit</span></code>
which contains enough words for each label actually allocated to have that
many words of storage. (And we add 2 words, to provide a safety margin, and
because in the event of a namespace for which no labels are created, I6
would otherwise throw an error at being asked to make an array with the
specification <code class="display"><span class="extract">--&gt; 0</span></code>.)
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">JumpLabels::allocate_counter</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">namespace</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">multiplier</span><span class="plain">) {</span>
<span class="reserved">label_namespace</span><span class="plain"> *</span><span class="identifier">lns</span><span class="plain"> = </span><span class="functiontext">JumpLabels::read_or_create_namespace</span><span class="plain">(</span><span class="identifier">namespace</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">multiplier</span><span class="plain"> &gt; </span><span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;allocate_storage</span><span class="plain">) </span><span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;allocate_storage</span><span class="plain"> = </span><span class="identifier">multiplier</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">JumpLabels::compile_necessary_storage</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">label_namespace</span><span class="plain"> *</span><span class="identifier">lns</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">lns</span><span class="plain">, </span><span class="reserved">label_namespace</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;allocate_storage</span><span class="plain"> &gt; 0) {</span>
<span class="identifier">packaging_state</span><span class="plain"> </span><span class="identifier">save</span><span class="plain"> = </span><span class="functiontext">Emit::named_array_begin</span><span class="plain">(</span><span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;label_storage_iname</span><span class="plain">, </span><span class="identifier">K_value</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = (</span><span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;allocate_storage</span><span class="plain">)*(</span><span class="identifier">lns</span><span class="plain">-</span><span class="element">&gt;label_counter</span><span class="plain">) + 2;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">N</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="functiontext">Emit::array_numeric_entry</span><span class="plain">(0);</span>
<span class="functiontext">Emit::array_end</span><span class="plain">(</span><span class="identifier">save</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function JumpLabels::allocate_counter is used in 25/cii (<a href="25-cii.html#SP3_4_6">&#167;3.4.6</a>).</p>
<p class="endnote">The function JumpLabels::compile_necessary_storage is used in 1/mr (<a href="1-mr.html#SP4_14">&#167;4.14</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="26-lt.html">Back to 'List Together'</a></li><li><a href="26-ct.html">Continue with 'Compiled Text'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>