1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 16:44:21 +03:00
inform7/docs/inter/M-ip.html

424 lines
36 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Inform Primitives</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">
<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-assets/Inform.png" height=72">
</a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../indocn.html">indoc</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
<li><a href="../inrtpsn.html">inrtps</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=18> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="../../../inweb/index.html">inweb</a></li>
<li><a href="../../../intest/index.html">intest</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Inform Primitives' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="index.html">inter</a></li><li><a href="index.html#M">Manual</a></li><li><b>Inform Primitives</b></li></ul></div>
<p class="purpose">The standard set of primitive invocations used within Inform.</p>
<ul class="toc"><li><a href="M-ip.html#SP1">&#167;1. What standard means</a></li><li><a href="M-ip.html#SP2">&#167;2. Arithmetic</a></li><li><a href="M-ip.html#SP3">&#167;3. Logical operators</a></li><li><a href="M-ip.html#SP4">&#167;4. Bitwise operators</a></li><li><a href="M-ip.html#SP5">&#167;5. Numerical comparison</a></li><li><a href="M-ip.html#SP6">&#167;6. Sequential evaluation</a></li><li><a href="M-ip.html#SP7">&#167;7. Random</a></li><li><a href="M-ip.html#SP8">&#167;8. Printing</a></li><li><a href="M-ip.html#SP9">&#167;9. Stack access</a></li><li><a href="M-ip.html#SP10">&#167;10. Accessing storage</a></li><li><a href="M-ip.html#SP11">&#167;11. Indirect function calls</a></li><li><a href="M-ip.html#SP12">&#167;12. Message function calls</a></li><li><a href="M-ip.html#SP13">&#167;13. External function calls</a></li><li><a href="M-ip.html#SP14">&#167;14. Control flow</a></li><li><a href="M-ip.html#SP15">&#167;15. Interactive fiction-only primitives</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. What standard means. </b>To recap from <a href="M-cpiti.html" class="internal">Code Packages in Textual Inter</a>, primitives are like built-in
atomic operations. The Inter specification allows for any desired set of
primitives to be used, provided they are declared. However, in practice
the <a href="../building-module/index.html" class="internal">building</a> module of Inter defines a standard set of 95 or so primitives
which are used across the Inform tool-chain, and:
</p>
<ul class="items"><li>&#9679; The front end of the Inform compiler invokes only (a subset of) this
standard set of primitives.
</li><li>&#9679; The back end guarantees to be able to perform final code-generation to
any supported platform on the whole of this standard set.
</li></ul>
<p class="commentary">That means the standard set is (for now at least) the only game in town, and
the following catalogue runs through it. Textual Inter code does not need
to declare primitives if they belong to this standard set, but the
declarations they have behind the scenes are all listed below.
</p>
<p class="commentary">(See <a href="../building-module/1-ip.html" class="internal">Inter Primitives (in building)</a> for where in the <a href="index.html" class="internal">inter</a> source code
these primitives are defined.)
</p>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. Arithmetic. </b>The following are standard integer arithmetic operations, using signed
twos-complement integers:
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !plus val val -&gt; val</span></span>. 16 or 32-bit integer addition.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !minus val val -&gt; val</span></span>. 16 or 32-bit integer subtraction.
</li><li>(c) <span class="extract"><span class="extract-syntax">primitive !unaryminus val -&gt; val</span></span>. Equivalent to performing <span class="extract"><span class="extract-syntax">0 - x</span></span>.
</li><li>(d) <span class="extract"><span class="extract-syntax">primitive !times val val -&gt; val</span></span>. 16 or 32-bit integer multiplication.
</li><li>(e) <span class="extract"><span class="extract-syntax">primitive !divide val val -&gt; val</span></span>. 16 or 32-bit integer division.
</li><li>(f) <span class="extract"><span class="extract-syntax">primitive !modulo val val -&gt; val</span></span>. Remainder after such a division.
</li></ul>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. Logical operators. </b>In general, the value 0 is false, and all other values are true.
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !not val -&gt; val</span></span>. True if the value is false, and vice versa.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !and val val -&gt; val</span></span>. True if both are true: doesn't evaluate the
second if the first is false.
</li><li>(c) <span class="extract"><span class="extract-syntax">primitive !or val val -&gt; val</span></span>. True if either is true: doesn't evaluate the
second if the first is true.
</li></ul>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. Bitwise operators. </b>These differ in that they do not "short circuit", and do not squash values
down to just 0 or 1.
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !bitwiseand val val -&gt; val</span></span>.
</li><li>(a) <span class="extract"><span class="extract-syntax">primitive !bitwiseor val val -&gt; val</span></span>.
</li><li>(a) <span class="extract"><span class="extract-syntax">primitive !bitwisenot val -&gt; val</span></span>.
</li></ul>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. Numerical comparison. </b>These are comparisons of signed integers. (If Inform needs to compare unsigned
integers, it calls a routine in the I6 template.)
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !eq val val -&gt; val</span></span>.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !ne val val -&gt; val</span></span>.
</li><li>(c) <span class="extract"><span class="extract-syntax">primitive !gt val val -&gt; val</span></span>.
</li><li>(d) <span class="extract"><span class="extract-syntax">primitive !ge val val -&gt; val</span></span>.
</li><li>(e) <span class="extract"><span class="extract-syntax">primitive !lt val val -&gt; val</span></span>.
</li><li>(f) <span class="extract"><span class="extract-syntax">primitive !le val val -&gt; val</span></span>.
</li></ul>
<p class="commentary">This is a special operation allowing the comparisons to test for multiple
possibilities at once. (Old-school Inform 6 users will recognise it as the
<span class="extract"><span class="extract-syntax">or</span></span> operator.)
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">!alternative val val -&gt; val</span></span>
</li></ul>
<p class="commentary">For example,
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">inv</span><span class="plain-syntax"> </span><span class="function-syntax">!eq</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">val</span><span class="plain-syntax"> x</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">inv</span><span class="plain-syntax"> </span><span class="function-syntax">!alternative</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="constant-syntax">2</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="constant-syntax">7</span>
</pre>
<p class="commentary">tests whether <span class="extract"><span class="extract-syntax">x</span></span> equals either 2 or 7.
</p>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. Sequential evaluation. </b>The reason for the existence of <span class="extract"><span class="extract-syntax">!ternarysequential</span></span> is that it's a convenient
shorthand, and also that it helps the code generator with I6 generation,
because I6 has problems with the syntax of complicated sequential evals.
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !sequential val val -&gt; val</span></span>. Evaluates the first, then the second
value, producing that second value.
</li><li>(a) <span class="extract"><span class="extract-syntax">primitive !ternarysequential val val val -&gt; val</span></span>. Evaluates the first,
then the second, then the third value, producing that third value.
</li></ul>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. Random. </b>This is essentially the built-in <span class="extract"><span class="extract-syntax">random</span></span> function of Inform 6, given an Inter
disguise. See the Inform 6 Designer's Manual for a specification.
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">!primitive random val -&gt; val</span></span>.
</li></ul>
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>&#167;8. Printing. </b>These print data of various kinds:
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !print val -&gt; void</span></span>. Print text.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !printnumber val -&gt; void</span></span>. Print a (signed) number in decimal.
</li><li>(c) <span class="extract"><span class="extract-syntax">primitive !printchar val -&gt; void</span></span>. Print a character value.
</li><li>(d) <span class="extract"><span class="extract-syntax">primitive !printnl void -&gt; void</span></span>. Print a newline. (This is needed because
some of our VMs use character 10 for newline, and crash on 13, and others vice versa.)
</li><li>(e) <span class="extract"><span class="extract-syntax">primitive !printdword val -&gt; void</span></span>. Print a dictionary word.
</li><li>(f) <span class="extract"><span class="extract-syntax">primitive !printstring val -&gt; void</span></span>. Print a packed string.
</li></ul>
<p class="commentary">There are also two primitive ways to change the visual style of text:
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !font val -&gt; void</span></span>. Change to fixed-width font if value is 1, or regular if 0.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !style val -&gt; void</span></span>. Change to this text style.
</li></ul>
<p class="commentary">The effect of these will depend on the platform the final Inter code is generated
for. If the value supplied to <span class="extract"><span class="extract-syntax">!style</span></span> is 0, 1, 2 or 3, then this should make an
effort to achieve roman, bold, italic, or reverse-video type, respectively, and
that should apply across all platforms. Use of any other value is likely to be
less portable. On C, for example, all other uses of <span class="extract"><span class="extract-syntax">!style</span></span> are (Inform) text
values which supply names for styles.
</p>
<p class="commentary">Then there is a primitive for a rum feature of Inform 6 allowing for the display of
"box quotations" on screen:
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !box val -&gt; void</span></span>.
</li></ul>
<p class="commentary">And another largely pointless primitive for issuing a run of a certain number of
spaces, for users too lazy to write their own loops:
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !spaces val -&gt; void</span></span>.
</li></ul>
<p class="commentary">On some platforms, active steps need to be taken before text can actually appear:
for example, those using the Glk input/output framework. As a convenience, this
primitive will do anything which might be necessary. <a href="../inform7/index.html" class="internal">inform7</a> doesn't use
this, instead compiling its own code to activate Glk, but it's useful to have
this opcode for making small Inter test cases work:
</p>
<ul class="items"><li>(a) !primitive !enableprinting void -&gt; void<span class="extract"><span class="extract-syntax">.
</span></span></li></ul>
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>&#167;9. Stack access. </b>The stack is not directly accessible anywhere in memory, so the only access
is via the following.
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !push val -&gt; void</span></span>. Push value onto the stack.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !pull ref -&gt; void</span></span>. Pull value from the stack and write it into
the storage referred to. Values on the stack have unchecked kinds: it's up to
the author not to pull an inappropriate value.
</li></ul>
<p class="commentary firstcommentary"><a id="SP10" class="paragraph-anchor"></a><b>&#167;10. Accessing storage. </b>Here the <span class="extract"><span class="extract-syntax">ref</span></span> term is a reference to a piece of storage: a property of an
instance, or a global variable, or an entry in memory, for example.
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !store ref val -&gt; val</span></span>. Put the value in <span class="extract"><span class="extract-syntax">ref</span></span>.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !setbit ref val -&gt; void</span></span>. Set bits in the mask <span class="extract"><span class="extract-syntax">val</span></span> in <span class="extract"><span class="extract-syntax">ref</span></span>.
</li><li>(c) <span class="extract"><span class="extract-syntax">primitive !clearbit ref val -&gt; void</span></span>. Clear bits in the mask <span class="extract"><span class="extract-syntax">val</span></span> in <span class="extract"><span class="extract-syntax">ref</span></span>.
</li><li>(d) <span class="extract"><span class="extract-syntax">primitive !postincrement ref -&gt; val</span></span>. Performs the equivalent of <span class="extract"><span class="extract-syntax">ref++</span></span>.
</li><li>(e) <span class="extract"><span class="extract-syntax">primitive !preincrement ref -&gt; val</span></span>. Performs the equivalent of <span class="extract"><span class="extract-syntax">++ref</span></span>.
</li><li>(f) <span class="extract"><span class="extract-syntax">primitive !postdecrement ref -&gt; val</span></span>. Performs the equivalent of <span class="extract"><span class="extract-syntax">ref--</span></span>.
</li><li>(g) <span class="extract"><span class="extract-syntax">primitive !predecrement ref -&gt; val</span></span>. Performs the equivalent of <span class="extract"><span class="extract-syntax">--ref</span></span>.
</li></ul>
<p class="commentary">Memory can be accessed with the following. The first value is the address of
the array; the second is an offset, that is, with 0 being the first entry,
1 the second, and so on. "Word" in this context means either an <span class="extract"><span class="extract-syntax">int16</span></span> or
an <span class="extract"><span class="extract-syntax">int32</span></span>, depending on what virtual machine are compiling to.
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !lookup val val -&gt; val</span></span>. Find word at this word offset.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !lookupbyte val val -&gt; val</span></span>. Find byte at this byte offset.
</li></ul>
<p class="commentary">Properties, like memory, can be converted to <span class="extract"><span class="extract-syntax">ref</span></span> in order to write to them,
and are accessible with <span class="extract"><span class="extract-syntax">propertyvalue</span></span>. Their existence can be tested with
<span class="extract"><span class="extract-syntax">propertyexists</span></span>; the other two opcodes here are for the handful of "inline
property values", where a property stores not a single value but a small array.
In each of the four ternary property primitives, the operands are <span class="extract"><span class="extract-syntax">K</span></span>, the
weak kind ID of the owner; <span class="extract"><span class="extract-syntax">O</span></span>, the owner; and <span class="extract"><span class="extract-syntax">P</span></span>, the property. For properties
of objects, <span class="extract"><span class="extract-syntax">K</span></span> will always be <span class="extract"><span class="extract-syntax">OBJECT_TY</span></span>.
</p>
<p class="commentary"><span class="extract"><span class="extract-syntax">propertyarray</span></span> and <span class="extract"><span class="extract-syntax">propertylength</span></span> both produce 0 (but not a run-time error)
if called on a property value which does not exist, or is not an inline array.
In particular, they always produce 0 if the owner <span class="extract"><span class="extract-syntax">O</span></span> is not an object, since
only objects can have inline property values.
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !propertyvalue val val val -&gt; val</span></span>.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !propertyarray val val val -&gt; val</span></span>.
</li><li>(c) <span class="extract"><span class="extract-syntax">primitive !propertylength val val val -&gt; val</span></span>.
</li><li>(d) <span class="extract"><span class="extract-syntax">primitive !propertyexists val val val -&gt; val</span></span>.
</li></ul>
<p class="commentary firstcommentary"><a id="SP11" class="paragraph-anchor"></a><b>&#167;11. Indirect function calls. </b>Invocations of functions can only be made with <span class="extract"><span class="extract-syntax">inv</span></span> when the function is
specified as a constant, and when its signature is therefore known. If
we need to call "whatever function this variable refers to", we have to
use one of the following. They differ only in their signatures. The
first value is the function address, and subsequent ones are arguments.
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !indirect0v val -&gt; void</span></span>.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !indirect1v val val -&gt; void</span></span>.
</li><li>(c) <span class="extract"><span class="extract-syntax">primitive !indirect2v val val val -&gt; void</span></span>.
</li><li>(d) <span class="extract"><span class="extract-syntax">primitive !indirect3v val val val val -&gt; void</span></span>.
</li><li>(e) <span class="extract"><span class="extract-syntax">primitive !indirect4v val val val val val -&gt; void</span></span>.
</li><li>(f) <span class="extract"><span class="extract-syntax">primitive !indirect5v val val val val val val -&gt; void</span></span>.
</li><li>(g) <span class="extract"><span class="extract-syntax">primitive !indirect0 val -&gt; val</span></span>.
</li><li>(h) <span class="extract"><span class="extract-syntax">primitive !indirect1 val val -&gt; val</span></span>.
</li><li>(i) <span class="extract"><span class="extract-syntax">primitive !indirect2 val val val -&gt; val</span></span>.
</li><li>(j) <span class="extract"><span class="extract-syntax">primitive !indirect3 val val val val -&gt; val</span></span>.
</li><li>(k) <span class="extract"><span class="extract-syntax">primitive !indirect4 val val val val val -&gt; val</span></span>.
</li><li>(l) <span class="extract"><span class="extract-syntax">primitive !indirect5 val val val val val val -&gt; val</span></span>.
</li></ul>
<p class="commentary firstcommentary"><a id="SP12" class="paragraph-anchor"></a><b>&#167;12. Message function calls. </b>These are the special form of function call from Inform 6 with the syntax
<span class="extract"><span class="extract-syntax">a.b()</span></span>, <span class="extract"><span class="extract-syntax">a.b(c)</span></span>, <span class="extract"><span class="extract-syntax">a.b(c, d)</span></span> or <span class="extract"><span class="extract-syntax">a.b(c, d, e)</span></span>. In effect, they look up a
property value which is a function, and call it. But because they have very
slightly different semantics from indirect function calls, they appear here
as primitives of their own. Inform 7 never compiles these, but kit assimilation
may do. To get an idea of how to handle these, see for example
<a href="../final-module/5-cfm.html" class="internal">C Function Model (in final)</a>, which compiles them to C.
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !message0 val val -&gt; val</span></span>.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !message1 val val val -&gt; val</span></span>.
</li><li>(c) <span class="extract"><span class="extract-syntax">primitive !message2 val val val val -&gt; val</span></span>.
</li><li>(d) <span class="extract"><span class="extract-syntax">primitive !message3 val val val val val -&gt; val</span></span>.
</li></ul>
<p class="commentary firstcommentary"><a id="SP13" class="paragraph-anchor"></a><b>&#167;13. External function calls. </b>The following calls a function which is not part of the program itself, and
which is assumed to be provided by code written in a different programming
language. It cannot be used when Inter is being generated to Inform 6
code, because I6 has no ability to link with external code; but it can be
used when generating C, for example.
</p>
<p class="commentary">The first value must be a literal double-quoted text, and is the name of
the external function. The second value is an argument to pass to it; and
the result is whatever value it returns.
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !externalcall val val -&gt; val</span></span>.
</li></ul>
<p class="commentary firstcommentary"><a id="SP14" class="paragraph-anchor"></a><b>&#167;14. Control flow. </b>The simplest control statement is an "if". Note that a different primitive
is used if there is an "else" attached: it would be impossible to use the
same primitive for both because they couldn't have the same signature.
</p>
<p class="commentary"><span class="extract"><span class="extract-syntax">!ifdebug</span></span> is an oddity: it executes the code only if the program is
being compiled in "debugging mode". (In Inform, that would mean that the
story file is being made inside the application, or else released in a
special testing configuration.) While the same effect could be achieved
using conditional compliation splats, this is much more efficient.
Similarly for <span class="extract"><span class="extract-syntax">!ifstrict</span></span>, which tests for "strict mode", in which run-time
checking of program correctness is performed, but at some performance cost.
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !if val code -&gt; void</span></span>.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !ifelse val code code -&gt; void</span></span>.
</li><li>(c) <span class="extract"><span class="extract-syntax">primitive !ifdebug code -&gt; void</span></span>.
</li><li>(d) <span class="extract"><span class="extract-syntax">primitive !ifstrict code -&gt; void</span></span>.
</li></ul>
<p class="commentary">There are then several loops.
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !while val code -&gt; void</span></span>. Similar to <span class="extract"><span class="extract-syntax">while</span></span> in C.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !do val code -&gt; void</span></span>. A do/until loop, where the test of <span class="extract"><span class="extract-syntax">val</span></span>
comes at the end of each iteration. Note that this is do/until, not do/while.
</li><li>(c) <span class="extract"><span class="extract-syntax">primitive !for val val val code -&gt; void</span></span>. Similar to <span class="extract"><span class="extract-syntax">for</span></span> in C.
</li><li>(d) <span class="extract"><span class="extract-syntax">primitive !objectloopx ref val code -&gt; void</span></span>. A loop over instances,
stored in the variable <span class="extract"><span class="extract-syntax">ref</span></span>, of the kind of object <span class="extract"><span class="extract-syntax">val</span></span>.
</li><li>(e) <span class="extract"><span class="extract-syntax">primitive !objectloop ref val val code -&gt; void</span></span>. A more general form,
where the second <span class="extract"><span class="extract-syntax">val</span></span> is a condition to be evaluated which decides whether
to execute the code for given <span class="extract"><span class="extract-syntax">ref</span></span> value.
</li></ul>
<p class="commentary">A switch statement takes a value, and then executes at most one of an
arbitrary number of possible code segments. This can't be implemented with
a single primitive, because its signature would have to be of varying
lengths with different uses (since some switches have many cases, some few).
Instead: a <span class="extract"><span class="extract-syntax">switch</span></span> takes a single <span class="extract"><span class="extract-syntax">code</span></span>, but that <span class="extract"><span class="extract-syntax">code</span></span> can in turn
contain only invocations of <span class="extract"><span class="extract-syntax">!case</span></span>, followed optionally by one of <span class="extract"><span class="extract-syntax">!default</span></span>.
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !switch val code -&gt; void</span></span>.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !case val code -&gt; void</span></span>.
</li><li>(c) <span class="extract"><span class="extract-syntax">primitive !default code -&gt; void</span></span>.
</li><li>(d) <span class="extract"><span class="extract-syntax">primitive !alternativecase val val -&gt; val</span></span>.
</li></ul>
<p class="commentary">This looks a little baroque, but it works in practice:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">inv</span><span class="plain-syntax"> </span><span class="function-syntax">!switch</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_number</span><span class="plain-syntax"> X</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">code</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">inv</span><span class="plain-syntax"> </span><span class="function-syntax">!case</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_number</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">code</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">inv</span><span class="plain-syntax"> </span><span class="function-syntax">!print</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_text</span><span class="plain-syntax"> </span><span class="string-syntax">"One!"</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">inv</span><span class="plain-syntax"> </span><span class="function-syntax">!case</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">inv</span><span class="plain-syntax"> </span><span class="function-syntax">!alternativecase</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_number</span><span class="plain-syntax"> </span><span class="constant-syntax">2</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_number</span><span class="plain-syntax"> </span><span class="constant-syntax">7</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">code</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">inv</span><span class="plain-syntax"> </span><span class="function-syntax">!print</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_text</span><span class="plain-syntax"> </span><span class="string-syntax">"Either two or seven!"</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">inv</span><span class="plain-syntax"> </span><span class="function-syntax">!default</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">code</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">inv</span><span class="plain-syntax"> </span><span class="function-syntax">!print</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_text</span><span class="plain-syntax"> </span><span class="string-syntax">"Something else!"</span>
</pre>
<p class="commentary">As in most C-like languages, there are primitives for:
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !break void -&gt; void</span></span>. Exit the innermost switch case or loop.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !continue void -&gt; void</span></span>. Complete the current iteration of
the innermost loop.
</li></ul>
<p class="commentary">Two ways to terminate what's happening:
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !return val -&gt; void</span></span>. Finish the current function, giving the
supplied value as the result if the function is being executed in a value
context, and throwing it away if not.
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !quit void -&gt; void</span></span>. Halt the whole program immediately.
</li></ul>
<p class="commentary">This is a sort of termination, too, loading in a fresh program state from a
file; something which may not be very meaningful in all platforms. Note that
there is no analogous <span class="extract"><span class="extract-syntax">!restart</span></span> or <span class="extract"><span class="extract-syntax">!save</span></span> primitive: those are handled by
assembly language instead. This may eventually go, too.
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !restore lab -&gt; void</span></span>.
</li></ul>
<p class="commentary">And, lastly, the lowest-level way to travel:
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !jump lab -&gt; void</span></span>. Jump to this label in the current function.
</li></ul>
<p class="commentary firstcommentary"><a id="SP15" class="paragraph-anchor"></a><b>&#167;15. Interactive fiction-only primitives. </b>The following would make no sense in a general-purpose program. Most mirror
very low-level I6 features. First, the spatial containment object tree:
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !move val val -&gt; void</span></span>. Moves first to second (both are objects).
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !remove val -&gt; void</span></span>. Removes object from containment tree.
</li><li>(c) <span class="extract"><span class="extract-syntax">primitive !in val val -&gt; val</span></span>. Tests if first is in second (both are objects).
</li><li>(d) <span class="extract"><span class="extract-syntax">primitive !notin val val -&gt; val</span></span>. Negation of same.
</li><li>(e) <span class="extract"><span class="extract-syntax">primitive !child val -&gt; val</span></span>. Finds the child node of an object.
</li><li>(f) <span class="extract"><span class="extract-syntax">primitive !children val -&gt; val</span></span>. The number of children: which may be 0.
</li><li>(g) <span class="extract"><span class="extract-syntax">primitive !parent val -&gt; val</span></span>. Finds the parent of an object.
</li><li>(h) <span class="extract"><span class="extract-syntax">primitive !sibling val -&gt; val</span></span>. Finds the sibling of an object.
</li></ul>
<p class="commentary">Object class membership:
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">primitive !ofclass val val -&gt; val</span></span>. Does the first belong to the enumerated
subkind whose weak type ID is the second value?
</li><li>(b) <span class="extract"><span class="extract-syntax">primitive !metaclass val -&gt; val</span></span>. Returns <span class="extract"><span class="extract-syntax">Class</span></span>, <span class="extract"><span class="extract-syntax">Object</span></span>, <span class="extract"><span class="extract-syntax">Routine</span></span>,
<span class="extract"><span class="extract-syntax">String</span></span> or 0 depending on the value supplied: see the Inform 6 Designer's Manual
for more on this.
</li></ul>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="M-cpiti.html">&#10094;</a></li><li class="progresscurrentchapter">M</li><li class="progresssection"><a href="M-ui.html">ui</a></li><li class="progresssection"><a href="M-ti.html">ti</a></li><li class="progresssection"><a href="M-dpiti.html">dpiti</a></li><li class="progresssection"><a href="M-cpiti.html">cpiti</a></li><li class="progresscurrent">ip</li><li class="progresssection"><a href="M-ia.html">ia</a></li><li class="progresssection"><a href="M-io.html">io</a></li><li class="progresssection"><a href="M-pas.html">pas</a></li><li class="progresssection"><a href="M-rc.html">rc</a></li><li class="progresschapter"><a href="1-mn.html">1</a></li><li class="progressnext"><a href="M-ia.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>