The standard set of primitive invocations used within Inform.


§1. Status. The Inter specification allows for any number of primitive invocations to be declared and used; none are built-in or required.

The Inform compiler, however, has a set of around 90 different primitives. The back end of the compiler can compile those into valid Inform 6 code; the front end of the compiler is guaranteed to declare and use only (a subset of) those 90. That gives the following set of primitives a kind of halfway status: though they are not part of the inter specification, for the time being they're the only game in town.

§2. Arithmetic. The following are standard integer arithmetic operations:

§3. Logical operators. In general, the value 0 is false, and all other values are true.

§4. Bitwise operators. These differ in that they do not "short circuit", and do not squash values down to just 0 or 1.

§5. Numerical comparison. These are comparisons of signed integers. (If Inform needs to compare unsigned integers, it calls a routine in the I6 template.)

§6. Sequential evaluation. The reason for the existence of !ternarysequential 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.

§7. Random. This is essentially the built-in random function of Inform 6, given an Inter disguise. See the Inform 6 Designer's Manual for a specification.

§8. Printing. These print data of various kinds:

There are also two primitive ways to change the visual style of text:

The effect of these will depend on the platform the final Inter code is generated for. If the value supplied to !style 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 !style are (Inform) text values which supply names for styles.

Lastly, a primitive for a rum feature of Inform 6 allowing for the display of "box quotations" on screen:

§9. Stack access. The stack is not directly accessible anywhere in memory, so the only access is via the following.

§10. Accessing storage. Here the ref term is a refernce to a piece of storage: a property of an instance, or a global variable, or an entry in memory, for example.

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 int16 or an int32, depending on what virtual machine are compiling to.

Properties, like memory, can be converted to ref in order to write to them, and are accessible with propertyvalue. Their existence can be tested with propertyexists; 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 K, the weak kind ID of the owner; O, the owner; and P, the property. For properties of objects, K will always be OBJECT_TY.

propertyarray and propertylength 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 O is not an object, since only objects can have inline property values.

§11. Indirect function calls. Invocations of functions can only be made with inv 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.

§12. External function calls. 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.

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.

§13. Control flow. 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.

!ifdebug 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.

There are then several loops.

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 switch takes a single code, but that code can in turn contain only invocations of !case, followed optionally by one of !default.

This looks a little baroque, but it works in practice:

    inv !switch
        val K_number X
        code
            inv !case
                val K_number 1
                code
                    inv !print
                        val K_text "One!"
            inv !case
                val K_number 2
                code
                    inv !print
                        val K_text "Two!"
            inv !default
                code
                    inv !print
                        val K_text "Something else!"

As in most C-like languages, there are primitives for:

Two ways to terminate what's happening:

And, lastly, the lowest-level way to travel:

§14. Interactive fiction-only primitives. The following would make no sense in a general-purpose program. Most mirror very low-level I6 features. First, the spatial containment object tree:

Object class membership: