1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-16 22:14:23 +03:00
inform7/docs/core-module/27-pt.html

105 lines
9 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>27/pc</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<!--Weave of '27/pt' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">core</a></li><li><a href="index.html#27">Chapter 27: Bridge to Inter Module</a></li><li><b>Package Types</b></li></ul><p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Package types. </b>Inter code is a nested hierarchy of "packages", which can be assigned "types".
Inter requires two types to exist, <code class="display"><span class="extract">_plain</span></code> and <code class="display"><span class="extract">_code</span></code>, and leaves the rest
to the user (i.e., us) to define as we see fit. In fact Inform generates
packages of slightly over 50 different types.
</p>
<p class="inwebparagraph">At run time, package types are pointers to the inter symbol which defined them,
but this is not a convenient way to refer to them in the Inform source code.
Instead we use the following dictionary in order to be able to refer to them
by name. So, for example, <code class="display"><span class="extract">PackageTypes::get(I"_cake")</span></code> returns the package
type for <code class="display"><span class="extract">_cake</span></code>, declaring it if it doesn't already exist.
</p>
<pre class="display">
<span class="identifier">dictionary</span><span class="plain"> *</span><span class="identifier">ptypes_indexed_by_name</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ptypes_created</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="functiontext">PackageTypes::get</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ptypes_created</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">ptypes_created</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">ptypes_indexed_by_name</span><span class="plain"> = </span><span class="identifier">Dictionaries::new</span><span class="plain">(512, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Dictionaries::find</span><span class="plain">(</span><span class="identifier">ptypes_indexed_by_name</span><span class="plain">, </span><span class="identifier">name</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> (</span><span class="identifier">inter_symbol</span><span class="plain"> *) </span><span class="identifier">Dictionaries::read_value</span><span class="plain">(</span><span class="identifier">ptypes_indexed_by_name</span><span class="plain">, </span><span class="identifier">name</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">enclose</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Decide if this package type is to be enclosing</span> <span class="cwebmacronumber">1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">new_ptype</span><span class="plain"> = </span><span class="functiontext">Emit::packagetype</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">enclose</span><span class="plain">);</span>
<span class="identifier">Dictionaries::create</span><span class="plain">(</span><span class="identifier">ptypes_indexed_by_name</span><span class="plain">, </span><span class="identifier">name</span><span class="plain">);</span>
<span class="identifier">Dictionaries::write_value</span><span class="plain">(</span><span class="identifier">ptypes_indexed_by_name</span><span class="plain">, </span><span class="identifier">name</span><span class="plain">, (</span><span class="reserved">void</span><span class="plain"> *) </span><span class="identifier">new_ptype</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">new_ptype</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PackageTypes::get is used in <a href="#SP2">&#167;2</a>, 27/hr (<a href="27-hr.html#SP5">&#167;5</a>), 27/hl (<a href="27-hl.html#SP1">&#167;1</a>, <a href="27-hl.html#SP2">&#167;2</a>), 27/pc (<a href="27-pc.html#SP10">&#167;10</a>, <a href="27-pc.html#SP10_1">&#167;10.1</a>, <a href="27-pc.html#SP11">&#167;11</a>), 27/ei (<a href="27-ei.html#SP2">&#167;2</a>).</p>
<p class="inwebparagraph"><a id="SP1_1"></a><b>&#167;1.1. </b>Most package types are "enclosing". Suppose that Inform is compiling
something to go into the package, but finds that it needs to compile something
else in order to do so &mdash; for example, it's compiling code to set a variable
to be equal to a literal piece of text, which must itself be compiled as a
small array. Where does Inform put that array? If the current package is
"enclosing", then Inform puts it into the package itself; and if not, then
into the package holding the current package, if that in turn is "enclosing";
and so on.
</p>
<p class="inwebparagraph">It seems tidy to make all packages enclosing, and in fact (after much
experiment) Inform nearly does that. But <code class="display"><span class="extract">_code</span></code> packages have to be an
exception, because the Inter specification doesn't allow constants (and
therefore arrays) to be defined inside <code class="display"><span class="extract">_code</span></code> packages.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Decide if this package type is to be enclosing</span> <span class="cwebmacronumber">1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"_code"</span><span class="plain">)) </span><span class="identifier">enclose</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>Dictionary lookups by name are fast, but not instant, and the one package
type which we need frequently is <code class="display"><span class="extract">_function</span></code>, so we cache that one:
</p>
<pre class="display">
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">function_ptype</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="functiontext">PackageTypes::function</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">function_ptype</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">function_ptype</span><span class="plain"> = </span><span class="functiontext">PackageTypes::get</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"_function"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">function_ptype</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PackageTypes::function is used in 27/pc (<a href="27-pc.html#SP11">&#167;11</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="27-pc.html">Back to 'Packaging'</a></li><li><a href="27-in.html">Continue with 'Inter Namespace'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>