2019-03-19 03:24:35 +02:00
|
|
|
Using Inter.
|
|
|
|
|
2019-03-19 14:11:09 +02:00
|
|
|
Using Inter at the command line.
|
2019-03-19 03:24:35 +02:00
|
|
|
|
2019-03-19 14:11:09 +02:00
|
|
|
@h What Inter does.
|
2022-03-25 01:35:22 +02:00
|
|
|
"Inter" is the intermediate representation of a program used in the Inform
|
|
|
|
compiler toolchain. Most compilers have one of these: for example, Microsoft
|
|
|
|
compilers mostly use "CIL" (common intermediate language), while |gcc| uses
|
|
|
|
something called GIMPLE, and so on. See //bytecode// for a longer discussion
|
|
|
|
of what motivates the design of Inter.
|
|
|
|
|
|
|
|
The practical effect is that the back end of the Inform compiler deals only
|
|
|
|
with Inter code. This back end exists as part of the executable //inform7//,
|
|
|
|
but also as a stand-alone program called //inter//, which comes with its
|
|
|
|
own command-line interface. Whereas //inform7// has a specific task to perform
|
|
|
|
and uses Inter code only as a means to an end, //inter// is designed to be
|
|
|
|
as flexible as possible.
|
|
|
|
|
|
|
|
@ Inter code can exist in memory, or in a human-readable text file, or in a
|
|
|
|
rapid-access binary file. The tool //inter// can convert between these formats:
|
|
|
|
= (text as BoxArt)
|
|
|
|
textual textual
|
|
|
|
inter ---+ +---> inter
|
|
|
|
\ /
|
|
|
|
\ /
|
|
|
|
----> memory ----
|
|
|
|
/ inter \
|
|
|
|
binary / \ binary
|
|
|
|
inter ---+ +---> inter
|
|
|
|
=
|
|
|
|
|
|
|
|
However, Inter can do much more than simply convert between these forms. It
|
|
|
|
has a "pipeline" design, meaning that it can run memory inter through any
|
|
|
|
desired series of compilation stages, one at a time:
|
|
|
|
= (text as BoxArt)
|
|
|
|
T --------> T --------> T --------> ... --------> T
|
|
|
|
step 1 step 2 step 3 ... step N
|
|
|
|
=
|
|
|
|
The Inter tree |T| starts out empty,[1] and at the end it is thrown away. So any
|
|
|
|
useful pipeline will begin by loading something in (usually as step 1), and
|
|
|
|
end by producing some useful output (usually in its last step or steps).
|
|
|
|
|
|
|
|
The advantage of this design is that it enables us to build what amount to
|
|
|
|
entirely different compilers, just by using different pipelines -- see
|
|
|
|
"assimilation" below for an example of a pipeline very different to the one
|
|
|
|
used in normal Inform 7 compilations. Pipelines also allow us to test existing
|
|
|
|
or proposed code-generation stages individually.
|
|
|
|
|
|
|
|
[1] Programs in Inter format are called "Inter trees".
|
|
|
|
|
|
|
|
@h Verify only.
|
2019-03-19 14:11:09 +02:00
|
|
|
If you have compiled the standard distribution of the command-line tools
|
2019-03-19 03:24:35 +02:00
|
|
|
for Inform then the Inter executable will be at |inter/Tangled/inter|.
|
|
|
|
|
2019-07-20 14:40:27 +03:00
|
|
|
Inter has three basic modes. In the first, the command line specifies only
|
|
|
|
a single file:
|
2020-04-08 01:02:44 +03:00
|
|
|
= (text as ConsoleText)
|
|
|
|
$ inter/Tangled/inter INTERFILE
|
|
|
|
=
|
2019-07-20 14:40:27 +03:00
|
|
|
Inter simply verifies this file for correctness: that is, to see if the inter
|
|
|
|
code supplied conforms to the inter specification. It returns the exit code 0
|
|
|
|
if all is well, and issues error messages and returns 1 if not.
|
2019-03-19 03:24:35 +02:00
|
|
|
|
|
|
|
Such files can be in either textual or binary form, and Inter automatically
|
|
|
|
detects which by looking at their contents. (Conventionally, such files
|
|
|
|
have the filename extension |.intert| or |.interb| respectively, but that's
|
|
|
|
not how Inter decides.)
|
|
|
|
|
2022-03-25 01:35:22 +02:00
|
|
|
@h Format conversion.
|
|
|
|
In the second mode, Inter not only loads (and verifies) the named file, but
|
|
|
|
then converts it to a different format and writes that out. For example,
|
2020-04-08 01:02:44 +03:00
|
|
|
= (text as ConsoleText)
|
2022-03-25 01:35:22 +02:00
|
|
|
$ inter/Tangled/inter my.intert -o my.interb -format=binary
|
2020-04-08 01:02:44 +03:00
|
|
|
=
|
2022-03-25 01:35:22 +02:00
|
|
|
converts |my.intert| (a textual inter file) to its binary equivalent |my.interb|,
|
|
|
|
and conversely:
|
2020-04-08 01:02:44 +03:00
|
|
|
= (text as ConsoleText)
|
2022-03-25 01:35:22 +02:00
|
|
|
$ inter/Tangled/inter my.interb -o my.intert -format=text
|
2020-04-08 01:02:44 +03:00
|
|
|
=
|
2022-03-25 01:35:22 +02:00
|
|
|
Two parameters must be specified: |-o| giving the output file, and |-format=F|
|
|
|
|
to say what format |F| this should have. Formats are in the same notation as
|
|
|
|
those used by //inbuild//, which similarly supports |-o| and |-format|.
|
|
|
|
In fact, |-format=text| is the default.
|
|
|
|
|
|
|
|
To take an elaborate example,
|
|
|
|
= (text as ConsoleText)
|
|
|
|
$ inter/Tangled/inter my.interb -o my.intert -format=C/32d/nomain
|
2020-04-08 01:02:44 +03:00
|
|
|
=
|
2022-03-25 01:35:22 +02:00
|
|
|
generates a 32-bit-word, debugging-enabled ANSI C program from the Inter tree
|
|
|
|
in |my.interb|, with no |main| function included in it.
|
|
|
|
|
|
|
|
As a special case, if |-o| is given just as |-|, then the output is printed
|
|
|
|
to the console rather than to a file.
|
|
|
|
|
|
|
|
@h Running a pipeline.
|
|
|
|
If we specify |-trace| as a command-line switch, Inter prints out every step
|
|
|
|
of the pipeline(s) it is following. This reveals that even the simple commands
|
|
|
|
above are, in fact, running pipelines, albeit short ones:
|
2020-04-08 01:02:44 +03:00
|
|
|
= (text as ConsoleText)
|
2022-03-25 01:35:22 +02:00
|
|
|
$ inter/Tangled/inter my.intert -trace
|
|
|
|
step 1/1: read <- my.intert
|
|
|
|
$ inter/Tangled/inter my.intert -o my.interb -format=binary -trace
|
|
|
|
step 1/2: read <- my.intert
|
|
|
|
step 2/2: generate binary -> my.interb
|
2020-04-08 01:02:44 +03:00
|
|
|
=
|
2022-03-25 01:35:22 +02:00
|
|
|
As this shows, a one or two-step pipeline was running:
|
|
|
|
|
|
|
|
(1) The first step used the |read| compilation stage, which reads some Inter
|
|
|
|
code into memory. Here, it comes from the file |my.intert|.
|
|
|
|
|
|
|
|
(2) The second step used the |generate| stage, which writes out Inter code
|
|
|
|
in the format of one's choice -- here "binary".
|
|
|
|
|
|
|
|
@ However, we don't have to use this default pipeline. |-pipeline-text 'PIPELINE'|
|
|
|
|
reads in a textual description of the pipeline to follow, with the steps divided
|
|
|
|
by commas. The examples above used a pipeline which in this notation would
|
|
|
|
be written as:
|
|
|
|
= (text as ConsoleText)
|
|
|
|
-pipeline-text 'read <- *in, generate -> *out'
|
|
|
|
=
|
|
|
|
|*in| and |*out| are examples of "pipeline variables". |*in| is the filename
|
|
|
|
of whatever file is to be read in, and |*out| is whatever was specified by |-o|
|
|
|
|
at the command line, or in other words, the filename to write the output to.
|
|
|
|
|
|
|
|
This is not quite the smallest possible pipeline. Consider:
|
|
|
|
= (text as ConsoleText)
|
|
|
|
$ inter/Tangled/inter -o my.intert -pipeline-text 'new, generate -> *out' -trace
|
|
|
|
step 1/2: new
|
|
|
|
step 2/2: generate text -> my.intert
|
|
|
|
=
|
|
|
|
Here we didn't specify any Inter file to read in, so |*in| does not appear.
|
|
|
|
Instead wevbegan the pipeline with the |new| compilation stage, which creates
|
|
|
|
a minimal Inter program from nothing.
|
|
|
|
|
|
|
|
Even three-step pipelines can be very useful. For example:
|
|
|
|
= (text as ConsoleText)
|
|
|
|
$ inter/Tangled/inter -o my.intert -pipeline-text 'read <- *in, eliminate-redundant-labels, generate -> *out' -trace
|
|
|
|
step 1/3: read <- my.intert
|
|
|
|
step 2/3: eliminate-redundant-labels
|
|
|
|
step 3/3: generate text -> my.intert
|
|
|
|
=
|
|
|
|
This could be used to test that the |eliminate-redundant-labels| compilation
|
|
|
|
stage is working as it should. We can feed our choice of Inter code into it,
|
|
|
|
and examine its direct output, in isolation from the working of the rest of
|
|
|
|
the compiler (and, of course, more quickly).
|
|
|
|
|
|
|
|
@ In practice, it becomes cumbersome to spell the pipeline out longhand on
|
|
|
|
the command line, so we can also put it into a text file:
|
2020-04-08 01:02:44 +03:00
|
|
|
= (text as ConsoleText)
|
|
|
|
$ inter/Tangled/inter -pipeline-file mypl.interpipeline
|
|
|
|
=
|
2022-03-25 01:35:22 +02:00
|
|
|
It's not allowed to specify both |-pipeline-file| and |-pipeline-text|.
|
|
|
|
The text file, however, specifies pipelines with one step on each line, not
|
|
|
|
using commas. So |-pipeline-text 'read <- *in, eliminate-redundant-labels, generate -> *out'|
|
|
|
|
is equivalent to |-pipeline-file| with the file:
|
2020-04-08 01:02:44 +03:00
|
|
|
= (text)
|
2022-03-25 01:35:22 +02:00
|
|
|
read <- *in
|
|
|
|
eliminate-redundant-labels
|
|
|
|
generate -> *out
|
2020-04-08 01:02:44 +03:00
|
|
|
=
|
2022-03-25 01:35:22 +02:00
|
|
|
For more on how to write and use pipeline files, see //Pipelines and Stages//.
|
|
|
|
|
|
|
|
@ In general, filenames follow the usual Unix conventions: they are taken as
|
|
|
|
relative to the current working directory, unless given as absolute filenames
|
|
|
|
beginning with |/|. But we can also set a "default directory" to take the
|
|
|
|
place of the CWD, using |-domain|:
|
2020-04-08 01:02:44 +03:00
|
|
|
= (text)
|
|
|
|
-domain D
|
2019-03-19 03:24:35 +02:00
|
|
|
|
2020-03-28 01:17:16 +02:00
|
|
|
@h Assimilation.
|
|
|
|
Inform makes use of what are called "kits" of pre-compiled Inter code:
|
|
|
|
for example, |CommandParserKit| contains code for the traditional interactive
|
2022-03-25 01:35:22 +02:00
|
|
|
fiction command parser. That pre-compilation is called "assimilation", and
|
|
|
|
is performed by the //inter// tool alone: it does not require, or use, the
|
|
|
|
bulk of the //inform7// compiler.
|
2019-03-19 03:24:35 +02:00
|
|
|
|
2022-03-25 01:35:22 +02:00
|
|
|
The source code for a kit could in principle be textual Inter, but that's too
|
2020-03-28 01:17:16 +02:00
|
|
|
verbose to write comfortably. In practice we use Inform 6 code as a notation,
|
2022-03-25 01:35:22 +02:00
|
|
|
and therefore assimilation is really compilation from I6 to Inter.
|
2020-03-28 01:17:16 +02:00
|
|
|
|
|
|
|
Kits are like so-called "fat binaries", in that they contain binary Inter
|
|
|
|
for each different architecture with which they are compatible. Inter can
|
2021-11-23 01:40:18 +02:00
|
|
|
build kits for only one architecture at a time, so a command must specify
|
2020-03-28 01:17:16 +02:00
|
|
|
which is wanted. For example:
|
2020-04-08 01:02:44 +03:00
|
|
|
= (text as ConsoleText)
|
2022-03-25 01:35:22 +02:00
|
|
|
$ inter/Tangled/inter -architecture 16 -build-kit inform7/Internal/Inter/BasicInformKit
|
|
|
|
$ inter/Tangled/inter -architecture 32d -build-kit inform7/Internal/Inter/BasicInformKit
|
2020-04-08 01:02:44 +03:00
|
|
|
=
|
2022-03-25 01:35:22 +02:00
|
|
|
At present there are four architectures: |16|, |16d|, |32| and |32d|.
|
|
|
|
Note that an architecture is not the same thing as a format: it specifies
|
|
|
|
only the word size (16 or 32 bit) and the presence, or not, of debugging data.
|
|
|
|
|
2021-11-23 01:40:18 +02:00
|
|
|
Incrementally building kits as needed could be done with something like
|
2020-03-28 01:17:16 +02:00
|
|
|
the Unix tool |make|, but in fact Inbuild has this ability: the command
|
2020-04-08 01:02:44 +03:00
|
|
|
= (text as ConsoleText)
|
|
|
|
$ inbuild/Tangled/inbuild -build K
|
|
|
|
=
|
2022-03-25 01:35:22 +02:00
|
|
|
looks at the kit |K|, works out which architectures need rebuilding, and
|
2020-03-28 01:17:16 +02:00
|
|
|
then issues commands like the above to instruct |inter| to do so. Indeed,
|
|
|
|
multiple kits can be managed with a single command:
|
2020-04-08 01:02:44 +03:00
|
|
|
= (text as ConsoleText)
|
|
|
|
$ inbuild/Tangled/inbuild -build -contents-of inform7/Internal/Inter
|
2022-03-25 01:35:22 +02:00
|
|
|
|
|
|
|
@ Under the hood, assimilation is just another use of pipeline processing. If we
|
|
|
|
run one of these |-build-kit| commands with |-trace| switched on, we see
|
|
|
|
something like this:
|
|
|
|
= (text as ConsoleText)
|
|
|
|
step 1/6: new
|
|
|
|
step 2/6: load-kit-source <- BasicInformKit
|
|
|
|
step 3/6: parse-insertions
|
|
|
|
step 4/6: resolve-conditional-compilation
|
|
|
|
step 5/6: compile-splats
|
|
|
|
step 6/6: generate binary -> inform7/Internal/Inter/BasicInformKit/arch-32.interb
|
|
|
|
=
|
|
|
|
This is in fact the result of running a pipeline file called |build-kit.interpipeline|
|
|
|
|
which is included in the standard Inter distribution.
|