1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-03 07:24:58 +03:00
inform7/inter/Manual/Inform Organisation.w
2022-03-31 12:32:39 +01:00

212 lines
9.9 KiB
OpenEdge ABL

Inform Organisation.
The standard hierarchy of inter code generated by Inform.
@h Status.
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//.
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.
@h Global area and main.
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|.
|/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.
@h Compilation modules.
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)
/main/M/actions
/main/M/activities
/main/M/adjectives
/main/M/arrays
/main/M/basics
/main/M/bibliographic
/main/M/chronology
/main/M/commands
/main/M/conjugations
/main/M/constants
/main/M/extensions
/main/M/functions
/main/M/grammar
/main/M/instances
/main/M/interactive_fiction
/main/M/kinds
/main/M/multimedia
/main/M/phrases
/main/M/properties
/main/M/relations
/main/M/responses
/main/M/rulebooks
/main/M/rules
/main/M/scenes
/main/M/table_columns
/main/M/tables
/main/M/tests
/main/M/text
/main/M/use_options
/main/M/variables
=
@ 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:
= (text as Inter)
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
...
=
@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|:
= (text as Inter)
package rule_fn _function
package call _code
...
=
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:
= (text as Inter)
package rule_fn _function
package call _code
...
package kernel _code
...
=
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.
@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
=
Be warned that these are large: they have several large kits linked into them
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.
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.)