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.