mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 10:04:21 +03:00
442 lines
45 KiB
HTML
442 lines
45 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>Phrase Blocks</title>
|
|
<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="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
|
|
</head>
|
|
<body>
|
|
<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>Compiler Webs</h2><ul>
|
|
<li><a href="../inbuild/index.html">inbuild</a></li>
|
|
<li><a href="../inform7/index.html">inform7</a></li>
|
|
<li><a href="../inter/index.html">inter</a></li>
|
|
</ul><h2>Inbuild Modules</h2><ul>
|
|
<li><a href="../supervisor-module/index.html">supervisor</a></li>
|
|
</ul><h2>Inform7 Modules</h2><ul>
|
|
<li><a href="index.html"><span class="selectedlink">core</span></a></li>
|
|
<li><a href="../inflections-module/index.html">inflections</a></li>
|
|
<li><a href="../linguistics-module/index.html">linguistics</a></li>
|
|
<li><a href="../kinds-module/index.html">kinds</a></li>
|
|
<li><a href="../if-module/index.html">if</a></li>
|
|
<li><a href="../multimedia-module/index.html">multimedia</a></li>
|
|
<li><a href="../problems-module/index.html">problems</a></li>
|
|
<li><a href="../index-module/index.html">index</a></li>
|
|
</ul><h2>Inter Modules</h2><ul>
|
|
<li><a href="../bytecode-module/index.html">bytecode</a></li>
|
|
<li><a href="../building-module/index.html">building</a></li>
|
|
<li><a href="../codegen-module/index.html">codegen</a></li>
|
|
</ul><h2>Shared Modules</h2><ul>
|
|
<li><a href="../arch-module/index.html">arch</a></li>
|
|
<li><a href="../syntax-module/index.html">syntax</a></li>
|
|
<li><a href="../words-module/index.html">words</a></li>
|
|
<li><a href="../html-module/index.html">html</a></li>
|
|
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
|
|
|
|
</ul>
|
|
</nav>
|
|
<main role="main">
|
|
|
|
<!--Weave of 'Phrase Blocks' generated by 7-->
|
|
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../compiler.html">Inform7 Modules</a></li><li><a href="index.html">core</a></li><li><a href="index.html#24">Chapter 24: Compilation Context</a></li><li><b>Phrase Blocks</b></li></ul><p class="purpose">Blocks of code are used to give conditionals and loops greater scope, as in more traditional programming languages.</p>
|
|
|
|
<ul class="toc"><li><a href="24-pb.html#SP1">§1. Definitions</a></li><li><a href="24-pb.html#SP3">§3. Pushing, popping</a></li><li><a href="24-pb.html#SP8">§8. Activation and deactivation</a></li><li><a href="24-pb.html#SP10">§10. The life of a block</a></li><li><a href="24-pb.html#SP15">§15. Bodies</a></li><li><a href="24-pb.html#SP17">§17. Breakage</a></li><li><a href="24-pb.html#SP18">§18. Blocks and scope</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>During code compilation, we must keep track of statement blocks: those
|
|
forming the body of "if", "while" or "repeat". The phrase as a whole does
|
|
not count as a block as such, unlike in C; and, again unlike in C, an
|
|
"if... otherwise..." invocation, where there are multiple phrases in both
|
|
"..." parts, counts as a single block with what we call a "division" in —
|
|
not as two different blocks.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">In principle, this information belongs to the current stack frame, since
|
|
it's within the context of a stack frame that code is compiled. But it
|
|
would be wasteful to store arrays for statement blocks inside every stack
|
|
frame structure, because in practice we only compile within one stack
|
|
frame at a time, and we finish each before beginning the next. So we
|
|
store the block stack in the only instance of a private structure.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">MAX_BLOCK_NESTING</span><span class="plain"> </span><span class="constant">50</span><span class="plain"> </span><span class="comment"> which frankly seems plenty</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">block_stack</span><span class="plain"> {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pb_sp</span><span class="plain">; </span><span class="comment"> stack pointer for the block stack which follows:</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">phrase_block</span><span class="plain"> </span><span class="identifier">pb_stack</span><span class="plain">[</span><span class="constant">MAX_BLOCK_NESTING</span><span class="plain">+1];</span>
|
|
<span class="plain">} </span><span class="reserved">block_stack</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">phrase_block</span><span class="plain"> {</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">from_structure</span><span class="plain">; </span><span class="comment"> e.g., "if" or "while"</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">block_location</span><span class="plain">; </span><span class="comment"> where block begins</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">switch_val</span><span class="plain">; </span><span class="comment"> for a switch statement</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">inter_schema</span><span class="plain"> *</span><span class="identifier">tail_schema</span><span class="plain">; </span><span class="comment"> code to add when the block closes</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">csi_state</span><span class="plain"> </span><span class="identifier">compilation_state</span><span class="plain">; </span><span class="comment"> details needed to compile that code</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">label_following</span><span class="plain">; </span><span class="comment"> or -1 if none is used</span>
|
|
<span class="plain">} </span><span class="reserved">phrase_block</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure block_stack is private to this section.</p>
|
|
|
|
<p class="endnote">The structure phrase_block is private to this section.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. Pushing, popping. </b>We need to keep track of two positions on the stack: the top (filled) entry,
|
|
and, sometimes, the one above it.
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">block_stack</span><span class="plain"> </span><span class="identifier">current_block_stack</span><span class="plain">;</span>
|
|
<span class="reserved">phrase_block</span><span class="plain"> *</span><span class="identifier">block_being_compiled</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="comment"> the one being compiled, if any</span>
|
|
<span class="reserved">phrase_block</span><span class="plain"> *</span><span class="identifier">block_being_opened</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="comment"> the one about to open, if any</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. </b>We need to be careful changing any of these without keeping the others in
|
|
line, so the only code allowed to change them is here:
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::empty_stack<button class="popup" onclick="togglePopup('usagePopup1920')">...<span class="popuptext" id="usagePopup1920">Usage of <b>Frames::Blocks::empty_stack</b>:<br><a href="24-pb.html#SP8">§8</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
|
|
<span class="identifier">block_being_compiled</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">block_being_opened</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§5. </b>Pushing happens in two stages. First we make a pointer to what will be, but
|
|
is not yet, the top of the stack:
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::prepush_stack<button class="popup" onclick="togglePopup('usagePopup1921')">...<span class="popuptext" id="usagePopup1921">Usage of <b>Frames::Blocks::prepush_stack</b>:<br><a href="24-pb.html#SP10">§10</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="identifier">block_being_opened</span><span class="plain"> = &(</span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_stack</span><span class="plain">[</span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain">]);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§6. </b>And then we actually increment the stack pointer:
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::push_stack<button class="popup" onclick="togglePopup('usagePopup1922')">...<span class="popuptext" id="usagePopup1922">Usage of <b>Frames::Blocks::push_stack</b>:<br><a href="24-pb.html#SP12">§12</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain">++;</span>
|
|
<span class="identifier">block_being_compiled</span><span class="plain"> = </span><span class="identifier">block_being_opened</span><span class="plain">;</span>
|
|
<span class="identifier">block_being_opened</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§7. </b>Popping is easier:
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::pop_stack<button class="popup" onclick="togglePopup('usagePopup1923')">...<span class="popuptext" id="usagePopup1923">Usage of <b>Frames::Blocks::pop_stack</b>:<br><a href="24-pb.html#SP9">§9</a>, <a href="24-pb.html#SP10">§10</a>, <a href="24-pb.html#SP14">§14</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain">--;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain"> > </span><span class="constant">0</span><span class="plain">)</span>
|
|
<span class="identifier">block_being_compiled</span><span class="plain"> = &(</span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_stack</span><span class="plain">[</span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain"> - </span><span class="constant">1</span><span class="plain">]);</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">block_being_compiled</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">block_being_opened</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="comment"> which should be true anyway</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8"></a><b>§8. Activation and deactivation. </b>If a phrase needs code blocks, Inform should call this when compilation
|
|
begins:
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::begin_code_blocks<button class="popup" onclick="togglePopup('usagePopup1924')">...<span class="popuptext" id="usagePopup1924">Usage of <b>Frames::Blocks::begin_code_blocks</b>:<br>Routines - <a href="26-rt.html#SP3">§3</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="24-sf.html#SP8">Frames::current_stack_frame</a></span><span class="plain">() == </span><span class="identifier">NULL</span><span class="plain">)</span>
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to use blocks outside stack frame"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">block_being_compiled</span><span class="plain">)</span>
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to begin block stack already in use"</span><span class="plain">);</span>
|
|
<span class="functiontext"><a href="24-pb.html#SP4">Frames::Blocks::empty_stack</a></span><span class="plain">(); </span><span class="comment"> which it should be anyway</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">LOCAL_VARIABLES</span><span class="plain">, </span><span class="string">"Block stack now active\n"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§9. </b>And this when it ends. The stack should in fact be empty, but just in
|
|
case we are recovering from some kind of problem, we'll empty anything
|
|
somehow left on it.
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::end_code_blocks<button class="popup" onclick="togglePopup('usagePopup1925')">...<span class="popuptext" id="usagePopup1925">Usage of <b>Frames::Blocks::end_code_blocks</b>:<br>Routines - <a href="26-rt.html#SP4">§4</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">block_being_compiled</span><span class="plain">) {</span>
|
|
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">block_being_compiled</span><span class="plain">-></span><span class="element">block_location</span><span class="plain">;</span>
|
|
<span class="functiontext"><a href="24-pb.html#SP7">Frames::Blocks::pop_stack</a></span><span class="plain">();</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">block_being_compiled</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">LOCAL_VARIABLES</span><span class="plain">, </span><span class="string">"Block stack now inactive\n"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§10. The life of a block. </b>So now let's follow what happens when a block is being compiled. Suppose
|
|
we have:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>repeat through the Table of Odds:</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">When Inform begins to compile this invocation, it observes that the phrase
|
|
being invoked is followed by a code block, and calls the following routine
|
|
to warn us. (That doesn't mean the block is opening yet: the setup code
|
|
for the loop hasn't been compiled yet.)
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::beginning_block_phrase<button class="popup" onclick="togglePopup('usagePopup1926')">...<span class="popuptext" id="usagePopup1926">Usage of <b>Frames::Blocks::beginning_block_phrase</b>:<br>Compile Phrases - <a href="25-cp.html#SP5">§5</a></span></button></span><span class="plain">(</span><span class="identifier">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">csp</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain"> == </span><span class="constant">MAX_BLOCK_NESTING</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"block stack overflow"</span><span class="plain">);</span>
|
|
<span class="functiontext"><a href="24-pb.html#SP7">Frames::Blocks::pop_stack</a></span><span class="plain">();</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext"><a href="24-pb.html#SP5">Frames::Blocks::prepush_stack</a></span><span class="plain">();</span>
|
|
<<span class="cwebmacro">Construct the next phrase block</span> <span class="cwebmacronumber">10.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10_1"></a><b>§10.1. </b>In the case of a repeat through a Table, we need to create two loop
|
|
variables. In addition to those, the loop we're compiling will inevitably
|
|
change the two row selection variables (always called <code class="display"><span class="extract">ct_0</span></code> and <code class="display"><span class="extract">ct_1</span></code>),
|
|
so we need to protect their contents; we push them onto the stack before
|
|
the loop begins, and pull them again when it finishes.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Construct the next phrase block</span> <span class="cwebmacronumber">10.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">block_being_opened</span><span class="plain">-></span><span class="element">switch_val</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">block_being_opened</span><span class="plain">-></span><span class="element">tail_schema</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">block_being_opened</span><span class="plain">-></span><span class="element">block_location</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
|
|
<span class="identifier">block_being_opened</span><span class="plain">-></span><span class="element">from_structure</span><span class="plain"> = </span><span class="identifier">csp</span><span class="plain">;</span>
|
|
<span class="identifier">block_being_opened</span><span class="plain">-></span><span class="element">label_following</span><span class="plain"> = -1;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="24-pb.html#SP10">§10</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§11. </b>Slightly later on, we know these:
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::supply_val_and_stream<button class="popup" onclick="togglePopup('usagePopup1927')">...<span class="popuptext" id="usagePopup1927">Usage of <b>Frames::Blocks::supply_val_and_stream</b>:<br>Compile Invocations Inline - <a href="25-cii.html#SP1_4">§1.4</a></span></button></span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">val</span><span class="plain">, </span><span class="identifier">inter_schema</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain">, </span><span class="reserved">csi_state</span><span class="plain"> </span><span class="identifier">CSIS</span><span class="plain">) {</span>
|
|
<span class="identifier">block_being_opened</span><span class="plain">-></span><span class="element">switch_val</span><span class="plain"> = </span><span class="identifier">val</span><span class="plain">;</span>
|
|
<span class="identifier">block_being_opened</span><span class="plain">-></span><span class="element">tail_schema</span><span class="plain"> = </span><span class="identifier">I</span><span class="plain">;</span>
|
|
<span class="identifier">block_being_opened</span><span class="plain">-></span><span class="element">compilation_state</span><span class="plain"> = </span><span class="identifier">CSIS</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12"></a><b>§12. </b>At this next stage, the preliminary code for the loop (if it's a loop)
|
|
has been compiled, and we're ready to open the actual block:
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::open_code_block<button class="popup" onclick="togglePopup('usagePopup1928')">...<span class="popuptext" id="usagePopup1928">Usage of <b>Frames::Blocks::open_code_block</b>:<br>Compile Phrases - <a href="25-cp.html#SP5_3_4">§5.3.4</a>, <a href="25-cp.html#SP5_3_5">§5.3.5</a>, <a href="25-cp.html#SP5_4_5">§5.4.5</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain"> != </span><span class="constant">MAX_BLOCK_NESTING</span><span class="plain">) </span><span class="functiontext"><a href="24-pb.html#SP6">Frames::Blocks::push_stack</a></span><span class="plain">();</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">LOCAL_VARIABLES</span><span class="plain">, </span><span class="string">"Start of block level %d\n"</span><span class="plain">, </span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13"></a><b>§13. </b>A division in a code block occurs at the "otherwise" point of an "if",
|
|
for example, but also for cases in a switch-style "if", so there can be
|
|
many of them.
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::divide_code_block<button class="popup" onclick="togglePopup('usagePopup1929')">...<span class="popuptext" id="usagePopup1929">Usage of <b>Frames::Blocks::divide_code_block</b>:<br>Compile Phrases - <a href="25-cp.html#SP5_3_4">§5.3.4</a>, <a href="25-cp.html#SP5_3_5">§5.3.5</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">block_being_compiled</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">; </span><span class="comment"> for problem recovery only</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">LOCAL_VARIABLES</span><span class="plain">, </span><span class="string">"Division in block level %d\n"</span><span class="plain">, </span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain">);</span>
|
|
<span class="functiontext"><a href="24-lv.html#SP41">LocalVariables::end_scope</a></span><span class="plain">(</span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14"></a><b>§14. </b>Whatever we pushed earlier, we now pull:
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::close_code_block<button class="popup" onclick="togglePopup('usagePopup1930')">...<span class="popuptext" id="usagePopup1930">Usage of <b>Frames::Blocks::close_code_block</b>:<br>Compile Phrases - <a href="25-cp.html#SP5_3_4">§5.3.4</a>, <a href="25-cp.html#SP5_3_5">§5.3.5</a>, <a href="25-cp.html#SP5_4_5">§5.4.5</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">block_being_compiled</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">; </span><span class="comment"> for problem recovery only</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">block_being_compiled</span><span class="plain">-></span><span class="element">label_following</span><span class="plain"> >= </span><span class="constant">0</span><span class="plain">) {</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">TL</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">TL</span><span class="plain">, </span><span class="string">".loop_break_%d"</span><span class="plain">, </span><span class="identifier">block_being_compiled</span><span class="plain">-></span><span class="element">label_following</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::place_label</span><span class="plain">(</span><span class="functiontext"><a href="27-em.html#SP2">Emit::tree</a></span><span class="plain">(), </span><span class="identifier">Produce::reserve_label</span><span class="plain">(</span><span class="functiontext"><a href="27-em.html#SP2">Emit::tree</a></span><span class="plain">(), </span><span class="identifier">TL</span><span class="plain">));</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">TL</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">LOCAL_VARIABLES</span><span class="plain">, </span><span class="string">"End of block level %d\n"</span><span class="plain">, </span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain">);</span>
|
|
<span class="functiontext"><a href="24-lv.html#SP41">LocalVariables::end_scope</a></span><span class="plain">(</span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">block_being_compiled</span><span class="plain">-></span><span class="element">tail_schema</span><span class="plain">) {</span>
|
|
<span class="identifier">value_holster</span><span class="plain"> </span><span class="identifier">VH</span><span class="plain"> = </span><span class="identifier">Holsters::new</span><span class="plain">(</span><span class="identifier">INTER_VOID_VHMODE</span><span class="plain">);</span>
|
|
<span class="functiontext"><a href="25-cii.html#SP2">Invocations::Inline::csi_inline_inner</a></span><span class="plain">(&</span><span class="identifier">VH</span><span class="plain">,</span>
|
|
<span class="identifier">block_being_compiled</span><span class="plain">-></span><span class="element">tail_schema</span><span class="plain">, &(</span><span class="identifier">block_being_compiled</span><span class="plain">-></span><span class="element">compilation_state</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext"><a href="24-pb.html#SP7">Frames::Blocks::pop_stack</a></span><span class="plain">();</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15"></a><b>§15. Bodies. </b>Are we in the body of a loop, perhaps indirectly?
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::inside_a_loop_body<button class="popup" onclick="togglePopup('usagePopup1931')">...<span class="popuptext" id="usagePopup1931">Usage of <b>Frames::Blocks::inside_a_loop_body</b>:<br>Dash - <a href="14-ds2.html#SP11_9_1_1_9">§11.9.1.1.9</a><br>Compile Invocations Inline - <a href="25-cii.html#SP3_5_3">§3.5.3</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> = </span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain">-1; </span><span class="identifier">i</span><span class="plain"> >= </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">--)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ControlStructures::is_a_loop</span><span class="plain">(</span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_stack</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">].</span><span class="element">from_structure</span><span class="plain">))</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16"></a><b>§16. </b>What can we find about the block we are most immediately in? Note that
|
|
if there is no current block stack, we behave as if the block stack were
|
|
empty, but (as long as nobody tries to open or close any blocks) no
|
|
internal errors are issued. This allows the typechecker to run even when
|
|
there is no current block stack, which is important when typechecking an
|
|
expression whose evaluation requires the use of a phrase.
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::current_block_level<button class="popup" onclick="togglePopup('usagePopup1932')">...<span class="popuptext" id="usagePopup1932">Usage of <b>Frames::Blocks::current_block_level</b>:<br>Local Variables - <a href="24-lv.html#SP42">§42</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="functiontext">Frames::Blocks::name_of_current_block<button class="popup" onclick="togglePopup('usagePopup1933')">...<span class="popuptext" id="usagePopup1933">Usage of <b>Frames::Blocks::name_of_current_block</b>:<br>Dash - <a href="14-ds2.html#SP11_9_1_1_9">§11.9.1.1.9</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">block_being_compiled</span><span class="plain"> == </span><span class="identifier">NULL</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="reserved">return</span><span class="plain"> </span><span class="identifier">ControlStructures::incipit</span><span class="plain">(</span><span class="identifier">block_being_compiled</span><span class="plain">-></span><span class="element">from_structure</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Frames::Blocks::start_of_current_block<button class="popup" onclick="togglePopup('usagePopup1934')">...<span class="popuptext" id="usagePopup1934">Usage of <b>Frames::Blocks::start_of_current_block</b>:<br>none</span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">block_being_compiled</span><span class="plain"> == </span><span class="identifier">NULL</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="reserved">return</span><span class="plain"> </span><span class="identifier">block_being_compiled</span><span class="plain">-></span><span class="element">block_location</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Frames::Blocks::switch_value<button class="popup" onclick="togglePopup('usagePopup1935')">...<span class="popuptext" id="usagePopup1935">Usage of <b>Frames::Blocks::switch_value</b>:<br>Compile Phrases - <a href="25-cp.html#SP5_3_5">§5.3.5</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">block_being_compiled</span><span class="plain"> == </span><span class="identifier">NULL</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="reserved">return</span><span class="plain"> </span><span class="identifier">block_being_compiled</span><span class="plain">-></span><span class="element">switch_val</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP17"></a><b>§17. Breakage. </b>It might seem reasonable to compile a breaking-out of the current loop
|
|
into an I6 "break" statement, but the semantics of I6 "break" are subtly
|
|
different: as in C, they will break out of a switch case in preference
|
|
to a wider loop, whereas in I7 we want always to exit the innermost loop.
|
|
So we do this by hand, jumping to a label placed just after the loop ends.
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">unique_breakage_count</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::emit_break<button class="popup" onclick="togglePopup('usagePopup1936')">...<span class="popuptext" id="usagePopup1936">Usage of <b>Frames::Blocks::emit_break</b>:<br>Compile Invocations Inline - <a href="25-cii.html#SP3_7">§3.7</a></span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</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"> = </span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="identifier">pb_sp</span><span class="plain">-1; </span><span class="identifier">i</span><span class="plain"> >= </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">--)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ControlStructures::permits_break</span><span class="plain">(</span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_stack</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">].</span><span class="element">from_structure</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_stack</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">].</span><span class="element">label_following</span><span class="plain"> == -1)</span>
|
|
<span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_stack</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">].</span><span class="element">label_following</span><span class="plain"> =</span>
|
|
<span class="identifier">unique_breakage_count</span><span class="plain">++;</span>
|
|
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="functiontext"><a href="27-em.html#SP2">Emit::tree</a></span><span class="plain">(), </span><span class="identifier">JUMP_BIP</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="functiontext"><a href="27-em.html#SP2">Emit::tree</a></span><span class="plain">());</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">TL</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">TL</span><span class="plain">, </span><span class="string">".loop_break_%d"</span><span class="plain">, </span><span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_stack</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">].</span><span class="element">label_following</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::lab</span><span class="plain">(</span><span class="functiontext"><a href="27-em.html#SP2">Emit::tree</a></span><span class="plain">(), </span><span class="identifier">Produce::reserve_label</span><span class="plain">(</span><span class="functiontext"><a href="27-em.html#SP2">Emit::tree</a></span><span class="plain">(), </span><span class="identifier">TL</span><span class="plain">));</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">TL</span><span class="plain">);</span>
|
|
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="functiontext"><a href="27-em.html#SP2">Emit::tree</a></span><span class="plain">());</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"not inside a loop block"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18"></a><b>§18. Blocks and scope. </b>When "let" creates something, this is called:
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::set_variable_scope<button class="popup" onclick="togglePopup('usagePopup1937')">...<span class="popuptext" id="usagePopup1937">Usage of <b>Frames::Blocks::set_variable_scope</b>:<br>Compile Invocations Inline - <a href="25-cii.html#SP1_2_1">§1.2.1</a></span></button></span><span class="plain">(</span><span class="reserved">local_variable</span><span class="plain"> *</span><span class="identifier">lvar</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="24-sf.html#SP8">Frames::current_stack_frame</a></span><span class="plain">())</span>
|
|
<span class="functiontext"><a href="24-lv.html#SP40">LocalVariables::set_scope_to</a></span><span class="plain">(</span><span class="identifier">lvar</span><span class="plain">,</span>
|
|
<span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19"></a><b>§19. </b>But when loops create something, this is called instead, because the loop
|
|
counter exists in one scope level inside the one holding the loop header
|
|
phrase:
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Frames::Blocks::set_scope_to_block_about_to_open<button class="popup" onclick="togglePopup('usagePopup1938')">...<span class="popuptext" id="usagePopup1938">Usage of <b>Frames::Blocks::set_scope_to_block_about_to_open</b>:<br>Deciding to Defer - <a href="12-dtd.html#SP23">§23</a>, <a href="12-dtd.html#SP27">§27</a><br>Compile Invocations Inline - <a href="25-cii.html#SP1_2_1">§1.2.1</a>, <a href="25-cii.html#SP3_5_1_1">§3.5.1.1</a></span></button></span><span class="plain">(</span><span class="reserved">local_variable</span><span class="plain"> *</span><span class="identifier">lvar</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="24-sf.html#SP8">Frames::current_stack_frame</a></span><span class="plain">())</span>
|
|
<span class="functiontext"><a href="24-lv.html#SP40">LocalVariables::set_scope_to</a></span><span class="plain">(</span><span class="identifier">lvar</span><span class="plain">,</span>
|
|
<span class="identifier">current_block_stack</span><span class="plain">.</span><span class="element">pb_sp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="24-lv.html">Back to 'Local Variables'</a></li><li><a href="24-sf.html">Continue with 'Stack Frames'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
<script>
|
|
function togglePopup(material_id) {
|
|
var popup = document.getElementById(material_id);
|
|
popup.classList.toggle("show");
|
|
}
|
|
</script>
|
|
|
|
<link href="Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
</main>
|
|
</body>
|
|
</html>
|
|
|