A specification of the inter language, as written out in text file form.
§1. A manual of a sort. In its textual form, Inter could conceivably be used as a programming language, albeit a low-level and verbose one, and this section is a brief manual for that language. But the real purpose of Inter is to assist testing and debugging of the Inform tool-chain. We can write test cases in textual Inter to see if inter works; or we can write out memory inter to the debugging log to see if inform7 works.
A textual inter file is a UTF-8 encoded text file which conventionally takes the file extension ".intert". Here is an example, the test case Hello:
package main _plain package Main _code code inv !enableprinting inv !print val "Hello, world.\n"
Some basic characteristics of textual Inter can be seen at a glance. It's line-based: each line makes a single use of a "construct" like package or code. Lines can be of arbitrary length. A line beginning with a # (in column 1) is a comment, and blank lines are ignored.
As in Python, indentation from the left margin is highly significant, and must be in the form of tab characters.
Most identifiers consist of a string of one or more English upper or lower case letters, underscores, or digits, except that it must not begin with a digit. Identifier lengths are unlimited. A few identifiers of special sorts begin with a special character to mark them out as special: !enableprinting, for example, is a "primitive", marked with a !.
A convention followed in Inter code generated by Inform is that many identifiers have the form P_Name, where P is some prefix letter showing what sort of thing is referred to: for example, variables begin with V, instances with I, properties with P, and so on. This is all done only for clarity, and is not part of the Inter specification.
§2. The main organising idea of Inter is the "package". Each program is a nested hierarchy of packages, and each package has both a name and a "package type". In the Hello example, an outer package called main, of type _plain, holds only a inner package called Main, of type _code.
In fact, every program must contain just one outermost package, called main, which has to have type _plain, so that is unsurprising.
Packages of type _code are functions. A program is not required to contain any functions at all, and even if it does, it is not required to contain one called Main. For example, the Inter program into which BasicInformKit is compiled does not provide a Main, and we could imagine kits which provided, say, only some variables and arrays. But if we want a program to compile and run in a stand-alone way, then it needs a Main function as a place to begin running.
§3. Outside even main. Though this does not happen in the Hello example, a handful of instructions can appear at the top of the program, outside even main. These really just define conventions used in the rest of the program, rather than describing what the program does, and that is why they are on the outside.
§4. version NUMBER indicates that the file was written in that version of the Inter language. NUMBER is a semantic version number, and it forces inter to reject the file if the version of the Inter specification understood by inter is not compatible with the one in the file. (Note that this about the version of the specification, not the version of inter as a program.)
See The Inter Version (in bytecode) for more on the significance of this.
§5. pragma TARGET "WHATEVER" does not change the meaning of the inter file; it simply provides pragmatic advice to the eventual compiler of code generated from this file. TARGET indicates the context for which this is intended.
At present Inform 7 uses this to pass on ICL (Inform Command Language) commands to Inform 6, such as memory settings or command-line switches. For example,
pragma Inform6 "$MAX_LABELS=200000"
When a program containing this instruction is generated to C, say, then this is ignored completely. And in fact, now that Inform has adopted Inform 6.36 as its preferred copy of I6, memory settings have become unnecessary and are ignored by I6 anyway, so even this use of pragma may yet disappear.
§6. packagetype _NAME declares that _NAME can be used as a package type. It's actually unnecessary to write this explicitly, which is why the Hello example did not begin with:
packagetype _plain packagetype _code
If the program creates, say, package MOMA _museum, then the necessary package type instruction packagetype _museum will be inferred automatically. Nevertheless, it's valid to spell this out.
All package types have names beginning with an underscore _. Authors of Inter programs are free to choose any types they like, and Inform tends to use semantically meaningful type names like _adjective. Only two package types are special: _code, which as we have seen marks that a package is a function, and _linkage, which is used only for a special package called connectors. Stand-alone programs never contain that package: see bytecode for an explanation of what it is for.
§7. primitive !PRIMITIVE SIGNATURE declares that a primitive invocation of this name and signature can be used in the program. Primitives occur only inside of functions, where they are "invoked", and they are operations sufficiently basic that they cannot themselves be written as other Inter functions. For example, in Hello we saw:
inv !print val "Hello, world.\n"
This is an invocation of the primitive !print, which prints text. The "signature" of this is val -> void, meaning that it expects to have one argument, a value, and produces no result.
The declarations for the two primitives in Hello would look like this:
primitive !enableprinting void -> void primitive !print val -> void
But once again they do not need to be given, because they are part of the standard set of Inter primitives supported by inter. So these definitions are implicitly made as needed.
In principle, though, the program could create entirely novel primitives:
primitive !flytoarabia val val val -> void
And this will work perfectly well... except that inter will not be able to code-generate from the result without modification, because it won't know how to fly to Arabia. So in practice, unless you are experimenting with modified versions of Inter, do not use the primitive construct at all.
§8. The declaration line for a package begins at the level of indentation of the package's owner. For main, it should be unindented, and this is the only package allowed to appear at the top level: all other packages should be inside main in some way.
The contents of the package are then one tab stop in from the declaration. Thus:
package main _plain ... package m1_RBLK1 _code ... package m1_RBLK2 _code ...
Here, main contains two sub-packages, m1_RBLK1 and m1_RBLK2, and indentation is used to show which package a statement belongs to.
Packages of any type can freely be created inside packages of any other type, except that _code packages cannot have subpackages. So this hypothetical bit of Inter is illegal:
package my_function _code package inner_part _code ... ...
Here, inner_part cannot be made a subpackage of my_function because _code packages have no subpackages.
§9. The remaining statements to cover fall into two categories.
- ● Those used outside functions, i.e., packages of type _code, are covered in Data Packages in Textual Inter.
- ● Those used in functions, i.e., packages of type _code, are covered in Code Packages in Textual Inter.