2019-03-25 11:21:34 +02:00
|
|
|
Inform Organisation.
|
|
|
|
|
|
|
|
The standard hierarchy of inter code generated by Inform.
|
|
|
|
|
|
|
|
@h Status.
|
2022-03-22 01:44:15 +02:00
|
|
|
The line between what is part of the Inter specification, and what is simply
|
|
|
|
a convention about its use, is a fine one. For example, Inter allows
|
|
|
|
arbitrary sets of primitives and of annotations, but in practice the Inform
|
|
|
|
toolchain standardises both: see //Inform Primitives// and //Inform Annotations//.
|
2019-03-25 11:21:34 +02:00
|
|
|
|
2022-03-22 01:44:15 +02:00
|
|
|
Similarly, the Inter specification allows great flexibility in how packages are
|
|
|
|
used to structure a program, but the Inform toolchain has definite ideas about
|
|
|
|
that -- as follows.
|
2019-03-25 11:21:34 +02:00
|
|
|
|
|
|
|
@h Global area and main.
|
2022-03-22 01:44:15 +02:00
|
|
|
As in every Inter program, the global area (outside of all packages) simply
|
|
|
|
defines packages and pragmas. At present, Inform generates pragmas only for
|
|
|
|
Inform 6 memory settings: even those are now probably not needed, and may go.
|
|
|
|
All of the actual program is in the |/main| package, which has type |_plain|.
|
2019-03-25 11:21:34 +02:00
|
|
|
|
2022-03-22 01:44:15 +02:00
|
|
|
|/main| contains the standard subpackages |/main/architecture| and |/main/connectors|,
|
|
|
|
both of which have type |_linkage|. The first defines architectural constants
|
|
|
|
such as |WORDSIZE|, while the second is used to manage the import and export of
|
|
|
|
symbols while linking trees together, and cannot contain content other than
|
|
|
|
symbols. Neither really contains the program as such.
|
2019-03-25 11:21:34 +02:00
|
|
|
|
|
|
|
@h Compilation modules.
|
2022-03-22 01:44:15 +02:00
|
|
|
The only other content of |/main| is its set of "modules". Each one is a subpackage
|
|
|
|
of type |_module|. They originate as follows:
|
|
|
|
|
|
|
|
(a) The "generic module" |/main/generic| contains material which is the same
|
|
|
|
on every run. For example, the definition of the typename |text_literal| can
|
|
|
|
be found here.
|
|
|
|
|
|
|
|
(b) There is one module for each "compilation unit" of source code contributing
|
|
|
|
to the program. |/main/source_text| is always one of these, and contains matter
|
|
|
|
coming directly from the main I7 source text. There is then one compilation
|
|
|
|
unit for each included extension, such as |/main/locksmith_by_emily_short|,
|
|
|
|
and one for each included kit of Inter code, such as |/main/BasicInformKit|.
|
|
|
|
|
|
|
|
(c) //inform7// also produces the "completion module" |/main/completion|,
|
|
|
|
which contains resources put together from the (natural language part of) the
|
|
|
|
program as a whole, but which can't be tied to any specific compilation unit.
|
|
|
|
For example, in an interactive fiction project, the spatial map is such a
|
|
|
|
resource.
|
|
|
|
|
|
|
|
(d) //inter// also produces the "synoptic module" |/main/synoptic|, which
|
|
|
|
contains material indexing and cross-referencing material in the other modules.
|
|
|
|
This is built last of all. For example, the synoptic module includes an array
|
|
|
|
at |/main/synoptic/actions/ActionCoding| which consolidates metadata on all
|
|
|
|
of the actions present in the program. This could not have been made as
|
|
|
|
part of the completion module because it includes references to actions only
|
|
|
|
found in the kits, and could not have been made as part of any kit because
|
|
|
|
it includes references to actions found only in the I7 source text.
|
|
|
|
|
|
|
|
In a sense the completion and synoptic modules play a similar role to each
|
|
|
|
other, and a long-term aspiration might be to move more of the former into
|
|
|
|
the latter, with a view to full linking of code some day. (At present the
|
|
|
|
tool-chain can precompile -- "assimilate" -- kits and link them in, but not
|
|
|
|
extensions written in Inform 7 source text.) Many structural choices have
|
|
|
|
been made in order to keep this option open, but it is not simple to do.
|
|
|
|
|
|
|
|
@ Thus the modules are not all produced at the same time, and several are
|
|
|
|
produced independently. The module for each kit, in particular, is essentially
|
|
|
|
compiled as a stand-alone Inter program and only joins the finished program
|
|
|
|
at the linking stage.
|
|
|
|
|
|
|
|
= (text as BoxArt)
|
|
|
|
+-------------------------------+ +---------------------+ +---------------------+
|
|
|
|
| architecture | | architecture | | architecture |
|
|
|
|
| generic | | BasicInformKit | | WorldModelKit |
|
|
|
|
| source_text | | connectors | | connectors |
|
|
|
|
| locksmith_by_emily_short | +----------+----------+ +----------+----------+
|
|
|
|
| ... | INTER | INTER |
|
|
|
|
| completion | | |
|
|
|
|
| connectors | | | ...
|
|
|
|
+------------------+------------+ | |
|
|
|
|
INFORM7 \ | |
|
|
|
|
\ \|/ \|/
|
|
|
|
\----------------------->o----------->o<-----------o---- ...
|
|
|
|
|
|
|
|
|
| INTER
|
|
|
|
|
|
|
|
|
\|/
|
|
|
|
+---------------+---------------+
|
|
|
|
| architecture |
|
|
|
|
| generic |
|
|
|
|
| source_text |
|
|
|
|
| locksmith_by_emily_short |
|
|
|
|
| ... |
|
|
|
|
| completion |
|
|
|
|
| BasicInformKit |
|
|
|
|
| WorldModelKit |
|
|
|
|
| ... |
|
|
|
|
| synoptic |
|
|
|
|
| connectors |
|
|
|
|
+-------------------------------+
|
|
|
|
=
|
|
|
|
|
|
|
|
@ Modules subdivide the program by origin. But each module is further subdivided
|
|
|
|
into "submodules", packages of type |_submodule|, and those divide it by its
|
|
|
|
ingredients. For example, the global variables in module |M| will all be in
|
|
|
|
the submodule |/main/M/variables|.
|
|
|
|
|
|
|
|
At present, the full range of possible subpackages is:
|
|
|
|
= (text as Inter)
|
2020-04-08 01:02:44 +03:00
|
|
|
/main/M/actions
|
|
|
|
/main/M/activities
|
|
|
|
/main/M/adjectives
|
2022-03-22 01:44:15 +02:00
|
|
|
/main/M/arrays
|
|
|
|
/main/M/basics
|
|
|
|
/main/M/bibliographic
|
2020-04-08 01:02:44 +03:00
|
|
|
/main/M/chronology
|
2022-03-22 01:44:15 +02:00
|
|
|
/main/M/commands
|
2020-04-08 01:02:44 +03:00
|
|
|
/main/M/conjugations
|
2022-03-22 01:44:15 +02:00
|
|
|
/main/M/constants
|
2020-04-08 01:02:44 +03:00
|
|
|
/main/M/extensions
|
|
|
|
/main/M/functions
|
|
|
|
/main/M/grammar
|
|
|
|
/main/M/instances
|
2022-03-22 01:44:15 +02:00
|
|
|
/main/M/interactive_fiction
|
2020-04-08 01:02:44 +03:00
|
|
|
/main/M/kinds
|
2022-03-22 01:44:15 +02:00
|
|
|
/main/M/multimedia
|
2020-04-08 01:02:44 +03:00
|
|
|
/main/M/phrases
|
|
|
|
/main/M/properties
|
|
|
|
/main/M/relations
|
2022-03-22 01:44:15 +02:00
|
|
|
/main/M/responses
|
2020-04-08 01:02:44 +03:00
|
|
|
/main/M/rulebooks
|
|
|
|
/main/M/rules
|
2022-03-22 01:44:15 +02:00
|
|
|
/main/M/scenes
|
|
|
|
/main/M/table_columns
|
2020-04-08 01:02:44 +03:00
|
|
|
/main/M/tables
|
2022-03-22 01:44:15 +02:00
|
|
|
/main/M/tests
|
|
|
|
/main/M/text
|
|
|
|
/main/M/use_options
|
2020-04-08 01:02:44 +03:00
|
|
|
/main/M/variables
|
|
|
|
=
|
2022-03-22 01:44:15 +02:00
|
|
|
|
|
|
|
@ Metadata is extensively used throughout Inter trees generated by Inform.
|
|
|
|
This is not simply to serve human readers who happen to be glancing at them:
|
|
|
|
it's essential to the process that generous and systematic metadata is present,
|
|
|
|
because both the synoptic module and the index[1] for a project are both generated
|
|
|
|
using that metadata.
|
|
|
|
|
|
|
|
[1] Again, this architectural choice is more work for us -- it was much easier
|
|
|
|
to produce the index higher up in the compiler, as was done until 2021 -- but
|
|
|
|
generating the index only in //inter// right at the end of the compilation
|
|
|
|
process, using only the Inter tree and its metadata, leaves open the possibility
|
|
|
|
of fuller linking of Inter code later on.
|
|
|
|
|
|
|
|
@ As an example, every module includes metadata at its top level like so:
|
2020-04-08 01:02:44 +03:00
|
|
|
= (text as Inter)
|
2022-03-22 01:44:15 +02:00
|
|
|
package main _plain
|
|
|
|
...
|
|
|
|
package basic_inform_by_graham_nelson _module
|
|
|
|
constant (int32) ^category = 3
|
|
|
|
constant (text) ^author = "Graham Nelson"
|
|
|
|
constant (text) ^title = "Basic Inform"
|
|
|
|
constant (text) ^version = "1"
|
|
|
|
constant (text) ^credit = "Basic Inform version 1 by Graham Nelson"
|
|
|
|
constant (int32) ^modesty = 0
|
|
|
|
constant (int32) ^word_count = 7691
|
|
|
|
...
|
2020-04-08 01:02:44 +03:00
|
|
|
=
|
2022-03-22 01:44:15 +02:00
|
|
|
|
|
|
|
@h Function packages.
|
|
|
|
All functions are expressed in Inter code by packages of type |_function|.
|
|
|
|
This contains the function body as a subpackage, but it may also contain
|
|
|
|
resources needed by that function body -- for example, literal texts, arrays
|
|
|
|
and so on. (The idea is that a |_function| package can be "transmigrated"
|
|
|
|
from one tree to another, without losing the resources it depends on.)
|
|
|
|
|
|
|
|
Usually this |_function| package will contain only one function body, often
|
|
|
|
but not always called just |call|:
|
2020-04-08 01:02:44 +03:00
|
|
|
= (text as Inter)
|
2022-03-22 01:44:15 +02:00
|
|
|
package rule_fn _function
|
|
|
|
package call _code
|
|
|
|
...
|
2020-04-08 01:02:44 +03:00
|
|
|
=
|
2022-03-22 01:44:15 +02:00
|
|
|
But if the function needs to manipulate or refer to data not expressible in
|
|
|
|
single words, such as lists or texts, then it will probably need to create and
|
|
|
|
subsequently destroy a stack frame. The mechanism will then be:
|
2020-04-08 01:02:44 +03:00
|
|
|
= (text as Inter)
|
2022-03-22 01:44:15 +02:00
|
|
|
package rule_fn _function
|
|
|
|
package call _code
|
|
|
|
...
|
|
|
|
package kernel _code
|
|
|
|
...
|
2020-04-08 01:02:44 +03:00
|
|
|
=
|
2022-03-22 01:44:15 +02:00
|
|
|
The "shell" function, |call|, creates a stack frame and then calls the "kernel"
|
|
|
|
function, which does the actual work; when that returns to the "shell", the
|
|
|
|
stack frame is disposed of again. This is all transparent to the user, who
|
|
|
|
simply calls |call| and doesn't need to know which mechanism is in play.
|
2022-03-28 01:14:38 +03:00
|
|
|
|
|
|
|
@h Looking at the Inter produced.
|
|
|
|
The following commands produce the final state of the Inter code for the test
|
|
|
|
case |Acidity|, in binary and textual form:
|
|
|
|
= (text as ConsoleText)
|
|
|
|
$ 'inform7/Tangled/inform7' -source inform7/Tests/Test\ Cases/Acidity.txt -o Acidity.interb -format=binary
|
|
|
|
$ 'inform7/Tangled/inform7' -source inform7/Tests/Test\ Cases/Acidity.txt -o Acidity.intert -format=text
|
|
|
|
=
|
2022-03-31 14:32:39 +03:00
|
|
|
Be warned that these are large: they have several large kits linked into them
|
2022-03-28 01:14:38 +03:00
|
|
|
by the time they have reached this final state, and thus contain many modules.
|
|
|
|
|Acidity.intert| runs to about 250,000 lines of textual Inter.
|
2022-03-31 14:32:39 +03:00
|
|
|
|
|
|
|
It's also possible to access the Inter output by the top half of //inform7//
|
|
|
|
before it passes through any linking process: simply add |-pipeline unlinked|.
|
|
|
|
Unlike the default pipeline |-pipeline compile|, |unlinked| just saves out
|
|
|
|
the Inter straight to an external file. (Of course, saving out unlinked Inter
|
|
|
|
to a format like Inform 6 will not produce viable code: linking is done for
|
|
|
|
a reason.)
|