@V9 0
@R3 USE OF MUTL
@S23.1 INTRODUCTION
@BFor each Pascal construct an example of the MUTL sequence
generated by the compiler is given, together
with comments on the intended action.@
@BThe constructs are presented in the following order:@
@
@M3.2  Label specification and declaration     @
@N3.3  Constant definition@
@N3.4  Type definition@
@N3.5  Variable declaration@
@N3.6  Procedure declaration@
@N3.7  Statements@
@N     3.7.1 Constants@
@N     3.7.2 Variables@
@N     3.7.3 Expression evaluation@
@N     3.7.4 Procedure reference@
@N     3.7.5 Assignments@
@N     3.7.6 Heap management@
@N     3.7.7 Control constructs@
@N3.8  MUTL housekeeping@
@S23.2 LABEL SPECIFICATION AND DECLARATION
@STL.LABEL.SPEC([SYMB.NAME],LABELUSE)
@BLabel use distinguishes between a source label or
a compiler generated label.
@STL.LABEL(LABEL)
@BThis procedure declares the label.
In order to allow non-local jumps the compiler declares a label
variable whenever a label is declared.
@X %|
@STL.S.DECL([""],%30,0)
@S23.3 CONSTANT DEFINITION
@BNo MUTL call is made as the constant is held in
compiler tables, except in the case
of string constants. See 3.7.1 for definition of string constants.
@S23.4 TYPE DEFINITION
@BThe Pascal basic types have the following MUTL
names:@
@T# 19
@
#Boolean    %20@
#Character  %80@
#Integer    %4C  (%44 when N+ pragmat in operation)@
#Real       %C   (%1C when R+ pragmat in operation)@
@BSubrange and scalar types are treated as
@X %%
integer at the MUTL level.@
@X %|
integer-32 (%4C), integer-16 (%44) or integer-8 (%40) depending
on the range of values of the type.
@BThe Pascal set types are treated as logical 8, 16, 32 or 64
according to the number of elements required. Since MUTL does not
allow logical 128, 128-bit sets are implemented as a type
consisting of two logical 64 elements. These are manipulated
using procedures in the Pascal run-time library.
@X %%
@BThe Pascal file type is discussed separately later.
The array, pointer and record types known as aggregate types
either address aggregate types or consist of a concantenation
of several predefined types or previously defined aggregate types.@
@BThe parameter of a MUTL procedure which passes a type specification
@X %`
is either the name given to a basic type which is either
less than 64 or greater than 2047 or
an aggregate type specification which has a value greater than or equal to
%100 and encoded as follows:@
@T# 5 13 16 18
@Q 13
@
Bits 2 - 13#:#MUTL name of previously defined type plus %40@
@
#0 -  1#:#0 -@Ispecification is a pointer to the type defined by bits
2-13@
@
###1 -@Ispecification is a pointer to a vector containing elements
whose type is defined by bits 2-13@
@
###3 -@Ispecification is a bounded pointer to the type defined by
bits 2-13.@
@BThe aggregate types are defined to MUTL by using the
following procedures:-@
@T# 6
@
(i)@ITL.TYPE([SYMB.NAME],NATURE)@
@IThis procedure starts the specification of an aggregate
type and allocates a name for the type. Unlike PASCAL,
MUTL does not allow type specifications to be
nested, but an aggregate type may include previously
specified types. Therefore Pascal must define nested type
specifications to MUTL before the main specification.
The second parameter of the procedure specifies
whether the type specified is internal to the module.
Since a PASCAL program is one module, this
parameter is zero.@
@
(ii)@ITL.TYPE.COMP(TYPE.SPEC,DIMENSION,[SYMB.NAME])@
@IThis procedure is repeatedly called to add the constituent
types of the current aggregate type specification. It is called
after TL.TYPE.
Type components do not have MUTL names instead
the position of a component (counting from zero) within
the type specification is used in accessing it.@
@
@IThe parameters are:@
@3
@
@I   TYPE.SPEC  (a type as earlier). For components of a PACKED@
@I              type the specification of a MUTL bit-string type@
@I              is used.@
@I   DIMENSION  = 0 scalar@
@I              > 0 vector of given number of elements@
@I              - 1 unknown number of elements@
@I             <- 1 parameter is negated@
@I   MUTL name of literal giving number of elements.@
@0
@
(iii)@ITL.END.TYPE(STATUS)@
@IThis procedure terminates the definition of the aggregate type
currently being defined (if the parameter has a value of zero)
or specifies that an alternative definition exists for the aggregate
type (if the parameter has a value of 1). The alternative
definition, if any, follows immediately.@
@IThe capability of defining alternative types is useful
in PASCAL in the specification of record types with
variants.@
@BExamples of the use of the above procedures for some PASCAL
type definitions follow. It is assumed that the next name to be
allocated by MUTL is 2 and that the type definitions occur in a PASCAL
program as numbered. This is to show how names are allocated in
MUTL.@
@S(i) alfa = PACKED ARRAY[1..10] OF CHAR@
@BNo type declaration is necessary since alpha will be represented
by a vector of bytes with dimension 10.@
@S(ii) counter = ARRAY[0..10,-1..20] OF INTEGER@
@BCounter will be represented by a vector of integer 32 with
dimension 10*20=200.@
@BNo type declaration is necessary.
@S(iii) bits = SET OF 0 .. 127@
@BNo type declaration necessary since bits will be represented by
a type which is defined by the compiler during the
initialisation procedures.
@S(iv) ptr = ^REC
@BAt the time a pointer is defined, the type of 'rec' may be
unknown. One of MUTL's
basic addressing type is a pointer to
an item whose type is not yet defined. It has the name %01.
@Q 21
@S(v) rec = RECORD@
@3
@
    idname : alfa;@
    size : INTEGER;@
    next : ptr;@
    descriptor : RECORD@
                       min,max : INTEGER;@
                       declared : BOOLEAN@
                 END;@
    value : RECORD@
                       serial : INTEGER;@
                       count : counter;@
                       CASE obtained : BOOLEAN OF@
                            FALSE : (maybeobtained : BOOLEAN;@
                                     index : INTEGER);@
                            TRUE  : (intval : INTEGER;@
                                     realval : REAL;@
                                     charval : CHAR)@
                  END@
END;@
@0
@BAs MUTL does not at present permit aggregate
type specifications to be nested, fields 'descriptor' and 'value'
are specified to MUTL before 'rec' is
specified. The type specification for 'descriptor' is as follows:-@
@3
@
(a) TL.TYPE([""],0) yields 6 as the name of@
                    the type to which "descriptor" belongs.@
(b) TL.TYPE.COMP(%4C,0,["min"])@
(c) TL.TYPE.COMP(%4C,0,["max"])@
(d) TL.TYPE.COMP(%20,0,["declared"])@
(e) TL.END.TYPE(0)@
@0
@BThe record-type 'value' contains variant fields which are to be
specified before that of 'value' as in MUTL, variants are
specified as separate subrecords, thus we have@
@3
@
(f) TL.TYPE([""],0)   yields 7 as the name of the variant@
                      part of 'value'@
(g) TL.TYPE.COMP(%20,0,["maybeobtained"])@
(h) TL.TYPE.COMP(%4C,0,["index"])@
(i) TL.END.TYPE(1) ends the first variant@
(j) TL.TYPE.COMP(%4C,0,[#intval"])@
(k) TL.TYPE.COMP(%1C,0,["realval"])@
(l) TL.TYPE.COMP(%80,0,["charval"])@
(m) TL.END.TYPE(0)   ends the specification of@
                     the variant part@
(n) TL.TYPE([""],0)   yields 8 as the name of the@
                      type to which "value" belongs@
(o) TL.TYPE.COMP(%4C,0,["serial"])@
(p) TL.TYPE.COMP(%110,0,["count"])@
(q) TL.TYPE.COMP(%20,0,["obtained"]) specifies the tagfield@
(r) TL.TYPE.COMP(%11C,0,[""]) adds the variant part to "value"@
(s) TL.END.TYPE(0) ends the specification of "value".@
@BThe following procedures will now be called to
specify 'rec' to MUTL.@
@
(t) TL.TYPE(["rec"],0)   yields 9@
(u) TL.TYPE.COMP(%108,0,["idname"])@
(v) TL.TYPE.COMP(%4C,0,["size"])@
(w) TL.TYPE.COMP(%01,0,["next"])@
(x) TL.TYPE.COMP(%118,0,["descriptor"])@
(y) TL.TYPE.COMP(%120,0,["value"])@
(z) TL.END.TYPE(0)@
@0
@S23.5 VARIABLE DECLARATION
@BThe procedure TL.S.DECL([SYMB.NAME],TYPE.SPEC,DIMENSION) declares
a variable which may be a scalar or a vector of previously defined
type. It allocates storage for
the variable within the currently selected data area and also gives
it a name.
@BSome examples on the use of the procedure are:-@
@3
@
(i)     VAR ch : CHAR@
@
        TL.S.DECL(["ch"],%80,0) - yields 9@
@
(ii)    words : ARRAY[1..5] OF BOOLEAN@
@
        TL.S.DECL(["words"],%80,5] - yields 11@
@
(iii)   table           : RECORD@
        toparea, height : REAL@
                          END@
@
        TL.TYPE([""],0) - yields 12@
        TL.TYPE.COMP(%1C,0,["toparea"])@
        TL.TYPE.COMP(%1C,0,["height"])@
        TL.END.TYPE(0)@
@
        TL.S.DECL(["table"],%130,0) - yields 13@
@
  (iv)  identifier : alfa          14@
   (v)  thisentry, newentry : ptr  15,16@
  (vi)  SETA, setb : bits          17,18@
(viii)  count : counter            19@
@0
@S13.6 PROCEDURE DECLARATION
@BIn MUTL, a procedure may have a result, may be recursive, and
must be specified before it is either defined or referenced. Its
specification gives its nature (either a parameter, a library
procedure, a static user-defined procedure, or a recursive
user-defined procedure), the type of its parameters (if any), and
the type of its result (if any). On specifying that a procedure is a
parameter or it is from a library, MUTL does not expect it to be
defined. A procedure definition informs MUTL that the code for the
procedure follows.
@BOn specifying a procedure, a name is allocated for it and it can
then be referenced even though it has not been defined. Thus, a
procedure can be forward referenced as in the forward declaration of
the PASCAL language. Names are not allocated for a procedure's
formal parameter(s) until the procedure is defined. Names allocated
in a procedure's definition are re-assigned consecutively at the end
of its definition as new declarations occur.
@BThe handling of procedures in MUTL conforms with PASCAL language
all procedures are treated as recursive. After a procedure heading
is recognised, its specification is given to MUTL unless already
given by forward declaration. The following procedures give the
specification.@
@T# 9
@
  (i)@ITL.TL.PROC.SPEC([SYMB.NAME],NATURE).@
@IIt starts the specification of a procedure and allocates a
name for it.@
@
 (ii)@ITL.PROC.PARAM(TYPE,DIMENSION).@
@IDefines the type of the next parameter in the current procedure declaration.@
@
(iii)@ITL.PROC.RESULT(TYPE).@
@IIt ends the specification of the procedure currently being
specified and defines the type of result (if any). If the
parameter has a value of zero, it indicates that the procedure
yields no result.@
@
@IThe following procedures define a procedure to MUTL.@
  (i)@ITL.PROC(NAME).@
@IIt defines that a procedure starts at the current position in
the code segment and allocates a name for each of the
procedure's parameters. NAME is the name allocated to the
procedure by TL.PROC.SPEC.@
@
 (ii)@ITL.PROC.KIND(KIND).@
@IIt specifies whether the current procedure's labels and
variable can be accessed non-locally or not. It is followed
by the imperative instructions of the procedure being
defined.@
@
(iii)@ITL.END.PROC.@
@IIt defines the end of the code for the procedure whose
definition is most recently started.@
@BThe use of the above procedures is illustrated by their calls to
plant codes for the following section of a PASCAL program.@
@
@
151  FUNCTION cosine (angle : REAL) : REAL; FORWARD;@
152  PROCEDURE draw (VAR width : INTEGER; VAR a : alfa);@
153  VAR 1,m : INTEGER;@
154        x : REAL;@
155  BEGIN@
       .@
       .@
       .@
       .@
160  END;@
161  PROCEDURE check (FUNCTION trigfn (acute : BOOLEAN) : INTEGER;@
     angle : REAL);@
162  BEGIN@
       .@
       .@
       .@
       .@
170  END;@
171  PROCEDURE SKIPLINE; EXTERNAL;@
172  FUNCTION cosine;@
173  VAR truns : INTEGER;@
174  BEGIN@
       .@
       .@
       .@
       .@
180  END;@
@BThe MUTL procedures called for each line are:-@
@S@OLine 151.@
@T# 12
@
         TL.PROC.SPEC(["cosine"],0)@
@IStarts the specification of COSINE. Suppose the next name which is
allocated to it is 21. The second parameter states that it is a
potentially recursive user-defined procedure.@
         TL.PROC.PARAM(%1C,0)@
@IIt defines the next parameter to be REAL.@
         TL.PROC.RESULT(%1C)@
@IIt ends the specification of COSINE and defines the type of its
result as REAL type.@
@
@
@OLine 152.@
@
         TL.PROC.SPEC(["draw"],0)@
@IIt starts the specification of DRAW and allocates the name 22 for it.@
         TL.PROC.PARAM(%4C+1,0).@
@IIt defines the next parameter as an unbounded pointer to an item
of INTEGER type.@
         TL.PROC.PARAM(4(10+64)+3,0)@
@IIt defines the next parameter as a bounded pointer to an item of
aggregate type allocated the name 10.@
         TL.PROC.RESULT(0).@
@IIt ends the specification of DRAW and states that it has no result.@
@
@
@OLine 153.@
@
         TL.PROC(22).@
@IIt states the definition of DRAW and allocates the names 23 and 24
for its parameters WIDTH and A respectively.@
         TL.PROC.KIND(0).@
@IIt specifies that non-local accesibility of procedure DRAW's labels and
variables is prohibited.@
         TL.S.DECL(["l"],%4C,0).@
@IIt declares variable l to be an integer-type and allocates the
name 25 for it.@
         TL.S.DECL(["m"],%4C,0).@
@IIt allocates the name 26 for m.@
@S@OLine 154.@
@
         TL.S.DECL(["x"],%1C,0).@
@IIt allocates the name 27 for x.@
@S@OLine 155.@
@
@INo procedure is called.@
@S@OLine 160.@
@
         TL.END.PROC.@
@IIt ends the definition of DRAW. The next name to be allocated is then
23 because all names allocated within the definition of DRAW are
re-assigned.@
@S@OLine 161.@
@
         TL.PROC.SPEC(["check"],0).@
@IIt allocates the name 23 for CHECK.@
         TL.PROC.SPEC([""],16).@
@IIt starts the specification of procedural parameter TRIGFN and allocates
the name 24 for it. This name is used in referencing TRIGFN in the procedure
CHECK as illustrated later in the chapter. It is passed a pointer to a
'null' string because the name TRIGFN is associated with the parameter
and not the procedure being specified.@
         TL.PROC.PARAM(%20,0).@
@IIt states that the next parameter of the procedural parameter is
a boolean-type.@
         TL.PROC.RESULT(%4C).@
@IIt ends the specification of the procedural parameter and defines
the result type as integer.@
         TL.PROC.PARAM(%28,0).@
@IIt defines the next parameter of CHECK as a basic type which is
a pointer to a procedure.@
         TL.PROC.PARAM(%1C,0).@
@IIt defines the next parameter of CHECK as a real type.@
         TL.PROC.RESULT(0).@
@IIt states that CHECK has no result.@
@S@OLine 162.@
@
         TL.PROC(23).@
@IIt starts the definition of CHECK.@
         TL.PROC.KIND(0).@
@S@OLine 170.@
@
         TL.END.PROC.@
@IIt ends the definition of CHECK.@
@S@OLine 171.@
@
         TL.PROC.SPEC(["skipline"],5).@
@IIt starts the specification of library procedure SKIPLINE and
allocates the name 25 for it.@
         TL.PROC.RESULT(0).@
@IIt ends the specification of SKIPLINE.@
@S@OLine 172.@
@
         TL.PROC(21).@
@IIt starts the definition of COSINE.@
         TL.PROC.KIND(0).@
@S@OLine 173.@
@
         TL.S.DECL(["turns"],%4C,0).@
@IIt declares TURNS to be a scalar of integer-type and allocates
the name 26 for it.@
@S@OLine 174.@
@
@INo procedure is called.@
@S@OLine 175.@
@
         TL.END.PROC.@
@IIt ends the definition of COSINE. The next name to be allocated
is now 26.@
@S23.7 STATEMENTS@
@BTL.PL is used to plant components of simple statements. Control
constructs also use TL.LABEL.SPEC and TL.LABEL.
@S33.7.1 Constants
@BThe procedures TL.C.LIT.32, TL.C.LIT.64 are used
to define the "current literal" to TL. This mechanism deals with
arithmetic contstants appearing in expressions:@
@T# 21
@
   TL.C.NULL(TYPE)@Iassigns the null pointer value to the current
literal.@
   TL.C.LIT.S@Iassigns a sequence of byte-sized values
(e.g. Characters) to current literal.@
@BOther types of literal must be declared as variables using TL.S.DECL.
The declared variable
can be initialised by calling TL.ASS(DECLARED LITERAL NAME) to commence
the initialisation process and then TL.ASS.VALUE(NAME,REPEAT,COUNT).
TL.ASS.VALUE assigns the value as specified by NAME to the components
at the current assignment position (the assignment position corresponds
to the position of the component of the variable) and advances the position
by 1. The parameter REPEAT.COUNT is the number of times the assignment is
repeated. The procedure TL.ASS.ADV(NO) can be used to select the position
of any component as the current assignment position. Its parameter is the
number of components to be skipped. Finally, procedure TL.ASS.END is called
to indicate the end of assignments. If the dimension of the variable is not
stated at the time it is declared, on calling TL.ASS.END, its dimension
is determined at that point.
@BThe following PASCAL constants are given to MUTL by the procedures
that are listed with them.@
@T# 10
@
(i) 1.0@
       TL.C.LIT.64(%1C,1.0) or TL.C.LIT.64(%C,1.0)@
@IDepending upon whether the double precision pragmat is in
operation or not.@
@
(ii) 164@
       TL.C.LIT.32(%4C,164)@
@
(iii) 'A'@
       TL.C.LIT.32(%80,ORD('A'))@
@
(iv) FALSE@
       TL.C.LIT.32(%20,ORD(FALSE))@
@
(v) TL.S.DECL([""],%80,-1)@
@IDeclares a string variable and allocates the name X (say) for it.@
       TL.ASS(X)@
@IIt starts the initialisation of the variable named X.@
       TL.C.LIT.S(%80,'ABCDE')@
@IIt defines the current literal to be the byte vector 'ABCDE'@
       TL.ASS.VALUE(0,1)@
@IIt assigns the current literal to the variable.@
@S33.7.2 Variable Access
@BIn PASCAL, a variable is accessed by either a reference to it, its element
(array-type), its field (record-type) or the item it is addressing
(pointer-type). At variable declaration, the entire variable is declared
to MUTL and thus has a name by which it can be accessed. The indexed,
field-designated and referenced variables cannot
be accessed by name alone. There are some selection and dereferencing
operations which have to be performed in order to access
them.@
@BThe factors in the example program (see 3.5 for declarations)
are accessed as follows. At the
end of the MUTL procedure calls, for each case the D register contains
the address of the factor.@
@T# 30
@
(i)   identifier[i]@
      TL.PL(%61,14) :@Iloads the address of IDENTIFIER into
the D register.@
      TL.PL(%02,20) :@Iloads the value of I into the
B register.@
      TL.C.LIT.32(%4C,-1) :@Idefines the current literal to
be an integer-type of value -1.@
      TL.PL(%08,0)  :@Iadds the value of the current literal
to the content of the B register.@
      TL.PL(%64,N)  :@Imodifies the D register to address the
element. N is any integer value, the
instruction requires no operand. It has
been pre-defined to be performed on the
B register. (In practice N=0 is always
used by the Pascal compiler).@
@BIn referencing an array-element, the lower-bound of the
array has to be taken into consideration. In MUTL the lower-bound
of all arrays is zero and thus the first element is referenced as
component 0. Hence, an adjustment has to be made for arrays whose
lower-bounds are not equal to zero by subtracting the lower-bound
from the index-value.@
@
(ii)  count[i,j]@
      TL.PL(%61,19) :@Iloads the address of COUNT into
the D register.@
      TL.PL(%02,20) :@Iloads the value of I into the
B register.@
      TL.C.LIT.32(%4C,20) :@Idefines the current literal to be
an integer of value 20 (since count is a vector of vectors with
dimension 20).@
      TL.PL(%0B,0) :@Imultiplies the contents of the B register
by the current literal.@
      TL.PL(%66,1) :@Imodifies the D register to point to a
vector whose first element is specified by the B register. The
operand 1 indicates that a bounded pointer is to be maintained.@
      TL.C.LIT.32(%4C,19) :@Idefines the current literal to be an
integer of value 19 (since the vectors of count have component 0
to 19).@
      TL.PL(%02,0) :@Iloads the current literal into the B register.@
      TL.PL(%67,0) :@Imodifies the D register to point to a vector
whose last element is that specified by the B register.@
@
      (This completes the selection of D[i].)@
@
      TL.PL(%02,21) :@Iloads the value of J into the
B register.@
      TL.C.LIT.32(%4C,1) :@Idefines the current literal as
an integer-type value 1.@
      TL.PL(%08,0)  :@Iadds the current literal to the
B register.@
      TL.PL(%64,0)  :@Imodifies the D register to address
the jth column.@
@BIn selecting the row, there was no need for an adjustment
because the lower-bound of the first-subscript is zero.@
@
(iii) table.height@
      TL.PL(%61,13) :@Iloads the address of TABLE
into the D register.@
      TL.PL(%63,1)  :@Imodifies the D register to
address the 2nd field of TABLE.
(The first field is numbered zero).@
@
(iv)  thisentry^@
      TL.PL(%62,15) :@Iloads the value of THISENTRY
into the D register.@
@
(v)   newentry^.value.intval@
      TL.PL(%62,16) :@Iloads the value of NEWENTRY
into the D register.@
      TL.PL(%63,4)  :@Imodifies the address of NEWENTRY^
in the D register to the address
of the 5th field.@
      TL.PL(%63,3)  :@Imodifies the D register to address
the 4th sub-field.@
      TL.PL(%65,1)  :@Imodifies the D register to select
the 2nd alternative declaration
of the 4th sub-field.@
      TL.PL(%63,0)  :@Imodifies the D register to address
the 1st field.@
@
      (See the declaration of type rec in 3.4).@
@S33.7.3 Expression Evaluation
@BThe A register is primarily used for evaluating expressions.
A subscript expression is evaluated
using the B register.@
@BThe expressions from the example program are evaluated as
follows. Except otherwise stated, the A register contains the
result of the evaluation.@
@
(i)   i*j@
      TL.PL(%46,%4C) :@ISets the mode of A register
 to integer-type.@
      TL.PL(%22,20)  :@ILoads I into the A register.@
      TL.PL(%2B,21)  :@IMultiplies the content of A
 register by J.@
@
(ii)  (table.area/0.5) - (j+2)@
      TL.PL(%61,13)  :@ILoads the address of TABLE into
 the D register.@
      TL.PL(%63,0)   :@IModifies the D register to address
 the first field of TABLE.@
      TL.C.LIT64(%1C,0.5) :@IDefines the current literal as a
 real-type value 0.5.@
      TL.PL(%46,%1C) :@ISets A register to real mode.@
      TL.PL(%22,%1004) :@ILoads the item addressed by the
 D register into the A register.@
      TL.PL(%2C,0)   :@IDivides the A register by the
 current literal.@
      TL.PL(%47,%1001) :@IPushes the content of A register
on top of the stack.@
      TL.PL(%46,%4C) :@ISets A register to integer mode.@
      TL.PL(%22,21)  :@ILoads J into the A register.@
      TL.C.LIT.32(%4C,2) : @IDefines the current literal as an
integer value 2.@
      TL.PL(%29,0)   :@IAdds the current literal to the
A register.@
      TL.PL(%45,%1C) :@ISets A register to real mode and
converts its content to real-type.@
      TL.PL(%2A,%1003) :@IPerforms reverse-subtraction
operation on the A register and
the item on top of stack.@
@
(iii) (i<j) AND (ch<>'*') AND (thisentry=nil) AND NOT (endloop OR@
      found).@
@
      TL.PL(%46,%4C) :@ISets A register to integer mode.@
      TL.PL(%22,20)  :@ILoads I into A register.@
      TL.PL(%2F,21)  :@ICompares A register and J.@
      TL.PL(%46,%20) :@ISets A register to boolean mode.@
      TL.PL(%22,%100D) :@ILoads logical 1 into A register if T
register implies that the r.h.s < l.h.s.
Otherwise, loads logical 0.@
      TL.PL(%47,%1001) :@IPushes the content of A register on top of
@Istack.@
      TL.PL(%46,%80)   :@ISets A register to character mode.@
      TL.PL(%22,10)    :@ILoads CH into A register.@
      TL.C.LIT.32(%80,'*') :@IDefines the current literal as
a character value '*'.@
      TL.PL(%2F,0)     :@ICompares A register and the current
literal.@
      TL.PL(%46,%20)   :@ISets A register to boolean mode.@
      TL.PL(%22,%1009) :@ILoads logical 1 into A register
if T implies 'not equal to'.@
      TL.PL(%24,%1003) :@IPerforms logical AND operation
on A register and the item on
top of stack.@
      TL.PL(%47,%1001) :@IPushes the contents of the A register
on top of stack.@
      TL.PL.(%46,%114) :@ISets the A register to pointer mode
(of type THISENTRY).@
      TL.PL(%22,15)    :@ILoads the value of THISENTRY into
A register.@
      TL.C.NULL(%114)  :@IDefines the current literal as a
pointer (of type THISENTRY) with
'null' value.@
      TL.PL(%2F,0)     :@ICompares A register and the current
literal.@
      TL.PL(%46,%20)   :@ISets A register to Boolean mode.@
      TL.PL(%22,%1003) :@ILoads item on top of stack into A
register.@
      TL.PL(%24,%1008) :@IPerforms logical AND operation on
A register and the T register which
contains logical 1 if the last
comparison implies 'equal to'.@
      TL.PL(%47,%1001) :@IPushes the content of A register
on top of stack.@
      TL.PL(%22,22)    :@ILoads ENDLOOP into the A register.
The A register is already in
boolean-mode.@
      TL.PL(%25,23)    :@IPerforms logical OR operation on A
register and FOUND.@
      TL.PL(%23,%1001) :@IPerforms logical 'non-equivalence'
operation on the A register.@
      TL.PL(%24,%1003) :@IPerforms logical AND operation on A
register and item on top of stack.@
@
(iv)  SETA * SETB@
      TL.PL(%46,%9C)   :@ISets A register to logical 64 mode.@
      TL.PL(%22,17)    :@ILoads SETA into the A register.@
      TL.PL(%24,18)    :@IPerforms logical 'and' on A register
and SETB.@
@S33.7.4. Procedure Reference
@BA procedure reference is initiated by the function 'stack link'.
Its operand is the name allocated by either TL.PROC.SPEC to an actual
procedure or TL.PROC.PARAM to a formal procedure. This is then followed
by a sequence of the function 'stack parameter' for each of its
parameters and finally, the 'enter' function which passes control to
the procedure being referenced. The operand of the 'enter' function
is either zero for an actual procedure or the name allocated by
TL.PROC.SPEC to a formal procedure.
@BThe result of a procedure is  loaded
into the A register prior to returning control from the procedure.
@S33.7.5. Assignment
@BThe A register operates in five modes:@
@
        REAL@
        INTEGER@
        LOGICAL@
        DECIMAL@
        TYPELESS (any predefined type including aggregate).@
@
Hence any assignment operation can be performed by loading
into the A register and storing.@
@T# 28
@
e.g.@
       i := j;@
       TL.PL(%46,%4C)     :@ISets A register to integer mode.@
       TL.PL(%22,20)      :@ILoads I into A register.@
       TL.PL(%20,21)      :@IStores A register in J.@
@S33.7.6 Heap Management
@BNEW and DISPOSE are implemented by calling two procedures
from a library written in MUSL:@
@T# 4
@
MAKEHEAP (Typesize, Typealign, dimension)@
@Icreates space on the heap and puts a descriptor in the
global variable HEAPTEMP.@
@
REMOVEHEAP (Typesize, Typealign)@
@Iremoves an item from the heap whose descriptor was placed
in the global variable HEAPTEMP.@
@Q 5
@
@I              Typesize and Typealign are obtained by calling@
@I              TLCTYPE(%4C,0,typename)@
@I              TLCTYPE(%4C,1,typename)@
@I              respectively.@
@S33.7.7 The Basic Control Constructs and the With Statement
@BIn planting codes for the basic control constructs, it is assumed
that the conditional expression has been evaluated
and its value is in the A register.@
@T# 33
@
@
(i)    IF <cond-expr> THEN statement;@
       TL.LABEL.SPEC([""],3)  :@ISpecifies label for false
'cond-expr' and allocates the
name 31 for it.@
       TL.C.LIT.16(%20,FALSE) :@IDefines the current literal as
Boolean value FALSE.@
       TL.PL(%2F,0)           :@ICompares the value of 'cond-expr'
in the A register with current
literal.@
       TL.PL(%49,31)          :@IJumps to label 31 if T implies
'equal to'.@
            .@
            .@
            .@
       codes for statement@
            .@
            .@
            .@
       TL.LABEL(31)          :@IDefines false-conditional-expression
label.@
@
@
(ii)   IF <cond-expr> THEN statement-1@
                    ELSE statement-2;@
       TL.LABEL.SPEC([""],3) :@ISpecifies label for false
'cond-expr' and
allocates the name 32 for it.@
       TL.C.LIT.16(%20,FALSE :@IDefines current literal as
Boolean value FALSE.@
       TL.PL(%2F,0)          :@ICompares A register and current
literal.@
            .@
            .@
            .@
       codes for statement-1@
            .@
            .@
            .@
       TL.LABEL.SPEC([""],3) :@ISpecifies label for end of
statement and allocates 33
for it.@
       TL.PL(%4F,33)         :@IJumps to end of statement.@
       TL.LABEL(32)          :@IDefines false condition label.@
            .@
            .@
            .@
       codes for statement-2@
            .@
            .@
            .@
       TL.LABEL(33)          :@IDefines end of statement label.@
@
@
(iii)  REPEAT@
            statements(s)@
       UNTIL cond-expr;@
       TL.LABEL.SPEC([""],3) :@ISpecifies start of loop label
and allocates the name 34 for it.@
       TL.LABEL(34)          :@IDefines start of loop label.@
            .@
            .@
            .@
       codes for statement(s)@
            .@
            .@
            .@
       TL.C.LIT.16(%20,FALSE) :@IDefines current literal as
Boolean value False.@
       TL.PL(%2F,30)          :@ICompares A register and current
literal.@
       TL.PL(%49,34)          :@IJumps to start of loop label if
T implies 'equal to'.
@
@
(iv)   WHILE cond-expr DO@
             statement;@
       TL.LABEL.SPEC([""],3)  :@ISpecifies start of loop label and
allocates 35 for it.@
       TL.LABEL.SPEC([""],3)  :@ISpecifies end of loop label and
allocates 36 for it.@
       TL.LABEL(35)           :@IDefines start of loop label.@
       TL.C.LIT.16(%20,FALSE)@
       TL.PL(%2F,30)          :@ICompares A register and current
literal.@
       TL.PL(%49,36)          :@IJumps to end of loop label if T
implies 'equal to'.@
            .@
            .@
            .@
       codes for statement@
            .@
            .@
            .@
       TL.PL(%4F,35)          :@IUnconditional branch to start of
loop label.@
       TL.LABEL(36)           :@IDefines end of loop label.@
@
@
(v)    FOR i := 1 TO j DO statement;@
       TL.C.LIT.32(%4C,1)  :@IDefines current literal to be 1.@
       TL.CV.CYCLE(20,0,1) :@IInstructs MUTL to plant code for a loop
with control variable i (MUTL name 20), initial value equal to the
current literal and increment +1.@
       TL.CV.LIMIT(21)     :@IDefines the upper limit of the loop
to be j (MUTL name 21).@
            .@
            .@
            .@
       code for statement@
            .@
            .@
            .@
       TL.REPEAT          :@IDefines the end of the loop.@
@
@
(vi)   10.1  CASE ch OF@
       10.2  'A' : statement-1;@
       10.3  'B' : statement-2;@
         .@
         .@
         .@
         .@
         .@
       10.66 END;@
@S@OLine 10.1.@
@T# 30
@
   TL.LABEL.SPEC([""],2) :@ISpecifies end-of-statement label
named 40.@
   TL.LABEL.SPEC([""],2) :@ISpecifies start-of-statement label named 41.@
   TL.PL(%50,41)         :@IUnconditional branch to start-of-statement
label.@
   TL.S.DECL(%[""],%2C,-1) :@IDeclares a vector literal with unknown
number of elements each pointing to a label. The literal is named 42.@
@S@OLine 10.2.
@
   TL.LABEL.SPEC(%"",%2) :@ISpecifies label 43 for start of statement
for case constant 'A',@
   TL.LABEL(43)          :@IDefines label 43.@
       .@
       .@
       .@
code for statement-1@
       .@
       .@
       .@
   TL.PL(%50,40)         :@IUnconditional branch to end-of-statement
label.@
@S@OLine 10.3
@
   TL.LABEL.SPEC("",3)  :@ISpecifies label 44 for start of statement
for case constant 'B'.@
   TL.LABEL(44)          :@IDefines label 44.@
       .@
       .@
       .@
code for statement-2@
       .@
       .@
       .@
   TL.PL(%50,40)         :@IUnconditional branch to end-of-statement label.
@S@OLine 10.66
@
   TL.LABEL(41)          :@IDefines start-of-statement label.@
   TL.PL(%02,10)         :@ILoads CH into the B register.@
   TL.C.LIT.32(%4C,-ORD('A')):@IDeclares current literal to be -ORD('A),
because 'A' is the smallest case constant listed.@
   TL.PL(%08,0)          :@IAdds the current literal to the B register.@
   TL.PL(61,42)          :@ILoads a reference to the case table vector
into the D register.@
   TL.PL(%64,0)          :@IModifies the D register to address the
Bth element.@
   TL.PL(%50,%1004)      :@IUnconditional branch to label addressed
by D register.@
   TL.LABEL.SPEC("",2)   :@ISpecifies label 100 for error case.@
   TL.LABEL(100)         :@IDefines label 100.@
       .@
       .@
       .@
code for run-time trap@
       .@
       .@
       .@
   TL.PL(%50,40)         :@IUnconditional branch to end-of-statement label.@
   TL.LABEL(40)          :@IDefines end-of-statement label.@
   TL.ASS(42,-1)@
   TL.ASS.VALUE(43,1)    :@IInitialises case table.@
       .@
       .@
       .@
   TL.ASS.END@
@T# 30
@
@
(vii)  WITH thisentry^.descriptor DO@
            max := min * max;@
       TL.PL(%62,15)     :@ILoads the value of THISENTRY into the
D register.@
       TL.PL(%63,3)      :@IModifies D register to address the
fourth field of record reference by
THISENTRY.@
       TL.S.DECL("",%125,0):@IDeclares a pointer variable and
allocates the name 50 for it. It is
used to save data structure
selection information.@
       TL.PL(%60,56)     :@IStores D register into the
variable named 50.@
       TL.PL(%62,50)     :@ILoads the variable into the D register.@
       TL.PL(%63,0)      :@IModifies D register to reference the
first field of DESCRIPTOR.@
       TL.PL(%46,%4C)    :@ISets A register to integer mode.@
       TL.PL(%22,%1004)  :@ILoads item addressed by D register into
the A register.@
       TL.PL(%62,50)     :@ILoads the selection information in
variable 50 into the
D register.@
       TL.PL(%63,1)      :@IModifies D register to reference the
second field of DESCRIPTOR.@
       TL.PL(%2B,%1004)  :@IMultiplies the A register by the item
addressed by the D register.@
       TL.PL(%62,50)     :@ILoads the selection information in
variable 50 into
D register.@
       TL.PL(%63,1)      :@IModifies D register to address second
field of DESCRIPTOR.@
       TL.PL(%20,%1004)  :@IStores A register into item addressed
by the D register.@
@S23.8 MUTL HOUSEKEEPING
@BThe compiler plants code at the beginning of each program
compiled for initialisation of certain variables declared in the
first heap segment for interfacing with the run-time library. There
are:@
@V1 7
@V2 7
@
HEAPTEMP : Used to pass descriptors between the PASCAL program
and the run-time library for use in MAKE.HEAP and REMOVE.HEAP.@
@
HEAPADDR : Used by the run-time library to store the current
heap position.@
@
INPFILE,OUTPFILE : File records for the standard files INPUT and OUTPUT.@
@
EMPTY128 : The 128-bit empty set.@
@
WORKSET : Used to pass a 128-bit set between the PASCAL program
and the run-time library for use in the set-manipulation procedures.@
@
HEAPCHECK : A flag used to communicate with the run-time library whether
run-time checking is in force or not.@
@V1 0
@V2 0
@BThe compiler also declares at the beginning of each compilation
all the library procedures from the run-time library which it
might need to run the program.
@S23.9 EXTERNAL LIBRARY PROCEDURES
@BThe compiler obtains the specification for library procedures by
calling the system procedures FINDN and FINDP. Such procedures need
not be declared before being used, but if they are declared as
EXTERNAL then the compiler checks the specification of the procedures
against that obtained using FINDN and FINDP.
@BSince many system procedures require ADDR[$LO8] parameters the MUSL
library PIOLIB contains two procedures which modify pascal variables
of type 'pointer-to-string-type' to give an ADDR[$LO8] result with an
appropriate bound:@
@T# 18
@
P.STR.TRUNC(P1)@
@IRemoves trailing spaces from a string returning a
pointer result.@
@
ADD.BOUND(PTR,BOUND)@
@IReturns a bounded pointer with base address
given by PTR and bound given by BOUND. The compiler uses this procedure
by making an EXTERNAL declaration:@
@
FUNCTION ADDBOUND(VAR PTR:CH;BOUND:INTEGER):ADDRLO8;EXTERNAL;@
@IThis enables it to pass a bounded pointer to a section of an array
by specifying as parameters the 1st. element required and the number
of elements required.@
@V9 0
@R4 IMPLEMENTATION OF FILES
@S24.1 INTRODUCTION
@BThe compiler handles files in such a way that their implementation
is not visible to the Pascal programmer. The only concern of the
programmer is the availability of the files in the system.
@S24.2 DECLARATION OF FILES
@BAll external files must be specified as parameters in the program
heading.
@BThe type-identifier TEXT is predefined.
@BFiles are declared to MUTL as variables of an aggregate type
consisting of 4 components:@
@T# 20
@
     FLAG -@IInteger flag giving current status of file.@
     STREAM -@IThe number of the stream associated with the file.@
     BUFFER -@IThe file buffer variable.@
     NAME -@IA bounded pointer to a vector containing the name of the file.@
@S24.3 USING FILES
@
1. @OAs parameters@
@BFiles can only be used as variable and not value parameters. They can
also be used as parameters of procedural and functional parameters.@
@
2. @OIn assignment@
@BFiles can not be assigned but buffer variables can.@
@
3. @OAs components of other types@
@BFiles are not allowed to be components of any other structured type.@
@S24.4 INPUT/OUTPUT
@BThere is no limit as to the number of files a programmer may use but,
since MUSS only allows 8 input streams and 8 output streams,
only 8 "readable" and 8 "writeable" files are allowed at a time.
All file must be initialised to "readable" or "writeable" by the
procedures RESET and REWRITE, which can also be used to change a
file from "readable" to "writeable" or vice versa. If a programmer
finds that too many files are in use then the procedure CLOSE(<filename>)
may be called. This ends the INPUT/OUTPUT stream assigned to that file.
@BThe compiler adheres to the requirements of input/output facilities
of standard Pascal.
@BThe number of characters in any line of a textfile sent to the line printer
may not be more than 120 characters.
@S24.5 USE OF MUSS FACILITIES IN THE IMPLEMENTATION
@S34.5.1 Introduction
@BThe MUSS provides basis of the input/output facilities. It
supports four different methods for structuring input/output
information, namely:@
@T# 7
@
(i)@IAs a sequence of @Ocharacter@O, structured into pages and lines.@
(ii)@IAs an unstructured sequence of @Wbinary information.@
(iii)@IAs a sequence of equal-length records called @Ounits@O.@
(iv)@IAs a sequence of variable-length records called @Orecords@O.@
@BThese structuring techniques meet the requirements of the standard legible
input and output in Pascal.
@S34.5.2 Correspondence Between MUSS Facilities and the Pascal@
      @GInput/Output@G@
@BIn Pascal, a file-type consists of a sequence of components that are all of
one type. The type of the components can be unstructured (character, integer,
real or boolean type) or structured (array, set, or record type).
@BThe MUSS structuring method (i) - sequence of chars corresponds to
the file with components of character. While method (ii) corresponds
to the file with components of integer or real or boolean type.
The structuring method (iii) - "sequence of equal-length records" corresponds
to files with components of record without variants, array and set types.
The sequence of variable-length records (iv) corresponds to the
files with components of record types which have variants.
@BThe buffer variables of the files which corresponds to methods (i) and (ii)
are of the types of their components while those of methods (iii) and (iv) are
pointers to their components.
@S34.5.3 Use of MUSS Basic Input/Output Operations
@BInput/output operations are performed in Pascal by the following procedures
and functions. They are mapped on the MUSS operations.@
@
(i)  @OReset(f)@
@
For external files:@
   If file f is already assigned to a stream then@
      END.INPUT (stream, 0)@
   or END.OUTPUT (stream, 0) is called, as appropriate.@
The file is then assigned to any available input stream by calling:@
      DEFINE.INPUT (-1, f, type, unit-size)@
@
For internal files:@
   If file f is already assigned to a stream then@
      SET.IBPOS (0,%10001)@
   or SET.OBPOS (0,%10001) is called as appropriate.@
Otherwise an input/output stream is assigned for the file by calling:@
      DEFINE.IO (-1, SCR*, *,0, 0, type, unit-size)@
@
   type - 00 character@
          01 binary@
          10 unit - the unit size in bytes must be the last parameter.@
          11 record.@
@
@
(ii) @ORewrite(f)@
@BIf file f is already assigned to a stream then END.INPUT,
END.OUTPUT, SETIBPOS or SETOBPOS are called as in (i) above.
@BIf file f is external then it is assigned to any available stream by calling
@
@
DEFINE.OUTPUT(-1,f,type,0,0,unit size/max rec size)@
@
type is as defined earlier@
@BIf file f is an internal file which has not been assigned to a
stream then DEFINE.IO is called as for Reset.@
@
@
(iii)   @OGet(f)@
@
   (a) @Ocharacters@
             f^ := IN.CH@
@
   (b) @Obinary@
             f^ := IN.BIN.S@
@
   (c) @Ounits@
             IN.UNIT@
             f^ := I.VEC@
@
   (d) @Orecords@
             IN.REC@
             f^ := I.VEC@
@
@
(iv)   @OPut(f)@
@
   (a) @Ocharacters@
             OUT.CH(f^)@
@
   (b) @Obinary@
             OUT.BIN.S(f^)@
@
   (c) @Ounits@
             OUT.UNIT@
             f^ := O.VEC@
@
   (d) @Orecords@
             OUT.REC(rec-size)@
             f^ := O.VEC@
@
@
(v)   @ORead(f,x)@
@BA MUSL library PIOLIB provides procedures for reading and
writing variables in accordance with the
PASCAL Standard. It contains the following procedures:
@SPCLOSEFILE(base,operation,mode,size)
@BPerforms RESET, REWRITE or CLOSE on a file.
@SPGET(base)
@BPerforms GET on a text file.@
@SINBOOL
@BReads a boolean value from the current input stream. Prints
error message if the next sequence of characters is not 'TRUE'
or 'FALSE'.
@SOUTBOOL(boolean,width)
@BWrites out a boolean variable with the specified width.
@SOUTINT(integer,width)
@BWrites out an integer with the specified width.
@SINSTRING(addr,length)
@BReads a string of given length from the input stream and puts it
in the byte vector addressed by addr.
@SOUTSTRING(addr,width)
@BPrints the string addressed by addr with the specified width.
@BIn addition the following procedures from the Mathematical
Functions library are used:@
@
   OUTREAL (real, totalwidth, fracdigits)@
Writes out a real with specified width and number of decimal places.
Fracdigits = 0 denotes exponential form.@
@
   INREAL@
Reads a real value from the current stream. Prints error message if
sequence of characters is not a valid real.
@BExamples of the use of these procedures and MUSS input/output
procedures are given below.@
@
   (a) @Ocharacters@
          1. @Ox - a character type@
                    x  := f^@
                    f^ := IN.CH@
@
          2. @Ox - integer type@
                    IN.BACKSPACE(1)@
                    X := IN.I@
                    f^ := IN.CH@
@
          3. @Ox - real type@
                    IN.BACKSPACE(1)@
                    x := IN.REAL@
                    f^ := IN.CH@
@
          4. @Ox - boolean type@
                    IN.BACKSPACE(1)@
                    x := IN.BOOL@
                    f^ := IN.CH@
@
          5. @Ox - string type@
                    IN.BACKSPACE(1)@
                    INSTRING([x],length)@
                    f^ := INCH@
@
   (b) @Obinary@
             x  := f^@
             f^ := IN.BIN.S@
@
   (c) @Ounit and records@
             F  := f^@
             x  := F^@
             IN.UNIT/IN.REC@
             f^ := I.VEC@
@X{|}*
@
(vi)   @OWrite(f,x{:n})@
@X{{}}
@
   (a) @Ocharacters@
           1. @Ox - character type@
                f^ := x@
                OUT.CH(f^)@
                SPACES(n-1)@
           2. @Ox - integer type@
                OUT.INT(x,n)@
           3. @Ox - real type@
                OUT.REAL(x,n,0)@
           4. @Ox - boolean type@
                OUT.BOOL(x,n)@
           5. @Ox - string type@
                OUT.STRING([x],n)@
@
   (b) @Obinary@
           OUT.BIN.S(x)@
@
   (c) @Ounits and records@
           F  := f^@
           F^ := x@
           OUT.UNIT/OUT.REC(rec-sign)@
           f^ := O.VEC@
@
@
(vii) @OReadln(f,x)@
@BThis applies only to the files structured as a sequence of characters.
The MUSS procedures for Read(f,x) are called and then SKIP.LINE@
@
@
(viii) @OWriteln(f,x)@
@BSame procedures as Write(f,x). NEW.LINES(1) is called at the end and it
applies only to textfiles.
@
@
(ix) @Oeoln(f)@
@Bf^ is compared with the line-feed character. The result of the comparison is
assigned to eoln(f).@
@
@
(x) @Opage(f)@
            OUT.CH(form feed character)@
@BFor all the Pascal file handling procedures except reset(f) and rewrite(f),
the stream which the file f has been assigned has to be selected. Thus before
the MUSS operations, SELECT.INPUT(stream no) or SELECT.OUTPUT(stream no)
must be called.@
@S34.5.4 The Representation of File Variables
@BFor each file variable the compiler declares 4 variables:@
@
   A pointer to the name of the file.@
   A buffer variable of appropriate type.@
   An integer variable containing the current stream allocated@
   to the file.@
   A flag giving information about the current state of the file@
   as follows:-@
@3
@
               0 = file undefined.@
   Bit 0@
               1 = file defined.@
   Bit 1       1 = file is input file.@
   Bit 2       1 = file is output file.@
   Bit 3       1 = EOF is true.@
   Bit 4       1 = EOLN is true.@
   Bit 5       1 = Output end-of-line character before resetting@
                   text file.@
@0
@BFor example, the standard files INPUT and OUTPUT have their flags
initialised to 3 and 13 respectively at the start of running a program
or opening a library. Internal files have both of bits 1 and 2 set to
indicate that an IO stream is used for them.

@V9 0
@R5 DESIGN PHILOSOPHY OF THE COMPILER
@BThe compiler structure is similar to the 1900 Pascal compiler
developed by J. Welsh, C. Quinn and K. McShane at Queen's
University, Belfast. This in turn was developed from the
ETH Zurich compiler for the CDC6000 by U. Ammann.
This Chapter describes this structure. There
are four main parts:@
@
@MPart 1  source listing and lexical analysis    @
@NPart 2  syntax analysis and error recovery@
@NPart 3  semantic analysis and error recovery@
@NPart 4  object program generation.@
@
@
Part 1 : Source listing generation and lexical analysis@
@S(A) Source listing generation
@BSource listing generation is implemented by the
following procedures:@
@T# 12
@
NEWCH
@IThis procedure reads the next source character from
the input stream, copies it to the output stream,
and leaves its value in the global variable CH.
CHVAL is set to be the value of the enumerated type CHTYPE
corresponding to CH. CHVAL is used to classify characters and to
convert between equivalent characters.@
@S(B) Lexical Analysis
@BLexical analysis is carried out by the procedure INSYMBOL.
When called, INSYMBOL scans the next language symbol in the
input stream and returns a representation of it in the
following global variables:@
@
SYMBOL
@IIn all cases SYMBOL represents the symbol scanned,
as defined by the type SYMBOLTYPE.@
@
OPERATOR
@IWhen SYMBOL = ADDOP, MULOP or RELOP, OPERATOR
represents the particular operator scanned,
as defined by the type OPTYPE.@
@
IDNAME
@IWhen SYMBOL = IDENT, IDNAME holds the
(first twelve) characters of the identifier
scanned. This enables string comparisons to be
used in checking for a delimiter.@
@
CONSTANT
@IWhen SYMBOL = INTCONST, REALCONST, CHARCONST
or STRINGCONST, CONSTANT holds a representation
of the constant scanned.@
@SPart 2 : Syntax analysis and syntactic error recovery
@S(A) Syntax Analysis
The order, names, and nesting of the procedures is as follows:@
@3
@
    PROGRAMME@
    BLOCK@
        INCONSTANT@
        TYP@
        SIMPLETYPE@
        FIELDLIST@
        LABELDECLARATION     **@
        TYPEDEFINITION       **@
        VARDECLARATION       **@
        PROCDECLARATION      **@
        PARAMETERLIST@
        BODY                 **@
        STATEMENT@
            SELECTOR@
            CALLPROC@
            EXPRESSION@
            SIMPLEEXPRESSION@
            TERM@
                FACTOR@
            ASSIGNMENT       **@
            COMPOUNDSTATEMENT**@
            IFSTATEMENT      **@
            CASESTATEMENT    **@
            FORSTATEMENT     **@
            WHILESTATEMENT   **@
            REPEATSTATENMENT **@
            GOTOSTATEMENT    **@
            WITHSTATEMENT    **@
@0
@BThe procedures marked ** do not correspond to Pascal syntax diagrams
but to particular limbs of the diagram
for the procedure enclosing them. They are introduced only to
break down these procedures into manageable proportions.@
@BThe procedure 'CALLPROC' is introduced to implement the analysis
of actual parameter lists in procedure and function calls,
which is usually shown as duplicate sub-diagrams
within those for 'STATEMENT' and 'FACTOR'.@
@BThe syntax analysers are writen on the assumption that the
next syntactic goal can always be selected by inspection of
(at most) the next incoming symbol (i.e. that the underlying
grammar is LL(1)). This is not so at the following points
in the diagrams actually used:@
@T# 10
@
     1.@IA statement beginning with an identifier may be
either an assignment or a procedure call.@
     2.@IA factor beginning with an identifier may be either
a variable or a function call.@
     3.@IA simple type beginning with an identifier may be
either a named type already declared or a subrange
whose lower bound is a constant identifier.@
@BIn all cases to resolve the choice on a purely syntactic
basis would require a look ahead of a further symbol.
However, if parallel semantic analysis is assumed (as in
stage 3 of this compiler) these choices can be resolved
without further lookahead, by inspection of the current
semantic attributes of the identifier involved. For this
reason syntactic resolution of these choices is not used.@
@BA similar problem arises with the actual parameter lists of
the built-in procedures and functions of Pascal which are
best analysed by special purpose syntax routines. These are
again selected by a semantic rather than syntactic test.@
@S(B) Syntactic error recovery
@BRecovery in the syntax analysis process following the
discovery of a syntax error is incorporated into the
syntax procedures on the following basis:@
@T# 6
@
1.
@IEach procedure when called is passed an actual
parameter which is a set of symbols forming the
(right) context of the string which it should
scan. This context normally includes@
@T# 11
@
      (A)@IAll symbols which may legitimately follow
the string to be scanned.@
      (B)@ISuch additional symbols as a superior
(calling) procedure may wish to handle in
the event of error recovery.@
@T# 6
@
2.
@IWhen entered the procedure may ensure that the
current symbol is an acceptable starter for the
string to be scanned, and if not scan forward
until such a symbol is found (subject to 4. below).@
@
3.
@IWhen calling a subsidiary syntax procedure the
procedure passes on as context its own context plus
those symbols if any which it may determine as right
context for the substring to be scanned.@
@
4.
@ITo recover from a syntax error the procedure may
scan over (skip) any symbol provided it is not
contained in the context passed to it.@
@
5.
@IOn exit the syntax procedure ensures that the current
symbol is contained in the context passed to it,
flagging a terminal error and skipping if this is not
initially the case.@
@SPart 3 : Semantic analysis and semantic error recovery@
@BSemantic analysis and semantic error recovery is implemented by
adding semantic interludes to
the Syntax Analyser.
The semantic analysis depends on the
following globally-defined data structures and manipulative
procedures.@
@
@
(A) The Identifier Table@
@BThis holds an entry for each identifier, either standard or
program defined, which may appear in the program being
compiled. The form of entry used depends on the "Class" of
usage of the identifier and is represented by the variant
record type "IDREC".@
@BThe table is referenced from a hash table with chained
overflow. In any chain the most recent (and highest numbered) scopes
appear earliest in the chain. The exceptions to this are
the parameters of FORWARD procedures and the field identifiers
of records. The IDRECs for these have negative scope levels fields
which are adjusted to the current scope level when the FORWARD procedure
is defined or a WITH statement entered. Thus they are skipped over in
the search for identifiers when they are not included in the current
scope.
@BOn leaving a procedure all the identifiers declared at that level
are removed from the hash table and the identifier table.
@BInsertion and Lookup of identifiers within the table is
provided by the two procedures "NEWID" and "SEARCHID".@
@BStandard identifiers supported by the language are held
within the table as a scope corresponding to a Pseudo-Block
enclosing the main program (at display level 0). These
entries are created by the procedure "STANDIDENTRIES" within
the procedure "INITSEMANTIC".@
@S(B) The Type Table
@BAll types underlying the data defined by the program being
compiled are represented by type entries whose form is
determined by the "FORM" of the type so represented (i.e.
Scalars, Arrays, etc.). Entries are constructed using a
corresponding variant record type "TYPEREC".@
@BThese type entries are accessed only via the identifier
table entries for type identifiers, or via the representation
of the data objects (Variables, Constants, Functions, Expressions)
whose type they describe. Thus for example all identifier
table entries have a common field "IDTYPE" which points to
an underlying type entry (with an obvious interpretation for
all classes of identifier other than "PROC").@
@BWhere types in turn depend on identifiers for their definition
(e.g. an enumerated scalar type such as (False, True)) the
type entries point back to the relevant identifier entries
in the identifier table (i.e. to those for 'False' and 'True').@
@BThe type entries representing the standard types supported
by the language (INTEGER, REAL, ETC.) are created by the
procedure "STANDTYPENTRIES" within the procedure
"INITSEMANTIC". These entries are directly accessible
via Global Pointer Variables "INTYPE", "REALTYPE", etc., as
well as via the identifier entries for "INTEGER", "REAL", etc.@
@BTo facilitate type analysis within the semantic analyser
a general-purpose Boolean Function "COMPTYPES" is provided
to test the compatibility of two types as represented by
pointers to the corresponding type entries. A result True is
returned if the types are identical (i.e. the pointers point
to the same type entry), strictly equivalent (i.e. two
distinct type entries of identical form and content), or
compatible by subrange-to-range transfer.@
@S(C) The Label Table
@BThis holds an entry for each label appearing in the program
being compiled, each entry being of the record type "LABELREC".@
@BThe table is held as a set of linear lists, one for each block
currently open. The block entries within the display serve to
locate these lists, as well as the starting position
for the block in the identifier table.
@BInsertion and Lookup of Labels within the table is provided by
two procedures "NEWLABEL" and "SEARCHLABEL".@
@BRecovery from semantic errors is accomodated within these data
structures and procedures as follows:@
@
(A) Duplicate, Mis-Used and Undeclared Identifiers@
@T# 6
@
(1)
@IIf NEWID finds an entry for the identifier already in
the current scope, an error is flagged but a second entry
is still made (for possible selection by SEARCHID as
below).@
@
(2)
@ISEARCHID when called is passed a parameter specifying
the acceptable classes of entry to be found. If the
first entry encountered for the identifier is not of an
acceptable class searching continues within the current
scope for a possible duplicate entry. If no acceptable
duplicate is found in the scope a Misuse Error is
reported and an anonymous default entry of acceptable
class is returned.@
@
(3)
@IIf SEARCHID fails to find an entry in any scope for the
identifier sought, an undeclared error is reported and
an entry of acceptable class is created for the identifier,
with otherwise default attributes.@
@B(Undeclared labels are similarly handled by the
procedure "SEARCHLABEL").
@S(3) Type Ambiguities
@BIn all situations where the type of a data object is not
determined it is represented by a pointer value "NIL". The
Type-Checking function "COMPTYPES" is defined to return "TRUE"
if either of its parameters has this value. In this way normal type
analysis can proceed without a preliminary screening for
indeterminate types at every point at which
they might arise.
@SPart 4 : Object Program Generation
@S(A) The Generation Interface
@BObject program generation is embedded within the
syntactic/semantic analyser as a set of procedure calls.
These calls, and the types underlying their parameter lists,
provide a generation interface which is independent of the
precise object code to be generated. Between calls the
analyser stores and transmits data of these types but without
any necessary knowledge of their internal nature.@
@BLikewise the generative procedures called should operate
without any knowledge of the analyser's functioning or of the
structures within which it stores the common data.
In practice however it is unnecessarily cumbersome in a one
pass system to segregate e.g. the analyser's data on types
from that which determines and describes their representation
in the object program. In these situations the interface
allows access of the analyser-built data-structures by the
generator procedures. Each case where this is so is noted in
the following summary of the interface procedures.
@S(1) Representation and Storage of Data
@BThe representation and storage of data within the object
program is described by the compiler as follows@
@T# 6
@
1.
@IEach Typeentry carries a field 'DESC'
of type 'DESCRIPTOR' which describes how
such data is to be represented in the object
program.@
@
2.
@IEach Identry for a directly referenceable stored
data item (Variable, Formal Parameter or Function
Result) carries a corresponding field
'TLNAME' which holds the MUTL name
for the run-time access of that data.@
@
3.
@IEach Identry for a record field name carries a
field 'SERIAL' of type 'INTEGER' which
specifies the field's run-time co-ordinates
relative to those of the record as a whole,
that is a MUTL field number.@
@
@IThese compile-time descriptions are generated by two
major procedures.@
@
4.
@IGETDESCRIPTOR which determines the
representation for a given type. For record types
it also determines the field offset for each
field identifier.
GETDESCRIPTOR causes new types to be declared to MUTL
and the corresponding MUTL names to be placed in the analyses
built type entries.@
@
5.
@IXXSTATICSTOREALLOCATION determine calls MUTL to the run-time
address co-ordinates for a Variable, Formal
Parameter or Function result.
A MUTL name returned by XXSTATICSTOREALLOCATION is
placed by VARDECLARATION into the analyses built identifier entry.@
@S(3) Block and Program Housekeeping
@BThe necessary compile and run-time housekeeping
operations associated with the object program are
realised as follows:@
@
1.
@IThe complete generator is initialised by an
operation INITCODEGENERATION before any other
storage allocation or code generative action
takes place.@
@
2.
@IThe necessary Prelude code for each
procedure is realised by the
operation XXSTARTPROCDEFINITION.
The prelude code for the program is created
by XXTLINITIALISATION.@
@
3.
@ITo enable additional housekeeping, and possible
diagnostic actions, appropriate to statement level
the operations@
@T# 6 12
@
#@IOPENSTATEMENT@
#@ICLOSESTATEMENT@
@
@T# 6
@Iare invoked as the initial and final action for
each statement compiled.@
@S(4) Variables, Expressions and Assignment
@BThe code generation interface for variable access,
expression evaluation and assignment assumes a Postfix
code form (though the generating procedures called
transform this code thereafter to the MUTL form). The generating calls
represent operations on a hypothetical run-time stack
of operand references and values, as follows:@
@T# 6
@
1.
@IVariable access is realised by the following
hypothetical operations@
@T# 6 12
@
#@ICONFREFERENCE@
#@ISTACKREFERENCE@
#@IINDEXEDREFERENCE@
#@IFIELDREFERENCE@
#@IWITHREFERENCE@
#@IOPENWITHSTATEMENT@
#@ICLOSEWITHSTATEMENT@
@T# 6
@
@IThe parameter lists for these reference creating
operations enable the complete representation
characteristics of the data items referenced to be
included in the stack entry. This is true for all
stacked operands.@
@
2.
@IExpression evaluation (other than program defined function calls)
is realised by the following additional stack operations:@
@T# 6 12
@
#@INEGATE@
@
#@IFLOAT@
@
#@IPERFORMOPERATION@
@
#@ISINGLETONSET@
#@IRANGESET@
@S(5) Special Operations
@BThe special operations, provided in the source language as
Built-In procedures, are realised partly by MUTL and partly by
special code generation procedures in the compiler. The latter
includes:@
@
#@IFILEPROC@
#@IMATHSFUNC@
#@ICONVFUNC@
#@IORDINALFUNC@
#@ITRANSFERPROC@
#@IDYNAMICSTOREPROC@
@S(6) Control Statements
@BControl Statement code is realised by the following hypothetical
operations:@
@
#@IJUMPONFALSE@
#@IOPENFORSTATEMENT@
#@ICLOSEFORSTATEMENT@
@S(7) Procedure and Function Calls
@BCalls to program defined procedures and functions are realised in
USERPROC by the following operations:@
@
#@ISTACKDESCRIBEDPARAM@
#@ISTACKNAMEDPARAM@
@X %%
