6 TALKING TO THE COMPILER
6.0 Interludes and User-Compiler Communication
GIN provides extensive facilities for the user to obtain information from the compiler and to make it do something other
than what it would normally do. Thereare two main facilities,
interludes and compiler variables.
An interlude is a section of code which is to be temporarily incorporated within and obeyed by the compiler and which does not form part of the program under compilation. Interludes are used for two main purposes:
- “Trivial” interludes are used by the directives #BIP, #DUMP and #GO to provide request slips and other data which contain more information than could conveniently be provided as parameters to directives. Essentially the information is stored directly in an area accessible both to the user and to the compiler, and at an appropriate time the compiler receives and acts upon it. In the case of #BIP and #DUMP the interlude must, be entered, but frequently the only instruction returns control to GIN.
- “Non-trivial” interludes are entered by the compiler after they have been compiled. As long as the limit on the size of the interlude (see Section 6.2 below) is observed any instructions whatever may be obeyed. It is possible to make use of a number of the compiler's own internal routines to extract and even alter information. Such interludes have been used:
- to print out on the console typewriter the size of a program.
- to list a compiled segment in a different format from #PRINT.
- to give a list of all the segments compiled, with the pages where their listings can be found.
- to list the stored source of a macro.
- to forget the existence of a macro so it can be recompiled.
- to dump to tape the GEORGE loader-allocator.
- to change the value of an identifier.
A compiler variable is any of the words within the compiler whose use has been described in this manual. It is possible to insert the value of any compiler variable in any location in the program or in an interlude, or to quote it wherever an arithmetical expression is needed, or to inspect or alter it by interlude or by #DEFINE. Since many of the variables accessible to the user are essential to correct compilation, altering their values can have far-reaching effects. Nevertheless, no attempt is now made to restrict such changes (except by refraining from publishing any information) on the grounds that new uses are constantly being found for them.
6.1 Compiler Variables
A compiler variable is an octal or decimal number not exceeding
76 followed by a question mark; e.g. 32? The meaning of a
compiler variable is as described in Section 10.2 for the
variable concerned. A small number of variables are never
changed by GIN, and most of these should not be changed by the
user. A list is given later in this Section of some variables
which it is known can usefully be changed by the user without
unpredictable or harmful effects.
A compiler variable expression (also called a compound compiler
variable) is any expression one or more of whose terms is a
compiler variable. Certain compiler variable expressions give
useful information in the same way as simple compiler variables.
When GIN evaluates a compiler variable it converts the decimal
or octal number to binary and adds to this the base address of
the compiler variable table. (Thus the variables 0? to 74?
occupy 75 consecutive words within GIN). It then extracts the
contents of this word in the table and substitutes that in the
expression being evaluated.
Certain of the compiler variables, such as 18?, 19?, 35? 36?
point at subsidiary tables rather than themselves containing
useful information, and some of these subsidiary tables also
contain pointers to other tables.
ALTERING COMPILER VARIABLE VALUES
The value of an individual compiler variable may be altered by #DEFINE thus:
#DEF 20?=372 Until 20? is next altered, wherever it is referred to 372 will be substituted #DEF 2?=2?+1023� 2? is rounded up to the next multiple of 1024.
A compiler variable may be altered within an interlude, but it must then be referred to as 18?+3]+n: e.g.
STO 0 18?+3]+0 [ALTERS 0?
Incidentally, you should note the distinction between:
LDN 0 0?
which picks up the value of 0? when that line of the interlude was compiled (mod 4096), and
LDX 0 18?+3]+0
which picks up the value when it is obeyed in an interlude - it is possible that the value could have changed between compiling the line and obeying it.
ALTERING COMPILER VARIABLE EXPRESSIONS
It is possible to alter words within the compiler not accessible directly by compiler variables by the use of #DEFINE. However, it is very important to realize that the ] at the end of the expression giving the contents of a compiler word is omitted when that word is being #DEFINED; thus
#DEF 19?+0=FRED #DEF BILL=19?+0]
will set BILL equal to FRED. In particular, the effects of #DEF 19? and #DEF 19?+0 are different. The reason for this is that when the #DEFINE routine recognizes 19? it will set the word to be altered to be 676 say (if the base of the compiler variable area is 657). When it reads “+0” it takes the contents of word 676, say 860, and adds zero to it to get the address of the word to be reset. This is an inconsistant usage and one liable to create confusion, but it is now too well established to be worth changing.
USING COMPILER VARIABLES IN EXPRESSIONS
Up to GIN512 it was not possible to bracket GIN expressions, and when using sub-expressions such as 19?+0] which are liable to be thought of as single units this was rather frustrating. Suppose the user would like to write (197+3])+(197+1]), GIN could not evaluate this, however, and we had to write :
#DEF 20?=19?+3] and then refer to 19?+1]+20? (Remember that "n?" is evaluated as a unit).
From GIN513 onwards bracketed expressions are available, which makes the the use of compiler variables in expressions rather easier. However, care must be taken to insert brackets where they are needed;
19?+3]+19?+1]
is by no means the same thing as
(19?+3])+(19?+1])
and the latter is much more likely to be meaningful. As a rule it is safer to ensure that anything of the form m?+n]+p]+…, which should be treated as a term in its own right, appears in parentheses.
WORDS WHICH MAY BE ALTERED
0? | May be #DEFINEd to anything less than 1024. If altered by an interlude, Bit 0 must be preserved. (#DEFINE deals with this). |
1? | #LIST is usually better |
2? | May be increased at any time outside an overlay to provide an unused area on backing store. May be decreased outside an overlay in order to cause the next segment to over-write a segment previously compiled. If this is done it must be reset after #END to the greatest value it has ever reached before the next occurrence of the following directives: #SEGMENT, #MEND, #DUMP, #BIP, #DELETE, #GO, #RESTORE. Inside an overlay, may be increased or decreased for the purposes mentioned above subject to the constraints above and also subject to the constraint that at the end of the overlay 2? must have increased overall by the length in words of the overlay. See 37? |
3? | Should be changed only by #ORDINARY or #EXTENDED |
20?-23? | May be altered as an when desired. GIN never uses them. |
24?-26? | May be altered as and when desired except in GEORGE source. |
33? | May be used to adjust the count of compilation errors. |
37? | 0nly meaningful within an overlay. 2?-37? must be the same at the end of any overlay (after #END of the last segment) as it was at the beginning of the overlay. The difference between the value 37? at the end of the overlay and the beginning must be the length in words of the overlay. (2? must have increased by the same amount). |
39?-40? | May be altered to change the headline on each page. Other words will be changed and used by GIN. Certain words, especially 45? (version of GIN), 47?, 48? may be used by programs. |
43?-55? | As above |
59? | As above |
63? | As above |
18?+1]+7] to 18?+1]+13] | In accordance with individual specifications. |
18?+1]+23 | As above |
18?+1]+55] to 18?+1]+57] | As above |
18?+7]+7] to 18?+7]+20] | As above |
19?+0] to 19?+0] | Without restriction |
31?+0] | In Executive versions of GIN only, this word may be zeroised to cause GIN to forget about forbidden areas already declared : see Section 4.6 |
The principle used in compiling this list has been 'Better safe than sorry'. If you have reason to believe that a useful effect could be obtained by changing the contents of any other word you should ask the person currently responsible for GIN for advice. This advice may take the form of consent to altering a word, of information about why a given word cannot be altered by the user, or of suggestions about how the desired effect might otherwise be obtained.
6.2 Interludes
Interludes may be compiled at any time. It is even possible
to compile them before #CORE if no macros or variables are used.
If an interlude is compiled outside a segment, it will be stored
at the beginning of the segment buffer and may be up to 1152
words long. If it is compiled inside a segment, it will be
stored immediately after the most recently compiled word, and
the maximum length is then 1024 less the number of words so far
compiled in the segment.
Interludes must be compiled in #ORDINARY mode; if required the
mode can be changed again afterwards. All interludes must now
be capable of operating in either 15-bit or 22-bit address mode,
as GIN may be using either. This involves making BUX, BCHX and
BDX branch to the following instruction (£) and counting in
another accumulator, and making no assumptions about the amount
of truncation performed by LDN and similar instructions.
The physical end of an interlude is signified by the #JUMP
directive, which also specifies the address of the first
instruction to be obeyed. On entry X0 contains a link back to
GIN, which may be saved somewhere in the interlude but must be
restored before returning to the compiler by EXIT 0 0.
Except before #CORE, interludes may use local labels freely as
long as they do not conflict with those used in the current or
immediately preceding segment. If two or more interludes follow
consecutively, later ones must avoid using the names of labels
in earlier ones. Similarly, if an interlude is inside a segment
its labels can be used later in the segment.
Interludes after #CORE may use universal identifiers without
restriction.
It is possible, and often useful, to store interludes within
macros, especially if they perform a generalised function which
may need to be repeated. Local identifiers within such macros will
be freed in the usual way.
It can be assumed that any address within an interlude is below
word 4096, and can therefore be referred to directly by instructions.
(This is only true of the first 1024 words in Executive GIN).
Input and output can be made to take place on any peripheral
which has been opened or allotted by GIN. Magnetic tapes are
not opened until they are referred to by a directive other than
#OFR or #OFW, and so may not be available. Any other peripherals
required should be obtained by the interlude and released when
finished with.
Some examples of interludes are given at 10.5, and should be studied carefully.
6.3 Notes on compiler subroutines and interlude writing
There are now quite a large number of subroutines which can
be used within interludes. All of them are routines which
GIN uses for its own purposes. Anyone who is likely to write
an interlude which makes use of them will appreciate that the
misuse of such routines can lead to almost any kind of disaster.
For this reason, any user who has any doubt about how to use any
of the routines should feel free to ask for advice and information
from the person responsible for GIN. It may well be that the
details of a routine given in this manual are not sufficiently
clear and complete for its successful use, and often this will
only appear when someone tries to use it.
Similarly, the information in the manual on GIN's internal formats
is likely to be incomplete and even to change with a new Version
of the compiler. Obviously the user is well advised to write
his interludes so as to be as independent as possible of these
formats. The use of the subroutines provided will help very
substantially in this respect.
A complete list of the subroutines is given at Section 10.2.18?+2].
All of them are accessible by
CALL X 18?+2]+n]
where X depends on n and is listed there, except that No. 21 must be entered by
BRN 18?+2]+21]
The user will find that he needs to know about some of GIN's
conventions in order to write successful interludes.
The most important thing to remember in this connection is that
all pointers to information held in the workfile are kept as
workfile addresses in up to 22 bits. Before any such information
is accessed the corresponding core address must be obtained by
calling 18?+2]+6], or if the information will be altered in any
way 18?+2]+7].
The area of corestore between 70? and 69?-1 is available for
use within the interlude, but 70? and 69? must be the same
after the interlude as they were before.
It is possible to obtain space for permanent use by increasing 32?
before #CORE by the amount required. This space will be in corestore.
It is possible to obtain up to 126 words of workfile space at a time
by calling 18?+2]+12]. The address of this area will of course need to
be remembered in an appropriate way. In each case, the areas obtained
will be ignored by the compiler, and will be available after a dump.
Using a subroutine in the wrong way can lead to almost any kind of failure.
Most of the routines do not check any input data, and those that do will
mostly cause entry to the GIN postmortem routines or an error halt.
It is always possible to enter GIN postmortem “voluntarily” by branching
to address 24.
If you need a subroutine not listed in the manual, please apply to the person responsible for GIN; if possible, it will be made available and documented for the next GIN version.