mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 18:14:21 +03:00
192 lines
22 KiB
HTML
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">★</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">§1. Definitions</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. Definitions. </b></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§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>§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">) > </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">>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">>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">>label_counter</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">lns</span><span class="plain">-</span><span class="element">>allocate_storage</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">lns</span><span class="plain">-</span><span class="element">>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">§4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§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">>module</span><span class="plain"> == </span><span class="identifier">cm</span><span class="plain">) && (</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">>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">§5</a>, <a href="#SP6">§6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§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">>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">>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">>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">>label_counter</span><span class="plain"> < 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">>label_prefix</span><span class="plain">, </span><span class="identifier">lns</span><span class="plain">-</span><span class="element">>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">>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">§3.4.2</a>, <a href="25-cii.html#SP3_4_4">§3.4.4</a>, <a href="25-cii.html#SP3_4_5">§3.4.5</a>), 25/cp (<a href="25-cp.html#SP5_4_3">§5.4.3</a>), 26/iti (<a href="26-iti.html#SP7_8_3">§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">§3.4.1</a>), 25/cp (<a href="25-cp.html#SP5_4_3">§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">§3.4.3</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§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">--> 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"> > </span><span class="identifier">lns</span><span class="plain">-</span><span class="element">>allocate_storage</span><span class="plain">) </span><span class="identifier">lns</span><span class="plain">-</span><span class="element">>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">>allocate_storage</span><span class="plain"> > 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">>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">>allocate_storage</span><span class="plain">)*(</span><span class="identifier">lns</span><span class="plain">-</span><span class="element">>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"><</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">§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">§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>
|
|
|