1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 16:44:21 +03:00
inform7/docs/core-module/27-cm.html
2020-04-07 01:06:09 +01:00

267 lines
26 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>27/hr</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="../webs.html">Sources</a></h1>
<ul>
<li><a href="../compiler.html"><b>compiler tools</b></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="../inbuild-module/index.html">inbuild</a></li>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../syntax-module/index.html">syntax</a></li>
<li><a href="../html-module/index.html">html</a></li>
</ul>
<h2>Inform7 Modules</h2>
<ul>
<li><a href="../core-module/index.html">core</a></li>
<li><a href="../problems-module/index.html">problems</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="../index-module/index.html">index</a></li>
</ul>
<h2>Inter Modules</h2>
<ul>
<li><a href="../inter-module/index.html">inter</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../codegen-module/index.html">codegen</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '27/cm' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="../compiler.html">Compiler Modules</a></li><li><a href="index.html">core</a></li><li><a href="index.html#27">Chapter 27: Bridge to Inter Module</a></li><li><b>Compilation Modules</b></li></ul><p class="purpose">To identify which parts of the source text come from which source (the main source text, the Standard Rules, or another extension).</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Compilation modules</a></li><li><a href="#SP6">&#167;6. Current module</a></li><li><a href="#SP7">&#167;7. Relating to Inter</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Compilation modules. </b>Inform is a language in which it is semantically relevant which source file the
source text is coming from: unlike, say, C, where <code class="display"><span class="extract">#include</span></code> allows files to include
each other in arbitrary ways. In Inform, all source text comes from one of the
following places:
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(a) The main source text, as shown in the Source panel of the UI app;
</li><li>(b) An extension file, including the Standard Rules extension;
</li><li>(c) Invented text created by the compiler itself.
</li></ul>
<p class="inwebparagraph">The Inter hierarchy also splits, with named modules representing each possibility
in (a) or (b) above. This section of code determines to which module any new
definition (of, say, a property or kind) belongs.
</p>
<pre class="display">
<span class="identifier">compilation_module</span><span class="plain"> *</span><span class="identifier">source_text_module</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="comment">the one for the main text</span>
<span class="identifier">compilation_module</span><span class="plain"> *</span><span class="identifier">SR_module</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="comment">the one for the Standard Rules</span>
<span class="identifier">compilation_module</span><span class="plain"> *</span><span class="functiontext">Modules::SR</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">SR_module</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Modules::SR is used in 21/rl (<a href="21-rl.html#SP26">&#167;26</a>).</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>We find these by performing a traverse of the parse tree, and looking for
level-0 headings, which are the nodes from which these blocks of source text hang:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Modules::traverse_to_define</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">ParseTree::traverse</span><span class="plain">(</span><span class="functiontext">Task::syntax_tree</span><span class="plain">(), </span><span class="functiontext">Modules::look_for_cu</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Modules::look_for_cu</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) == </span><span class="identifier">HEADING_NT</span><span class="plain">) {</span>
<span class="identifier">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain"> = </span><span class="identifier">Headings::from_node</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">h</span><span class="plain">) &amp;&amp; (</span><span class="identifier">h</span><span class="plain">-&gt;</span><span class="identifier">level</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)) </span><span class="functiontext">Modules::new</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">compilation_module</span><span class="plain"> *</span><span class="functiontext">Modules::new</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">) {</span>
<span class="identifier">source_location</span><span class="plain"> </span><span class="identifier">sl</span><span class="plain"> = </span><span class="identifier">Wordings::location</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sl</span><span class="plain">.</span><span class="identifier">file_of_origin</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">"null foo"</span><span class="plain">);</span>
<span class="identifier">inform_extension</span><span class="plain"> *</span><span class="identifier">owner</span><span class="plain"> = </span><span class="identifier">Extensions::corresponding_to</span><span class="plain">(</span>
<span class="identifier">Lexer::file_of_origin</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">))));</span>
<span class="identifier">compilation_module</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain"> = </span><span class="identifier">Packaging::new_cm</span><span class="plain">();</span>
<span class="identifier">C</span><span class="plain">-&gt;</span><span class="identifier">hanging_from</span><span class="plain"> = </span><span class="identifier">from</span><span class="plain">;</span>
<span class="identifier">ParseTree::set_module</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">);</span>
<span class="functiontext">Modules::propagate_downwards</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">pname</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Compose a name for the module package this will lead to</span> <span class="cwebmacronumber">2.1</span>&gt;<span class="plain">;</span>
<span class="identifier">C</span><span class="plain">-&gt;</span><span class="identifier">inter_presence</span><span class="plain"> = </span><span class="identifier">Packaging::get_module</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">pname</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">pname</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">owner</span><span class="plain">) {</span>
<span class="functiontext">Hierarchy::markup</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">-&gt;</span><span class="identifier">inter_presence</span><span class="plain">-&gt;</span><span class="identifier">the_package</span><span class="plain">, </span><span class="constant">EXT_AUTHOR_HMD</span><span class="plain">, </span><span class="identifier">owner</span><span class="plain">-&gt;</span><span class="identifier">as_copy</span><span class="plain">-&gt;</span><span class="identifier">edition</span><span class="plain">-&gt;</span><span class="identifier">work</span><span class="plain">-&gt;</span><span class="identifier">raw_author_name</span><span class="plain">);</span>
<span class="functiontext">Hierarchy::markup</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">-&gt;</span><span class="identifier">inter_presence</span><span class="plain">-&gt;</span><span class="identifier">the_package</span><span class="plain">, </span><span class="constant">EXT_TITLE_HMD</span><span class="plain">, </span><span class="identifier">owner</span><span class="plain">-&gt;</span><span class="identifier">as_copy</span><span class="plain">-&gt;</span><span class="identifier">edition</span><span class="plain">-&gt;</span><span class="identifier">work</span><span class="plain">-&gt;</span><span class="identifier">raw_title</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">);</span>
<span class="identifier">semantic_version_number</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="identifier">owner</span><span class="plain">-&gt;</span><span class="identifier">as_copy</span><span class="plain">-&gt;</span><span class="identifier">edition</span><span class="plain">-&gt;</span><span class="identifier">version</span><span class="plain">;</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="string">"%v"</span><span class="plain">, &amp;</span><span class="identifier">N</span><span class="plain">);</span>
<span class="functiontext">Hierarchy::markup</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">-&gt;</span><span class="identifier">inter_presence</span><span class="plain">-&gt;</span><span class="identifier">the_package</span><span class="plain">, </span><span class="constant">EXT_VERSION_HMD</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Extensions::is_standard</span><span class="plain">(</span><span class="identifier">owner</span><span class="plain">)) </span><span class="identifier">SR_module</span><span class="plain"> = </span><span class="identifier">C</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">owner</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">source_text_module</span><span class="plain"> = </span><span class="identifier">C</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>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Modules::traverse_to_define is used in 1/htc (<a href="1-htc.html#SP2_3">&#167;2.3</a>).</p>
<p class="endnote">The function Modules::look_for_cu appears nowhere else.</p>
<p class="endnote">The function Modules::new appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP2_1"></a><b>&#167;2.1. </b>Here we must find a unique name, valid as an Inter identifier: the code
compiled from the compilation module will go into a package of that name.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compose a name for the module package this will lead to</span> <span class="cwebmacronumber">2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Extensions::is_standard</span><span class="plain">(</span><span class="identifier">owner</span><span class="plain">)) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">pname</span><span class="plain">, </span><span class="string">"standard_rules"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">owner</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">pname</span><span class="plain">, </span><span class="string">"source_text"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">pname</span><span class="plain">, </span><span class="string">"%X"</span><span class="plain">, </span><span class="identifier">owner</span><span class="plain">-&gt;</span><span class="identifier">as_copy</span><span class="plain">-&gt;</span><span class="identifier">edition</span><span class="plain">-&gt;</span><span class="identifier">work</span><span class="plain">);</span>
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">pname</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">) == </span><span class="character">' '</span><span class="plain">)</span>
<span class="identifier">Str::put</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="character">'_'</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">Str::put</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">Characters::tolower</span><span class="plain">(</span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">)));</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2">&#167;2</a>.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>We are eventually going to need to be able to look at a given node in the parse
tree and say which compilation module it belongs to. If there were a fast way
to go up in the tree, that would be easy &mdash; we could simply run upward until we
reach a level-0 heading. But the node links all run downwards. Instead, we'll
"mark" nodes in the tree, annotating them with the compilation module which owns
them. This is done by "propagating downwards", as follows.
</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Modules::propagate_downwards</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">compilation_module</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">) {</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">P</span><span class="plain">) {</span>
<span class="identifier">ParseTree::set_module</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">);</span>
<span class="functiontext">Modules::propagate_downwards</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">);</span>
<span class="identifier">P</span><span class="plain"> = </span><span class="identifier">P</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Modules::propagate_downwards is used in <a href="#SP2">&#167;2</a>.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>As promised, then, given a parse node, we have to return its compilation module:
but that's now easy, as we just have to read off the annotation made above &mdash;
</p>
<pre class="display">
<span class="identifier">compilation_module</span><span class="plain"> *</span><span class="functiontext">Modules::find</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</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">ParseTree::get_module</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Modules::find is used in <a href="#SP6">&#167;6</a>, 5/nv (<a href="5-nv.html#SP16">&#167;16</a>), 6/bp (<a href="6-bp.html#SP31">&#167;31</a>), 15/pr (<a href="15-pr.html#SP5_3">&#167;5.3</a>), 19/tb (<a href="19-tb.html#SP9">&#167;9</a>), 21/rl (<a href="21-rl.html#SP26">&#167;26</a>), 22/ph (<a href="22-ph.html#SP6_8">&#167;6.8</a>), 22/tp (<a href="22-tp.html#SP7">&#167;7</a>), 27/hr (<a href="27-hr.html#SP4">&#167;4</a>).</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Current module. </b>Inform has a concept of the "current module" it's working on, much as it has
a concept of "current sentence".
</p>
<pre class="display">
<span class="identifier">compilation_module</span><span class="plain"> *</span><span class="identifier">current_CM</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">compilation_module</span><span class="plain"> *</span><span class="functiontext">Modules::current</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_CM</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Modules::set_current_to</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="identifier">current_CM</span><span class="plain"> = </span><span class="identifier">CM</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Modules::set_current</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">P</span><span class="plain">) </span><span class="identifier">current_CM</span><span class="plain"> = </span><span class="functiontext">Modules::find</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">current_CM</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="endnote">The function Modules::current is used in 9/tfa (<a href="9-tfa.html#SP7_2">&#167;7.2</a>), 15/ma (<a href="15-ma.html#SP11_3">&#167;11.3</a>), 17/ts (<a href="17-ts.html#SP5">&#167;5</a>, <a href="17-ts.html#SP11_1">&#167;11.1</a>), 22/tp (<a href="22-tp.html#SP7">&#167;7</a>), 23/ad (<a href="23-ad.html#SP5">&#167;5</a>), 26/jl (<a href="26-jl.html#SP4">&#167;4</a>).</p>
<p class="endnote">The function Modules::set_current_to is used in 9/tfa (<a href="9-tfa.html#SP7_2">&#167;7.2</a>), 17/ts (<a href="17-ts.html#SP11_1">&#167;11.1</a>), 23/ad (<a href="23-ad.html#SP5">&#167;5</a>).</p>
<p class="endnote">The function Modules::set_current is used in 9/tfa (<a href="9-tfa.html#SP7_2">&#167;7.2</a>), 23/ad (<a href="23-ad.html#SP5">&#167;5</a>), 25/cp (<a href="25-cp.html#SP3">&#167;3</a>).</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Relating to Inter. </b>Creating the necessary package, of type <code class="display"><span class="extract">_module</span></code>, is the work of the
Packaging code.
</p>
<pre class="display">
<span class="identifier">module_package</span><span class="plain"> *</span><span class="functiontext">Modules::inter_presence</span><span class="plain">(</span><span class="identifier">compilation_module</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">C</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">"no module"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">C</span><span class="plain">-&gt;</span><span class="identifier">inter_presence</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Modules::inter_presence appears nowhere else.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="27-hr.html">Back to 'Hierarchy'</a></li><li><a href="27-ei.html">Continue with 'Emitting Inter'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>