1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 16:44:21 +03:00
inform7/retrospective/6L02/I6T/Introduction.i6t
2019-02-05 00:44:07 +00:00

226 lines
12 KiB
Plaintext

B/introt: Introduction Template.
@Purpose: A short introduction to the template and its organisation.
@-------------------------------------------------------------------------------
@p The Software Stack.
The term "software stack" is sometimes used to refer to the total
body of code running in a computer. As the word "stack" implies, there
tends to be a fairly clear division between components, and an architecture
in which one component is supported by another. The ground on which the
stack rests is the hardware. Then come device drivers, for communicating
with hardware, and a kernel of very low-level code to regulate who talks to
the hardware and when. On top of that are usually several layers of
operating-system facilities and utility programs, and on top of all of that
are Firefox, iTunes and other consumer programs which the user has made a
conscious decision to run. These top-level programs are visible, while the
lower layers are concealed from the user and are generally very reliable,
so it is easy to forget that they are there at all.
Similarly, when writing and testing a work with I7, it's easy to think that
the only code running is the code directly generated by the source text.
In fact, though, it runs inside a simulated computer called the virtual
machine (or VM), and the VM has a software stack just as other computers do.
Here the distinction between "program" and "operating system" is more
blurred, because it can afford to be -- the VM only ever has a single
program running, and is not connected to any valuable hardware or data, so
there is no need to protect the system's integrity from a malicious program,
or to protect one program from the failings of another running at the same
time. But there is still a recognisable software stack. From top to bottom,
the VM at run-time contains:
(a) The rules, text and tables written by the author of this specific work of IF;
(b) Material contributed by Extensions which the author chose to borrow from;
(c) Rules, phrases and other constructions made by the Standard Rules
extension, whose use is compulsory;
(d1) Infrastructure for rulebooks and code for maintaining a world model
common to all works of IF;
(d2) The code needed to manage complex data structures such as relations,
tables, texts, and so on;
(e) The interface to the VM, which is abstracted so that higher levels
do not need to know whether Glulx or the Z-machine is being used.
Here (d1) and (d2) are independent blocks, so the picture is roughly so:
\centerline{\it the player typing at a keyboard}
\centerline{(a) MATERIAL WRITTEN BY THE AUTHOR}
\centerline{(b) EXTENSIONS CHOSEN BY THE AUTHOR}
\centerline{(c) THE STANDARD RULES}
\centerline{(d1) MECHANICS OF PLAY\qquad (d2) DATA STRUCTURE SUPPORT}
\centerline{(e) VIRTUAL MACHINE INTERFACE}
\centerline{\it virtual machine "hardware"}
NI is not like a compiler for a conventional program, because it has to
conjure up the entire software stack whenever it compiles anything. (Until
2008, NI compiled code which ran on top of the traditional I6 library:
nowadays it compiles stand-alone code which never uses the |#Include|
directive. While it's true that the I6 compiler does add a very thin extra
layer of code itself -- the "veneer" -- in all other respects NI
specifies every single line of I6 code which makes up the eventual story
file.)
NI compiles layers (a), (b) and (c) from the I7 source text found in the
project file, in the Extensions installed by the user, and in the Standard
Rules extension which comes pre-installed. But parts (d1), (d2) and (e)
are almost exactly the same I6 code whatever may be sitting above them:
they are simply copied, with minor variations, from a large body of standing
code installed in the I7 application which is called the "template".
@p Segments and Paragraphs.
The template is divided into about 40 individual "segments", each stored
in its own file and with the |.i6t| file extensions. This stands for
"I6 template", because the code generated by NI is Inform 6 (I6) code.
What makes the file a template rather than being raw code is that it is
divided into named paragraphs which contain both commentary and also I6
code: when NI turns a template into the output code, the commentary
(and each paragraph heading) is stripped out.
See the Inform documentation for how to modify the template in use for
any particular project: I6 code can be added before, instead of or after
any named segment or paragraph, and in addition, it's possible to replace
entire segment files with your own versions stored in the Materials folder
for a project.
@p Architecture.
To recap, then, the template contributes the following parts of the software
stack:
\centerline{(d1) MECHANICS OF PLAY\qquad (d2) DATA STRUCTURE SUPPORT}
\centerline{(e) VIRTUAL MACHINE INTERFACE}
A more detailed version of this diagram organises its segments follows:
{\it NI Control}. |Main.i6t|, |Load-Core.i6t| (and several others like it),
|Output.i6t|, |Definitions.i6t|.
{\it Mechanics of Play I: Rules}. |OrderOfPlay.i6t|, |Actions.i6t|,
|Activities.i6t|, |Rulebooks.i6t|.
{\it II: Infrastructure}. |Parser.i6t|, |ListWriter.i6t|, |OutOfWorld.i6t|,
|WorldModel.i6t|, |Light.i6t|, |Tests.i6t|.
{\it III: Basic Services}. |Language.i6t|, |MStack.i6t|, |Chronology.i6t|,
|Printing.i6t|, |RTP.i6t|, |Utilities.i6t|.
{\it Data Structure Support I: Basics}. |Number.i6t|, |Time.i6t|,
|Tables.i6t|, |Sort.i6t|, |Relations.i6t|, |Figures.i6t|.
{\it II: Block Values}. |Text.i6t|, |RegExp.i6t|, |Char.i6t|,
|UnicodeData.i6t|, |StoredAction.i6t|, |Lists.i6t|, |RelationKind.i6t|,
|BlockValues.i6t|, |Flex.i6t|.
{\it Virtual Machine Interface}. |ZMachine.i6t| {\it or} |Glulx.i6t| and
|FileIO.i6t|.
To elaborate:
{\it NI Control}. As well as containing commentary and I6 code, template
files can also contain commands to tell NI to do something more interesting
than simply copying over material verbatim into its output. Four of the
segments use this ability a great deal: the remaining segments hardly use
it at all. These four segments therefore don't fit anywhere in the diagram
of the software stack above. "Main.i6t" controls the top-level logic of NI
and gives the sequence of operations; "Load-.i6t" specifies the basic
kinds of value known to NI -- numbers, times, texts, rulebooks and so on;
"Output.i6t" is essentially the arrangement used to join all the many
fragments of I6 from the template and the I7 source text into a single
end-to-end I6 program which will become the story file; "Definitions.i6t"
defines many named constants which are used across the template.
{\it Mechanics of Play I: Rules}. "OrderOfPlay.i6t" is the highest-level
description of what happens when a story file runs: it contains the I6
|Main| routine, and definitions of the primitive rules in the most
important rulebooks.
"Actions.i6t" and "Activities.i6t" contain code which runs actions
and activities, respectively: these sit on top of "Rulebooks.i6t", which
performs general rulebook-running.
{\it Mechanics of Play II: Infrastructure}. "Parser.i6t" breaks down a
command typed by the player into a slate of variables which can be formed
into an action. "ListWriter.i6t" is a general-purpose service for printing
lists of objects satisfying various descriptions, and formatted in different
ways. "OutOfWorld.i6t" provides code to handle out-of-world actions not
needing direct access to VM internals: PRONOUNS and SUPERBRIEF, for instance.
"Tests.i6t" provides code for the testing commands -- TEST, ACTIONS,
SHOWME and so forth.
"WorldModel.i6t" contains code for performing object movements and the
like in such a way that the world model rules are preserved: it handles
component parts, decides touchability and so on. "Light.i6t" determines
the level of light and decides on visibility.
{\it Mechanics of Play III: Basic Services}. "Language.i6t" provides
English-language messages issued by template routines and the Standard
Rules during play: replacing this segment is the way to translate I7 story
files into other languages of play. (It's the equivalent of the old I6
"language definition files", and retains most of the same structure.)
"MStack.i6t" provides a small general-purpose memory stack.
"Chronology.i6t" performs the continuous monitoring required to ensure
that past-tense conditions work: for instance we can only determine whether
or not "the Black Door has been open" if we have spent the whole time so
far checking on whether it is open or not, and this is where the checking
is done. "Printing.i6t" handles paragraph-breaking, the printing of
object names with suitable articles attached, and miscellaneous other
printing needs. "RTP.i6t" issues run-time problem messages as needed:
these should appear only if the story file does something clearly illegal,
and point to bugs not yet removed from the author's code. "Utilities.i6t"
provides miscellaneous utility functions at a very low level, such as for
unsigned comparison of two numbers.
{\it Data Structure Support I: Basics}. Many kinds of value need no
maintenance, and little or no support. "Number.i6t" and "Time.i6t"
contain code to parse numbers and times of day from text typed by the
player, together with a few basic operations: for instance, the rounding
off of times of day. "Tables.i6t" provides access to table entries,
specified in a variety of direct and indirect ways; this makes use of
"Sort.i6t", which abstracts a choice of sorting algorithms for use on
tables and other I6 data. "Relations.i6t" provides code for testing and
asserting relations: the information about what is related to what else is
stored in a variety of different ways, depending on the relation, to make
best use of memory. "Figures.i6t" displays figures and plays back sound
effects, or rather, passes instructions to do so down to the VM.
{\it Data Structure Support II: Block Values}. Kinds of value can be divided
into the ordinary ones -- number, object, time and so on -- together with
"block values" such as text, stored action and list. Block values have
to be stored in dynamically allocated memory from a heap. It would be wasteful
to include all of this code, and to spare memory for the heap, if no block
values were actually needed, so the following segments are only compiled if
the source text makes specific reference to at least one block value.
"Text.i6t" manages strings of text, which can shrink or stretch to arbitrary
lengths: it makes use of "RegExp.i6t" for regular expression matching and
search-and-replace; and also of "Char.i6t" for code to deal with lower and
upper casing of letters, and "UnicodeData.i6t" to provide character set
details, mechanically converted from the Unicode 4.0 standard.
"StoredAction.i6t" manages stored actions: it can convert the current action
into a stored one, and also try a long-stored action so that it now takes
place. "Lists.i6t" manages the flexibly sized lists produced by values whose
kind is list of numbers, list of texts, list of lists of lists of stored
actions, and so forth: it can merge, insert, delete, resize, rotate, and
reverse lists, and makes use once again of "Sort.i6t" (q.v.) to sort them.
"BlockValues.i6t" provides the basic support for kinds of value which
can't be stored as single words of data.
At the lowest level, "Flex.i6t" manages flexible memory allocation as
required by "BlockValues.i6t": it organises the heap of unclaimed memory,
for instance, and maks allocations and deallocations when needed.
{\it Virtual Machine Interface}. Depending on the Settings used for the
I7 project being compiled, we either use "ZMachine.i6t" or "Glulx.i6t":
if Glulx, we also add "FileIO.i6t", which provides support for the
limited file-handling abilities offered by Glulx.
Properly speaking, there is one further template file: "Introduction.i6t".
It provides the commentary you are now reading, but has no other function,
contains no code, and is finished now anyway.