1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-03 07:24:58 +03:00
inform7/docs/BasicInformKit/S-mst.html
2020-05-03 01:20:55 +01:00

288 lines
37 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>MStack Template</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
MathJax = {
tex: {
inlineMath: '$', '$'], ['\\(', '\\)'
},
svg: {
fontCache: 'global'
}
};
</script>
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
</script>
<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-src/Figures/Inform.png" height=72">
</a></h1>
<ul><li><a href="../compiler.html">compiler tools</a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul><h2>Extensions</h2><ul>
<li><a href="../basic_inform/index.html">basic_inform</a></li>
<li><a href="../standard_rules/index.html">standard_rules</a></li>
</ul><h2>Kits</h2><ul>
<li><a href="index.html"><span class="selectedlink">BasicInformKit</span></a></li>
<li><a href="../BasicInformExtrasKit/index.html">BasicInformExtrasKit</a></li>
<li><a href="../CommandParserKit/index.html">CommandParserKit</a></li>
<li><a href="../EnglishLanguageKit/index.html">EnglishLanguageKit</a></li>
<li><a href="../WorldModelKit/index.html">WorldModelKit</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'MStack Template' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../extensions.html">Kits</a></li><li><a href="index.html">BasicInformKit</a></li><li><b>MStack Template</b></li></ul></div>
<p class="purpose">To allocate space on the memory stack for frames of variables to be used by rulebooks, activities and actions.</p>
<ul class="toc"><li><a href="S-mst.html#SP1">&#167;1. The Memory Stack</a></li><li><a href="S-mst.html#SP2">&#167;2. Create Frame</a></li><li><a href="S-mst.html#SP3">&#167;3. Destroy Frame</a></li><li><a href="S-mst.html#SP4">&#167;4. Seek Frame</a></li><li><a href="S-mst.html#SP5">&#167;5. Backtrace</a></li><li><a href="S-mst.html#SP6">&#167;6. Access to Variables</a></li><li><a href="S-mst.html#SP7">&#167;7. Access to Nonexistent Variables</a></li><li><a href="S-mst.html#SP8">&#167;8. Rulebook Variables</a></li><li><a href="S-mst.html#SP9">&#167;9. Activity Variables</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1"></a><b>&#167;1. The Memory Stack. </b>The M-Stack, or memory stack, is a sequence of frames, piled upwards.
If we had an accessible stack in memory, we could use that, but neither
the Z-machine nor Glulx has such a stack, alas, alas, alas. The following
is not a very good solution, but it just about works.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">MAX_MSTACK_FRAME</span><span class="plain-syntax"> = </span><span class="constant-syntax">2</span><span class="plain-syntax"> + </span><span class="identifier-syntax">MAX_FRAME_SIZE_NEEDED</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">MSTACK_CAPACITY</span><span class="plain-syntax"> = </span><span class="constant-syntax">20</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">MSTACK_SIZE</span><span class="plain-syntax"> = </span><span class="identifier-syntax">MSTACK_CAPACITY</span><span class="plain-syntax">*</span><span class="identifier-syntax">MAX_MSTACK_FRAME</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">Array</span><span class="plain-syntax"> </span><span class="identifier-syntax">MStack</span><span class="plain-syntax"> --&gt; </span><span class="identifier-syntax">MSTACK_SIZE</span><span class="plain-syntax">;</span>
<span class="identifier-syntax">Global</span><span class="plain-syntax"> </span><span class="identifier-syntax">MStack_Top</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="comment-syntax">Topmost word currently used</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2"></a><b>&#167;2. Create Frame. </b>A frame is created by calling the following function with two arguments:
<span class="extract"><span class="extract-syntax">creator</span></span>, a function which initialises a block of variables, and an
ID number identifying the owner.
</p>
<p class="commentary">The <span class="extract"><span class="extract-syntax">creator</span></span> function is called with the address at which to initialise
the variables as its first argument, and the value 1 as the second
argument. (The idea is that the same function can be used later to
deallocate the variables, and then the second argument will be \(-1\).)
The <span class="extract"><span class="extract-syntax">creator</span></span> function returns the extent of the block of memory it has
used, in words. Thus is required to be strictly less than <span class="extract"><span class="extract-syntax">MAX_MSTACK_FRAME</span></span>
minus 1.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">Mstack_Create_Frame</span><span class="plain-syntax"> </span><span class="identifier-syntax">creator</span><span class="plain-syntax"> </span><span class="identifier-syntax">id</span><span class="plain-syntax"> </span><span class="identifier-syntax">extent</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">creator</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">extent</span><span class="plain-syntax"> = </span><span class="identifier-syntax">creator</span><span class="plain-syntax">.</span><span class="identifier-syntax">call</span><span class="plain-syntax">(</span><span class="identifier-syntax">MStack_Top</span><span class="plain-syntax">+2, </span><span class="constant-syntax">1</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">extent</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">rfalse</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">MStack_Top</span><span class="plain-syntax"> + </span><span class="identifier-syntax">MAX_MSTACK_FRAME</span><span class="plain-syntax"> &gt;= </span><span class="identifier-syntax">MSTACK_SIZE</span><span class="plain-syntax"> + </span><span class="constant-syntax">2</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">RunTimeProblem</span><span class="plain-syntax">(</span><span class="identifier-syntax">RTP_MSTACKMEMORY</span><span class="plain-syntax">, </span><span class="identifier-syntax">MSTACK_SIZE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Mstack_Backtrace</span><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">MStack_Top</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">MStack</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">MStack_Top</span><span class="plain-syntax"> = </span><span class="identifier-syntax">id</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">MStack_Top</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">MStack_Top</span><span class="plain-syntax"> = </span><span class="identifier-syntax">MStack_Top</span><span class="plain-syntax"> + </span><span class="identifier-syntax">extent</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">MStack</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">MStack_Top</span><span class="plain-syntax"> = -(</span><span class="identifier-syntax">extent</span><span class="plain-syntax">+2);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">rtrue</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3"></a><b>&#167;3. Destroy Frame. </b>As sketched above, the same creator function and ID number are passed to
the following routine to destroy the frame again. It takes the stack down
to the level of the most recently created frame with this ID number: note
that each action, for instance, has its own ID number for this purpose,
but can be taking place several times in a nested fashion &mdash; one taking
action might have caused another taking action which caused a third,
for instance, so that there are three incomplete taking actions at once.
In that case, there will be three independent sets of taking action
variables on the M-stack, all with the same ID number. We remove the
topmost one: the implication of that is that frames must always be
destroyed in reverse order of creation.
</p>
<p class="commentary">In practice, I7 uses frames such that the frame sought should always be
the topmost one in any case, and so that frames are always explicitly
destroyed, not wiped by being undercut when an earlier-created frame
is destroyed.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">Mstack_Destroy_Frame</span><span class="plain-syntax"> </span><span class="identifier-syntax">creator</span><span class="plain-syntax"> </span><span class="identifier-syntax">id</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Mstack_Seek_Frame</span><span class="plain-syntax">(</span><span class="identifier-syntax">id</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">pos</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">; </span><span class="comment-syntax">Not found: do nothing</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">MStack_Top</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> - </span><span class="constant-syntax">2</span><span class="plain-syntax">; </span><span class="comment-syntax">Clear mstack down to just below this frame</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">creator</span><span class="plain-syntax">) </span><span class="identifier-syntax">creator</span><span class="plain-syntax">.</span><span class="identifier-syntax">call</span><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">, -1);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">rtrue</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4"></a><b>&#167;4. Seek Frame. </b>We return the position on the M-stack of the most recently created frame
with the given ID number (see above), or 0 if no such frame exists; the
size is stored in the global variable <span class="extract"><span class="extract-syntax">MStack_Frame_Extent</span></span>. (Because word 0
on the stack is used as a sentinel &mdash; all frames are placed above it &mdash; no frame
can actually begin at word 0 on the stack, so 0 is safe to use as an exception.)
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">Global</span><span class="plain-syntax"> </span><span class="identifier-syntax">MStack_Frame_Extent</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">Mstack_Seek_Frame</span><span class="plain-syntax"> </span><span class="identifier-syntax">id</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> = </span><span class="identifier-syntax">MStack_Top</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">pos</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">MStack</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">pos</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">MStack_Frame_Extent</span><span class="plain-syntax"> = </span><span class="identifier-syntax">MStack</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">pos</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> + </span><span class="identifier-syntax">MStack_Frame_Extent</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">MStack_Frame_Extent</span><span class="plain-syntax"> = (-2) - </span><span class="identifier-syntax">MStack_Frame_Extent</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">MStack</span><span class="plain-syntax">--&gt;(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">+1) == </span><span class="identifier-syntax">id</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax">+2;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">MStack_Frame_Extent</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="comment-syntax">Not found</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5"></a><b>&#167;5. Backtrace. </b>Purely for debugging purposes, and giving feedback if the stack runs out of
memory:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">Mstack_Backtrace</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> </span><span class="identifier-syntax">k</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"Mstack backtrace: size "</span><span class="plain-syntax">, </span><span class="identifier-syntax">MStack_Top</span><span class="plain-syntax">+1, </span><span class="string-syntax">" words^"</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> = </span><span class="identifier-syntax">MStack_Top</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">MStack</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">pos</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">MStack_Frame_Extent</span><span class="plain-syntax"> = </span><span class="identifier-syntax">MStack</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">pos</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> + </span><span class="identifier-syntax">MStack_Frame_Extent</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">MStack_Frame_Extent</span><span class="plain-syntax"> = (-2) - </span><span class="identifier-syntax">MStack_Frame_Extent</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"Block at "</span><span class="plain-syntax">, </span><span class="identifier-syntax">pos</span><span class="plain-syntax">+2,</span>
<span class="plain-syntax"> </span><span class="string-syntax">" owner ID "</span><span class="plain-syntax">, </span><span class="identifier-syntax">MStack</span><span class="plain-syntax">--&gt;(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">+1), </span><span class="string-syntax">" size "</span><span class="plain-syntax">, </span><span class="identifier-syntax">MStack_Frame_Extent</span><span class="plain-syntax">, </span><span class="string-syntax">"^"</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">k</span><span class="plain-syntax">=0: </span><span class="identifier-syntax">k</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">MStack_Frame_Extent</span><span class="plain-syntax">: </span><span class="identifier-syntax">k</span><span class="plain-syntax">++) </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="identifier-syntax">MStack</span><span class="plain-syntax">--&gt;(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">+2+</span><span class="identifier-syntax">k</span><span class="plain-syntax">), </span><span class="string-syntax">" "</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"^"</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6"></a><b>&#167;6. Access to Variables. </b>An M-stack variable is identified by a combination of ID number and offset:
for instance ID 20007, offset 1, is the variable "room gone to" belonging
to the going action. The following routine converts that into an address on
the M-stack, in the topmost block with the given ID number (since "room gone
to", for instance, always means its value in the most current going action
of those now under way). Typechecking in the compiler should mean that it is
impossible to produce either error message below: Inform will only compile valid
uses of <span class="extract"><span class="extract-syntax">MstVO</span></span> ("M-stack variable offset") where the seek succeeds and
the offset is within range.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">MstVO</span><span class="plain-syntax"> </span><span class="identifier-syntax">id</span><span class="plain-syntax"> </span><span class="identifier-syntax">off</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Mstack_Seek_Frame</span><span class="plain-syntax">(</span><span class="identifier-syntax">id</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">pos</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"Variable unavailable for this action, activity or rulebook: "</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"internal ID number "</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">id</span><span class="plain-syntax">, </span><span class="string-syntax">"/"</span><span class="plain-syntax">, </span><span class="identifier-syntax">off</span><span class="plain-syntax">, </span><span class="string-syntax">"^"</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">off</span><span class="plain-syntax">&lt;0) || (</span><span class="identifier-syntax">off</span><span class="plain-syntax"> &gt;= </span><span class="identifier-syntax">MStack_Frame_Extent</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"Variable stack offset wrong: "</span><span class="plain-syntax">, </span><span class="identifier-syntax">id</span><span class="plain-syntax">, </span><span class="string-syntax">"/"</span><span class="plain-syntax">, </span><span class="identifier-syntax">off</span><span class="plain-syntax">, </span><span class="string-syntax">" at "</span><span class="plain-syntax">, </span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="string-syntax">"^"</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax">+</span><span class="identifier-syntax">off</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP7"></a><b>&#167;7. Access to Nonexistent Variables. </b>A long-standing point where I7 is not as strict in type-checking as it might
be occurs when checking rule preambles like "Before going to a dead end...".
Such a preamble must be checked whatever the current action is &mdash; in many
cases, it will not be a going action at all; which means that "room gone to",
a value implied by the "to" clause, will not exist. If the type-checking
were stricter, it would be a nuisance for authors, and instead we relax a
little by accessing such variables using a more forgiving routine. Here,
if a variable does not exist, we return 0 to mean that it can be read at
M-stack position 0: this is the sentinel word, which is not part of any
frame, and which contains 0. Thus the variable reads as if it is 0, the
default for the kind of value "object", which is the KOV for action
variables such as "room gone to".
</p>
<p class="commentary">The routine may only be used where the variable is being read, and never
where it is to be written, of course: that would corrupt the sentinel.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">MstVON</span><span class="plain-syntax"> </span><span class="identifier-syntax">id</span><span class="plain-syntax"> </span><span class="identifier-syntax">off</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Mstack_Seek_Frame</span><span class="plain-syntax">(</span><span class="identifier-syntax">id</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">pos</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="comment-syntax">word position 0 on the M-stack</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">off</span><span class="plain-syntax">&lt;0) || (</span><span class="identifier-syntax">off</span><span class="plain-syntax"> &gt;= </span><span class="identifier-syntax">MStack_Frame_Extent</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">print</span><span class="plain-syntax"> </span><span class="string-syntax">"Variable stack offset wrong: "</span><span class="plain-syntax">, </span><span class="identifier-syntax">id</span><span class="plain-syntax">, </span><span class="string-syntax">"/"</span><span class="plain-syntax">, </span><span class="identifier-syntax">off</span><span class="plain-syntax">, </span><span class="string-syntax">" at "</span><span class="plain-syntax">, </span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="string-syntax">"^"</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pos</span><span class="plain-syntax">+</span><span class="identifier-syntax">off</span><span class="plain-syntax">;</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP8"></a><b>&#167;8. Rulebook Variables. </b>Each rulebook has a slate of variables, usually empty, with ID number the
same as the rulebook's own ID number. (Rulebook IDs number upwards from 0
in order of creation in the source text.) The associated creator functions,
usually null, are stored in an array if there is no problem about memory
usage, but with a switch statement if <span class="extract"><span class="extract-syntax">MEMORY_ECONOMY</span></span> is in force; this
costs a very small amount of time, but saves 1K of readable memory.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">MStack_CreateRBVars</span><span class="plain-syntax"> </span><span class="identifier-syntax">rb</span><span class="plain-syntax"> </span><span class="identifier-syntax">cr</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">MEMORY_ECONOMY</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">cr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">MStack_GetRBVarCreator</span><span class="plain-syntax">(</span><span class="identifier-syntax">rb</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifnot</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">cr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">rulebook_var_creators</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">rb</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</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">cr</span><span class="plain-syntax">) </span><span class="identifier-syntax">Mstack_Create_Frame</span><span class="plain-syntax">(</span><span class="identifier-syntax">cr</span><span class="plain-syntax">, </span><span class="identifier-syntax">rb</span><span class="plain-syntax">);</span>
<span class="plain-syntax">];</span>
<span class="plain-syntax">[ </span><span class="identifier-syntax">MStack_DestroyRBVars</span><span class="plain-syntax"> </span><span class="identifier-syntax">rb</span><span class="plain-syntax"> </span><span class="identifier-syntax">cr</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">MEMORY_ECONOMY</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">cr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">MStack_GetRBVarCreator</span><span class="plain-syntax">(</span><span class="identifier-syntax">rb</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifnot</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">cr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">rulebook_var_creators</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">rb</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</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">cr</span><span class="plain-syntax">) </span><span class="identifier-syntax">Mstack_Destroy_Frame</span><span class="plain-syntax">(</span><span class="identifier-syntax">cr</span><span class="plain-syntax">, </span><span class="identifier-syntax">rb</span><span class="plain-syntax">);</span>
<span class="plain-syntax">];</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9"></a><b>&#167;9. Activity Variables. </b>Exactly the same goes for activity variables except that here the ID number
is \(10000+N\), where \(N\) is the allocation ID of the activity. (This would
fail if there were more than 10,000 rulebooks, but this is very difficult
to see happening.)
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">[ </span><span class="identifier-syntax">MStack_CreateAVVars</span><span class="plain-syntax"> </span><span class="identifier-syntax">av</span><span class="plain-syntax"> </span><span class="identifier-syntax">cr</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">cr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">activity_var_creators</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">av</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">cr</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="plain-syntax"> </span><span class="identifier-syntax">Mstack_Create_Frame</span><span class="plain-syntax">(</span><span class="identifier-syntax">cr</span><span class="plain-syntax">, </span><span class="identifier-syntax">av</span><span class="plain-syntax"> + </span><span class="constant-syntax">10000</span><span class="plain-syntax">);</span>
<span class="plain-syntax">];</span>
<span class="plain-syntax">[ </span><span class="identifier-syntax">MStack_DestroyAVVars</span><span class="plain-syntax"> </span><span class="identifier-syntax">av</span><span class="plain-syntax"> </span><span class="identifier-syntax">cr</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">cr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">activity_var_creators</span><span class="plain-syntax">--&gt;</span><span class="identifier-syntax">av</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">cr</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="plain-syntax"> </span><span class="identifier-syntax">Mstack_Destroy_Frame</span><span class="plain-syntax">(</span><span class="identifier-syntax">cr</span><span class="plain-syntax">, </span><span class="identifier-syntax">av</span><span class="plain-syntax"> + </span><span class="constant-syntax">10000</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="S-tbl.html">&#10094;</a></li><li class="progresssection"><a href="S-dfn.html">dfn</a></li><li class="progresssection"><a href="S-utl.html">utl</a></li><li class="progresssection"><a href="S-gll.html">gll</a></li><li class="progresssection"><a href="S-zmc.html">zmc</a></li><li class="progresssection"><a href="S-prg.html">prg</a></li><li class="progresssection"><a href="S-mth.html">mth</a></li><li class="progresssection"><a href="S-fl.html">fl</a></li><li class="progresssection"><a href="S-srt.html">srt</a></li><li class="progresssection"><a href="S-tbl.html">tbl</a></li><li class="progresscurrent">mst</li><li class="progresssection"><a href="S-rlb.html">rlb</a></li><li class="progresssection"><a href="S-flx.html">flx</a></li><li class="progresssection"><a href="S-blc.html">blc</a></li><li class="progresssection"><a href="S-txt.html">txt</a></li><li class="progresssection"><a href="S-unc.html">unc</a></li><li class="progresssection"><a href="S-chr.html">chr</a></li><li class="progresssection"><a href="S-rgx.html">rgx</a></li><li class="progresssection"><a href="S-lst.html">lst</a></li><li class="progresssection"><a href="S-cmb.html">cmb</a></li><li class="progresssection"><a href="S-rlt.html">rlt</a></li><li class="progresssection"><a href="S-rlt2.html">rlt2</a></li><li class="progresssection"><a href="S-rtp.html">rtp</a></li><li class="progressnext"><a href="S-rlb.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>