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

775 lines
28 KiB
Plaintext

B/outt: Output Template.
@Purpose: This is the superstructure of the file of I6 code output by NI:
from ICL commands at the top down to the signing-off comments at the bottom.
@-------------------------------------------------------------------------------
@p ICL Commands.
The Inform Control Language is a mini-language for controlling the I6 compiler,
able to set command-line switches, memory settings and so on. I6 ordinarily
discards lines beginning with exclamation marks as comments, but at the very
top of the file, lines beginning |!%| are read as ICL commands: as soon as
any line (including a blank line) doesn't have this signature, I6 exits
ICL mode. So, basically, we'd better do this here:
@c
{-call:Config::Inclusions::compile_icl_commands}
@p Other Configuration.
Setting the |Grammar__Version| constant is a rather creaky old way to tell
the I6 compiler to use more detailed grammar tables: GV1 has not in fact
been used since about 1994.
@c
Constant Grammar__Version 2;
@p Identification.
Both of the compiler and template layer, and of the story file to be produced.
The "library" identifying texts are now a little anachronistic, since the
template layer is not strictly speaking an I6 library in the same way as
the original: but it is surely the spiritual successor to 6/11N, so we
may as well mark it 6/12N.
@c
! This file was compiled by Inform 7: the build number and version of the
! I6 template layer used are as follows.
{-call:Config::Template::compile_build_number}
Constant LibSerial = "080126";
Constant LibRelease = "6/12N";
Constant LIBRARY_VERSION = 612;
{-call:Config::Plugins::define_IFDEF_symbols}
{-array:Plugins::Bibliographic::UUID_ARRAY}
{-call:Plugins::Bibliographic::compile_constants}
Default Story 0;
Default Headline 0;
{-routine:Extensions::Files::ShowExtensionVersions}
@p Use options.
Use options are translated into I6 constant declarations, and NI puts them
here:
@c
{-call:Config::Inclusions::UseOptions::compile}
#Ifndef USE_SCORING;
Constant USE_SCORING = {-value:default_scoring_setting};
#Endif;
@p Constants.
@c
{-segment:Definitions.i6t}
@p Global Variables.
These are not the only global variables defined in the template layer:
those needed locally only by single sections (and not used in definitions
of phrases in the Standard Rules, or referred to by NI directly) are defined
within those sections -- they can be regarded as unimportant implementation
details, subject to change at whim. The variables here, on the other hand,
are more important to understand.
(1) The first three variables to be defined are special in that they are
significant to very early-style Z-machine interpreters, where they are
used to produce the status line display (hence |sline1| and |sline2|).
The first variable must always equal a valid object number, which is why
we -- pretty weirdly -- set it equal to the placeholder object |InformLibrary|,
which takes no part in play, and is not a valid I7 object. This is not
typesafe in I7 terms, but that doesn't matter because initialisation
will correct it to a typesafe value before any I7 source text can execute.
(|sline1| and |sline2| are entirely unused on when we target Glulx.)
Once these variables are defined, the sequence of definition of the rest
is not significant.
(2) The |say__*| are used for the finite state machine used in printing
text, which keeps track of automatic paragraph breaking and the like. For
details see the "Printing.i6t" section.
(3) |standard_interpreter| is used only for the Z-machine VM, and is always
0 for Glulx. For Z, a non-zero value here is the version number of the
{\it Z-Machine Standards Document} which the interpreter claims to support,
in the form (upper byte).(lower). |undo_flag|, similarly, behaves slightly
differently on the two platforms according to whether they support multiple
consecutive UNDOs. UNDO basically works by taking memory snapshots of the
whole VM ("saving UNDO") to revert to at a later point ("performing UNDO"),
so it is expensive on memory, and traditional VMs can only store a single
memory snapshot -- making two UNDOs in a row, going back two steps,
impossible. Given this, |undo_flag| has three possible states: 0 means
UNDO is not available at all, 1 means it is not available now because
there is no further saved state to go back to from here, and 2 means it
is available.
(4) |deadflag| in normally 0, or false, meaning play continues; 1 means the
game ended in death; 2 for ended in victory; higher numbers represent
exotic endings. (As from May 2010, the use of 2 for victory is deprecated,
and a separate flag, |story_complete|, records whether the story is
"complete" in the sense that we don't expect the player to replay.)
|deadflag| switching state normally triggers an end to rulebook processing,
so is the single most important global variable to the running of a story
file.
(5) At present, |time_rate| is not made use of in I7: if positive, it is
the number of minutes which pass each turn; if negative, the number of
turns which pass each minute. This is quite a neat way to approximate a
wide range of time steps with an integer such that fractions are exact
and we can approximate any duration to a fair accuracy (the worst case
being $3/4$ minute, where we have to choose between 1 minute or $1/2$
minute).
(6) Note that |notify_mode| is irrelevant if the use option "Use no scoring"
is in force: it isn't looked at, and can't be changed, and shouldn't have
an effect anyway since |score| will never be altered.
(7) |player| is a variable, not a constant, since the focus of play can
change. |SACK_OBJECT| is likewise an unexpected variable: in the I6
library, there could only be one player's holdall, a single rucksack-like
possession which had to be the value of the constant |SACK_OBJECT|. Here we
define |SACK_OBJECT| as a global variable instead, the value of which is
the player's holdall currently in use. |visibility_ceiling| is the
highest object in the tree visible from the player's point of view:
usually the room, but sometimes nothing (in darkness), and sometimes a
closed non-transparent container.
(8) See "OrderOfPlay.i6t" for the meaning of action variables.
(9) This is a slate of global variables used by the parser to give some
context to the general parsing routines (GPRs) which it calls; in the I6
design, any object can provide its own GPR, in the form of a |parse_name|
property. GPRs are in effect parser plug-ins, and I7 makes extensive use
of them.
(10) Similarly, variables for the parser to give context to another sort
of plug-in routine: a scope filter. I7 uses these too.
(11) The |move_*| variables are specific to the |##Going| action.
(12) These variables hold current settings for listing objects and,
more elaborately, performing room descriptions.
(13) The current colour scheme is stored in variables in order that it can
be saved in the save game state, and changed correctly on an UNDO: if it
were a transient state inside the VM interpreter's screen model, then a
RESTORE or UNDO will upset what the original author may have intended the
appearance of text in particular scenes to be. (Cf. Adam Cadre's I6 patch
|L61007|.)
(14) These pixel dimensions are used both for the Glulx and v6 Z-machines,
but not for the more commonly used versions 5 or 8, whose screen model is
based on character cells.
(15) For debugging. |debug_flag| is traditionally called so, but is actually
now a bitmap of flags for tracing actions, calls to object routines, and so on.
@c
! [1]
Global location = InformLibrary; ! does not = I7 "location": see below
Global sline1; Global sline2;
! [2]
Global say__p = 1; Global say__pc = 0; Global say__pc_save = 0;
Global say__n; Global say__comp;
Global los_rv = false;
Global parameter_object; ! = I7 "parameter-object" = I7 "container in question"
Global parameter_value; ! not typesafe in I7
Array deferred_calling_list --> 27;
Global property_to_be_totalled; ! used to implement "total P of..."
Global property_loop_sign; ! $+1$ for increasing order, $-1$ for decreasing
Global suppress_scope_loops;
Global temporary_value; ! can be used anywhere side-effects can't occur
Global enable_rte = true; ! reporting of run-time problems is enabled
#ifdef TARGET_ZCODE;
Constant BLOCKV_STACK_SIZE = 224;
#ifnot;
Constant BLOCKV_STACK_SIZE = DynamicMemoryAllocation/4;
#endif;
Array blockv_stack --> BLOCKV_STACK_SIZE;
Global I7SFRAME;
Global TEXT_TY_RE_Err = 0;
Array LocalParking --> 64;
! [3]
Global standard_interpreter = 0;
Global undo_flag;
! [4]
Global deadflag = 0;
Global story_complete = 0;
Global resurrect_please = false;
! [5]
Global not_yet_in_play = true; ! set false when first command received
Global turns = 1; ! = I7 "turn count"
Global the_time = NULL; ! = I7 "time of day"
Global time_rate = 1;
Constant NUMBER_SCENES_CREATED = {-value:NUMBER_CREATED(scene)};
Constant SCENE_ARRAY_SIZE = (NUMBER_SCENES_CREATED+2);
Array scene_started --> SCENE_ARRAY_SIZE;
Array scene_ended --> SCENE_ARRAY_SIZE;
Array scene_status --> SCENE_ARRAY_SIZE;
Array scene_endings --> SCENE_ARRAY_SIZE;
Array scene_latest_ending --> SCENE_ARRAY_SIZE;
! [6]
Global score; ! = I7 "score"
Global last_score; ! = I7 "last notified score"
Global notify_mode = 1; ! score notification on or off
Global left_hand_status_line = T_SL_Location; ! = I7 "left hand status line"
Global right_hand_status_line = T_SL_Score_Moves; ! = I7 "right hand status line"
! [7]
Global player; ! = I7 "player"
Global real_location; ! = I7 "location"
Global visibility_ceiling; ! highest object in tree visible to player
Global visibility_levels; ! distance in tree to that
Global SACK_OBJECT; ! current player's holdall item in use
! [8]
Global act_requester;
Global actor; ! = I7 "person asked" = I7 "person reaching"
Global actors_location; ! like real_location, but for the actor
Global actor_location; ! = I7 "actor-location"
Global action;
Global meta; ! action is out of world
Global inp1;
Global inp2;
Array multiple_object --> MATCH_LIST_WORDS; ! multiple-object list (I6 table array)
Global toomany_flag; ! multiple-object list overflowed
Global multiflag; ! multiple-object being processed
Global multiple_object_item; ! item currently being processed in multiple-object list
Global noun; ! = I7 "noun"
Global second; ! = I7 "second noun"
Global keep_silent; ! true if current action is being tried silently
Global etype; ! parser error number if command not recognised
Global trace_actions = 0;
Global untouchable_object;
Global untouchable_silence;
Global touch_persona;
Global special_word; ! dictionary address of first word in "[text]" token
Global consult_from; ! word number of start of "[text]" token
Global consult_words; ! number of words in "[text]" token
Global parsed_number; ! value from any token not an object
Global special_number1; ! first value, if token not an object
Global special_number2; ! second value, if token not an object
Array parser_results --> 16; ! for parser to write its results in
Global parser_trace = 0; ! normally 0, but 1 to 5 traces parser workings
Global pronoun_word; ! records which pronoun ("it", "them", ...) caused an error
Global pronoun_obj; ! and what object it was thought to refer to
Global players_command = 100; ! = I7 "player's command"
Global matched_text; ! = I7 "matched text"
Global reason_the_action_failed; ! = I7 "reason the action failed"
Global understand_as_mistake_number; ! which form of "Understand... as a mistake"
Global particular_possession; ! = I7 "particular possession"
! [9]
Global parser_action; ! written by the parser for the benefit of GPRs
Global parser_one;
Global parser_two;
Global parameters; ! number of I7 tokens parsed on the current line
Global action_to_be; ! (if the current line were accepted)
Global action_reversed; ! (parameters would be reversed in order)
Global wn; ! word number within "parse" buffer (from 1)
Global num_words; ! number of words in buffer
Global verb_word; ! dictionary address of command verb
Global verb_wordnum; ! word number of command verb
! [10]
Global scope_reason = PARSING_REASON; ! current reason for searching scope
Global scope_token; ! for "scope=Routine" grammar tokens
Global scope_error;
Global scope_stage; ! 1, 2 then 3
Global advance_warning; ! what a later-named thing will be
Global reason_code = NULL; ! for the I6 veneer
Global ats_flag = 0; ! for AddToScope routines
Global ats_hls;
! [11]
Global move_pushing;
Global move_from;
Global move_to;
Global move_by;
Global move_through;
! [12]
#Ifdef DEFAULT_BRIEF_DESCRIPTIONS;
Global lookmode = 1; ! 1 = BRIEF, 2 = VERBOSE, 3 = SUPERBRIEF
#Endif;
#Ifdef DEFAULT_VERBOSE_DESCRIPTIONS;
Global lookmode = 2; ! 1 = BRIEF, 2 = VERBOSE, 3 = SUPERBRIEF
#Endif;
#Ifdef DEFAULT_SUPERBRIEF_DESCRIPTIONS;
Global lookmode = 3; ! 1 = BRIEF, 2 = VERBOSE, 3 = SUPERBRIEF
#Endif;
#Ifndef lookmode;
Global lookmode = 2; ! 1 = BRIEF, 2 = VERBOSE, 3 = SUPERBRIEF
#Endif;
Global c_style; ! current list-writer style
Global c_depth; ! current recursion depth
Global c_iterator; ! current iteration function
Global lt_value; ! common value of list_together
Global listing_together; ! object number of one member of a group being listed together
Global listing_size; ! size of such a group
Global c_margin; ! current level of indentation printed by WriteListFrom()
Global inventory_stage = 1; ! 1 or 2 according to the context in which list_together uses
Global prior_named_noun; ! for adaptive text generation
Global prior_named_list; ! ditto: length of list of items
Global prior_named_list_gender; ! ditto: common gender of list of items, or -1
Global story_tense = 1; ! ditto: present tense
Global story_viewpoint = 2; ! ditto: second person singular
! [13]
Global clr_fg = 1; ! foreground colour
Global clr_bg = 1; ! background colour
Global clr_fgstatus = 1; ! foreground colour of statusline
Global clr_bgstatus = 1; ! background colour of statusline
Global clr_on; ! has colour been enabled by the player?
Global statuswin_current; ! if writing to top window
! [14]
Global statuswin_cursize = 0;
Global statuswin_size = 1;
! [16]
Global debug_flag = 0;
Global debug_rules = 0;
Global debug_scenes = 0;
Global debug_rule_nesting;
@p VM-Specific Code.
These sections of code contain different definitions of the same routines,
and in some cases the same arrays, to handle low-level functions in the
virtual machine -- saving the game, performing UNDO, parsing typed text into
dictionary word addresses and so on.
@c
#Ifdef TARGET_GLULX;
{-segment:Glulx.i6t}
#Endif;
#Ifdef TARGET_ZCODE;
{-segment:ZMachine.i6t}
#Endif;
@p Compass.
I6 identified compass directions as being children of the pseudo-object
|Compass|, so we define it. (Note that |Compass| is not a valid I7 object,
and is used for no other purpose.) Because of the traditional structure
of language definitions, this needs to come first.
@c
Object Compass "compass" has concealed;
@p Language of Play.
The equivalent of I6's language definition file, though here the idea is
that a translation should have an inclusion to replace the "Language.i6t"
segment, which contains the English definition.
@c
{-segment:Language.i6t}
Default LanguageCases 1;
@p The Old Library.
The I6 library consisted essentially of the parser, the verb routines, and
a pile of utilities and world-modelling code, of which the biggest single
component was the list-writer. The parser lives on below; the verb routines
are gone, with the equivalent functionality having moved upstairs into
I7 source text in the Standard Rules; and the rest of the library largely
lives here:
@c
{-segment:Light.i6t}
{-segment:ListWriter.i6t}
{-segment:Utilities.i6t}
@p Parser.
The largest single block of code in the traditional I6 library part of the
template layer is the parser.
The two pseudo-objects |InformParser| and |InformLibrary| are relics of the
object-oriented approach in I6, and are used only very slightly in the
template layer; they are not used at all in I7, and are not valid for the
"object" kind of value.
The parser includes arrays for typed text and some parsing information
derived from it, and if these should overrun it would cause enigmatic
bugs, as the next arrays in memory would be corrupted: as a tripwire,
the |Protect_I7_Arrays| array consists of two magic values in sequence.
If it is ever discovered to contain the wrong data, the alarm sounds.
@c
Object InformParser "(Inform Parser)" has proper;
{-segment:Parser.i6t}
[ ParserError error_type;
if (error_type) PrintSingleParagraph(error_type);
rfalse;
];
Object InformLibrary "(Inform Library)" has proper;
Array Protect_I7_Arrays --> 16339 12345;
@p Order of Play.
The |Main| routine, where execution begins, and the primitive rules in the
principal rulebooks.
@c
{-segment:OrderOfPlay.i6t}
@p Properties.
Some either/or properties are compiled to I6 attributes, which must be
predeclared, so we do that first. (All other properties can simply be
used without declaration.)
What then follows is a table of property metadata: in particular, specifying
which properties can be used with which I6 classes or objects. Policing
this at run-time costs a little speed, but traps many errors of programming,
and keeps everything typesafe. It is the price we pay for the relatively
lenient compile-time checking of I7's "object" kind of value. To make
it as efficient as possible, we calculate offsets into the metadata: this
has to be done (once) at run-time, with the routine compiled.
@c
{-call:Properties::alias_translations}
{-call:Properties::Implementation::OfObjects::compile_attributes}
{-array:Properties::Implementation::OfObjects::property_metadata}
Constant attributed_property_offsets_SIZE 48;
Array attributed_property_offsets --> attributed_property_offsets_SIZE;
Constant valued_property_offsets_SIZE (100 + {-value:NUMBER_CREATED(property)} + INDIV_PROP_START-48);
Array valued_property_offsets --> valued_property_offsets_SIZE;
{-routine:Properties::Implementation::OfObjects::CreatePropertyOffsets}
@p Activities.
These are numbered upwards from 0 in order of creation. The following arrays
taken together provide, for each activity number: (i) the rulebook numbers
for the before, for, and after stages of the activity, and (ii) a flag
indicating whether the activity is "future action"-capable, that is, is
a parsing activity allowed to make use of the action which conjecturally
might result from the current grammar line being parsed. (This is called
the "action to be", hence "atb".)
@c
Constant NUMBER_RULEBOOKS_CREATED = {-value:NUMBER_CREATED(rulebook)};
{-call:Code::Activities::compile_activity_constants}
{-array:Code::Activities::Activity_before_rulebooks}
{-array:Code::Activities::Activity_for_rulebooks}
{-array:Code::Activities::Activity_after_rulebooks}
{-array:Code::Activities::Activity_atb_rulebooks}
@p Relations.
@c
{-call:Semantics::Relations::compile_defined_relation_constants}
@p Printing Routines.
@c
{-call:Kinds::RunTime::compile_data_type_support_routines}
{-routine:Kinds::RunTime::I7_Kind_Name}
{-routine:Code::Rulebooks::RulebookOutcomePrintingRule}
@p Object Tree.
The I6 object tree contains |Class| definitions as well as objects, but
we precede both with a pseudo-object called |property_numberspace_forcer|.
It does nothing except to ensure that properties are declared in I6 in the
same sequence as I7 (which need not otherwise happen); it plays no part
in play, and is not a valid I7 "object" value.
@c
{-log:Compiling the storage for the model world}
{-call:World::Compile::compile}
@p Tables.
The initial state of the I6 arrays corresponding to each I7 table: see
"Tables.i6t" for details.
@c
{-log:Compiling the tables}
{-callv:Data::Tables::complete}
{-call:Data::Tables::compile}
@p Equations.
Routines to evaluate from equations.
@c
{-log:Compiling the equations}
{-call:Data::Equations::compile}
@p Actions.
@c
{-log:Compiling the named action patterns}
{-call:Plugins::Actions::Patterns::Named::compile}
{-log:Compiling the action routines}
{-array:Plugins::Actions::ActionData}
{-array:Plugins::Actions::ActionCoding}
{-array:Plugins::Actions::ActionHappened}
{-call:Plugins::Actions::compile_action_routines}
{-routine:Plugins::Parsing::Lines::MistakeActionSub}
@p Phrases.
The following innocent-looking commands tell NI to compile I6 definitions
for all of the rules which are not I6-written primitives, and also for
adjective definitions, so it results in a fairly enormous cataract of code.
@c
{-log:Compiling first block of phrases}
{-call:Code::Phrases::compile_first_block}
@p Timed Events.
Some of the phrases are simply called in the course of other phrases, but
some are rules in rulebooks or in the table of timed events, so those
come next:
@c
{-array:Code::Phrases::TimedEventsTable}
{-array:Code::Phrases::TimedEventTimesTable}
@p Rulebooks.
The literally hundreds of rulebooks are set up here. (In the end a rulebook
is only a (word) array of rule addresses, terminated with a |NULL|.)
@c
{-log:Compiling the rulebooks}
{-array:Code::Phrases::rulebooks_array}
{-call:Code::Phrases::compile_rulebooks}
@p Scenes.
@c
{-log:Compiling scene details}
{-routine:Plugins::Scenes::DetectSceneChange}
#IFDEF DEBUG;
{-routine:Plugins::Scenes::ShowSceneStatus}
#ENDIF;
@p The New Library.
The gleaming, aluminium and glass extension to the library: almost all of it
material new in I7 usage.
@c
{-log:CTNL}
{-segment:Actions.i6t}
{-segment:Activities.i6t}
{-segment:Figures.i6t}
{-segment:FileIO.i6t}
{-segment:MStack.i6t}
{-segment:OutOfWorld.i6t}
{-segment:Printing.i6t}
{-segment:Relations.i6t}
{-segment:RTP.i6t}
{-segment:Rulebooks.i6t}
{-segment:Sort.i6t}
{-segment:Tables.i6t}
{-segment:WorldModel.i6t}
@p Parsing Tokens.
GPRs, scope and noun filters to be used in grammar lines, but no actual
grammar lines as yet.
@c
{-callv:Plugins::Parsing::Verbs::prepare}
{-call:Plugins::Parsing::Verbs::compile_conditions}
{-log:Compiling GPR tokens for parsing various kinds of value}
{-segment:Number.i6t}
{-segment:RealNumber.i6t}
{-segment:Time.i6t}
{-call:Plugins::Parsing::Tokens::Values::compile_type_gprs}
@p Text generation.
@c
{-routine:Semantics::ConjugateVerb}
{-call:Semantics::Adjectives::Meanings::agreements}
@p Testing commands.
@c
#IFDEF DEBUG;
{-call:Plugins::Parsing::TestScripts::write_text}
{-segment:Tests.i6t}
{-routine:Plugins::Parsing::TestScripts::InternalTestCases}
#ENDIF; ! DEBUG
@p I6 Inclusions.
This paragraph contains no code, by default: it's a hook on which to hang
verbatim I6 material.
@c
! "Include (- ... -)" inclusions with no specified position appear here.
@p Entries in constant lists.
Well: most of them, anyway. In particular, all of those which are lists of
texts with substitution will be swept up, which is important for timing
reasons. A second round later on will catch any later ones.
@c
{-call:Data::Lists::check}
{-call:Data::Lists::compile}
@p To Phrases.
We now compile all of the remaining code in the source text: the "To..."
phrases and all of their attendant text routines, loop-over-scope routines
and so on.
We now have to be quite careful about the sequence of events. Compiling the
text routines is an irrevocable step, after which we must not compile any
new text with substitutions. On the other hand we mustn't leave it any later,
because a text substitution might contain references to the past, or involve
propositions which must be deferred into routines.
@c
{-log:Compiling second block of phrases}
{-call:Code::Phrases::compile_as_needed}
{-call:Data::Strings::compile_responses}
{-call:Data::Lists::check}
{-call:Data::Lists::compile}
{-call:Code::Phrases::compile_as_needed}
{-callv:Data::Strings::allow_no_further_text_subs}
{-log:Compiling noun and scope filter tokens}
{-call:Plugins::Parsing::Tokens::Filters::compile}
@p Chronology.
Similarly, this is where we wrap up all references to past tenses: after this
point, we cannot safely compile any I7 condition in the past tense.
@c
{-log:Compiling chronology}
{-segment:Chronology.i6t}
{-callv:Code::Chronology::allow_no_further_past_tenses}
@p Grammar.
This is the trickiest matter of timing. We had to leave the grammar lines
until now because the past-tense code above might have needed to investigate
whether the player's command matched a given pattern at some time in the
past (a case which arose naturally in one of the example games, so which
should not be dismissed as an aberration). This is therefore the earliest
point at which we can know for sure that no further grammar lines are
needed.
@c
{-log:Compiling I6 Verb directives}
{-call:Plugins::Parsing::Verbs::compile_all}
{-log:Compiling noun and scope filter tokens}
{-call:Plugins::Parsing::Tokens::Filters::compile}
#IFTRUE ({-value:no_verb_verb_defined} == 1);
[ UnknownVerb; verb_wordnum = 0; return 'no.verb'; ];
[ PrintVerb v;
if (v == 'no.verb') { print "do something to"; rtrue; }
rfalse;
];
#Ifnot;
[ UnknownVerb; rfalse; ]; [ PrintVerb v; rfalse; ];
#ENDIF;
@p Deferred Propositions.
Most conditions, such as "the score is 10", and descriptions, such as
"open doors which are in lighted rooms", are translated by NI into
propositions in a form of predicate calculus. Sometimes these can be
compiled immediately to I6 code, but other times they involve complicated
searches and have to be "deferred" into special routines which will
perform them. This is where we compile those routines.
@c
{-log:Compiling routines from predicate calculus}
{-call:Semantics::Relations::compile_defined_relations}
{-call:Properties::Measurement::Adjectives::compile_MADJ_routines}
{-call:Calculus::Propositions::compile_remaining_deferred}
{-callv:Calculus::Deferrals::allow_no_further_deferrals}
@p Miscellaneous Loose Ends.
And we still aren't done, because we still have:
(1) Routines which switch between possible interpretations of phrases
by performing run-time type checking. (Note that these cannot involve
grammar, or the past tenses, or text substitutions, or deferred propositions.)
(2) Arrays holding constant lists, such as |{2, 3, 4}|, if any.
(3) The string constants, named in the pattern |SC_*|, in alphabetical order.
(This ensures that their packed addresses will have unsigned comparison
ordering equivalent to alphabetical order.)
(4) "Stub" I6 constants for property names where properties aren't used,
to prevent them causing errors if they are referred to in code but not
actually present in any object (as can easily happen with extensions
presenting optional features which the user chooses not to employ).
|cap_short_name| is similarly stubbed: this doesn't correspond to any
I7 property, but is used by NI to record capitalised forms of the printed
name (which in turn goes into |short_name|).
(5) Counters are used to allocate cells of storage to inline phrases which
need a permanent state associated with them: see the Standard Rules. Since
all I7 source text has been compiled by now, we know the final values of
the counters, and therefore the amount of storage we need to allocate.
(6) Similarly, each "quotation" box needs its own cell of memory.
@c
{-call:Data::Lists::check}
{-call:Data::Lists::compile}
{-call:Data::Strings::compile}
{-call:Properties::Implementation::OfObjects::compile_stub_properties}
#IFNDEF cap_short_name;
Constant cap_short_name = short_name;
#ENDIF;
{-call:Formats::Inform6::Labels::Counters::compile_allocated_storage}
Array Runtime_Quotations_Displayed --> {-value:extent_of_runtime_quotations_array};
@p Block Values.
These are values which are pointers to more elaborate data on the memory heap,
rather than values in themselves: they point to "blocks". A section of code
handles the heap, and there is then one further section to support each of
the kinds of value in question.
@c
{-call:Kinds::RunTime::compile_heap_allocator}
{-call:Code::Phrases::Constants::compile_closures}
{-call:Kinds::compile_runtime_id_structures}
{-segment:Flex.i6t}
{-segment:BlockValues.i6t}
{-segment:Text.i6t}
{-segment:RegExp.i6t}
{-segment:StoredAction.i6t}
{-segment:Lists.i6t}
{-segment:Combinations.i6t}
{-segment:RelationKind.i6t}
{-array:Plugins::Figures::tableoffigures}
{-array:Plugins::Sounds::tableofsounds}
{-callv:Code::Rules::check_response_usages}
{-call:Kinds::RunTime::compile_block_constants}
{-callv:Code::Phrases::Timed::check_for_unused}
@p Signing off.
And that's all, folks.
@c
! End of automatically generated I6 source
! --------------------------------------------------------------------------