PLN 2

PLASYD - Syntax and Notes

J. K. Buckle

Version: 3

1969

Contents

Appendices

Introduction

This document is a fairly rigorous description of the syntax of the PLASYD language together with informal descriptions of the semantics, programmer's viewpoint and implementation notes. Each section is therefore divided into up to four subsections.

  1. Syntax in modified B.N.F.
  2. Examples where applicable
  3. Semantics and programming notes
  4. Implementation notes where applicable.

Loosely speaking the syntax metalanguage is as follows :-

  1. ::= means "is defined as".
  2. | means "or".
  3. A quantity in angle brackets < > to the left of ::= is a class whose members take one of the forms on the right of ::=.
  4. Appearance of an item in angle brackets to the right of ::= indicates that this may be replaced by any of the members of that class.
  5. An item in angle brackets with associated limits <item>nm means that there may be m, m+1, .... , n consecutive occurences of that item. An upper limit of * means infinity.
    Thus <Asymbol> ::= A
         <name>    ::=<A symbol>41
    
    would allow <name> to take one of the forms A, AA, AAA or AAAA while
         <name>    ::=<A symbol>*0
    
    would allow a null name or A or AA or AAA or .... etc.
  6. A subsidiary backwards definition appearing in parenthesis after a main definition e.g.
         <I assignment> ::= <I Register> ← <I address> (I =:: INTEGER | LONG INTEGER) 
    
    means that the subsidiary definee should be replaced consistently by one of its definitions throughout the main definition. Thus the example above is equivalent to
         <INTEGER assignment> ::= <INTEGER Register> ← <INTEGER address>
    and
         <LONG INTEGER assignment> ::= <LONG INTEGER Register> ← <LONG INTEGER address>
    
    We can think of =:: as "stands for".
  7. The backwards definition of section 5 is valid throughout the description.

Within PLASYD spaces and new lines or end of card (72 characters) are significant and are used, together with other non-alphanumeric symbols, to terminate identifiers, numbers and reserved words. New lines do not however terminate statements. Lines from whatever medium must not be greater than 72 characters, or character positions. Tabs are considered to be at 6 character intervals.

1. Nodes

  1. K =:: INTEGER | REAL | LONG INTEGER | LONG REAL
    
  2. If K appears more than once in a syntactic rule it must be replaced consistently or possibly according to further rules in the accompanying text. Thus, for example
         <K register> ::= <K register identifier> 
    means 
         INTEGER register ::= INTEGER register identifier 
         REAL register    ::= REAL register identifier etc. 
    
         INTEGER         corresponds to the 1900 24 bit signed integer
         REAL            corresponds to the 1900 48 bit floating point number
         LONG INTEGER    corresponds to the 1900 48 bit double length integer
         LONG REAL       corresponds to the 1900 48 bit double length floating point number
    
  3. LONG REAL and LONG INTEGER can be omitted from the first version of the compiler.

2. Basic Symbols

  1. <character> ::=
         A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|
         0|1|2|3|4|5|6|7|8|9|
         +|-|*|/|<|=|>|#|←|,|.|;|:|@|%|"|&|(|)|[|]|£|$|?|'|!
    <basic symbol> ::= <character>|
        AND|OR|ER|NOT|NEG|SLL|SRL|SLA|SRA|SRAV|SLC|SRC|IF|THEN|ELSE|CASE|OF|
        CASEND|WHILE|DO|FOR|STEP|UNTIL|BEGIN|END|GOTO|OBEY|GO|TO|FIX|FLOAT|
        REAL|LOGICAL|INTEGER|CHAR|FUNCTION|PROCEDURE|GLOBAL|LOWER|LONG|EX|
        SYN|ACC|LOWEND|GLOBEND|MINUS|UNDER|FROM|CARRY|CNT|CH|INTERPRET|INCLUDE|
        BASE|OVERFLOW|FOVERFLOW|EXTERNAL|ENTRY|GLABEL|DEFINE|DATA|NULL|SA|LA|
        PURE|PUREND|RETURN|BRINGOVERLAY|NONPLASYD
    
  2. All characters within the symbols [ and ] are ignored as comment, except within strings and character sequences where [ ] are normal characters. Fixed word symbols are terminated by any non alpha-numeric character, including space.

    The symbols := are allowed as an alternative to . The full form of all reserved words must be presented to the compiler.

    There is a facility in the language for conditional compilation. The sequence ?<n> (other than in a string or character sequence, where <n> is a positive integer less than 11, will cause the following PLASYD statements up to sequence )?<n> outside a string or character sequence, to be compiled if system switch <n> is on.

    This can be used for optionally compiled calls to a TRACE package if required.

  3. A full listing of all compiler input should be produced on request. A possible error should be signalled if following a [ another [ is found before a ]. Comment should be made when a section of program is omitted by the ? facility. PURE and PUREND are reserved for future use when writing PURE programs.

3. Identifiers

  1. <letter> ::= A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|%
    <identifier> ::= <letter>|<identifier><letter>|<identifier><digit>
    <K accumulator identifier> ::= <identifier>
    <K cell identifier> ::= <identifier>
    <procedure identifier> ::= <identifier>
    <block identifier> ::= <identifier>
    <lower K cell identifier> ::= <identifier>
    <upper K cell identifier> ::= <identifier>
    <label identifier> ::= <identifier>
    <instruction identifier> ::= <procedure identifier>|<label identifier>
    
  2. A KAREN CATCH22 A1B2 %ASPACE
  3. Identifiers are associated with a K accumulator, a K cell, a procedure or function by an appropriate declaration. They may also be associated with a disc subfile in which case they must also conform to other conventions. Identifiers are restricted to 32 characters in any case.

    The fixed words of section 2 may not be used as identifiers, nor may the fixed accumulator identifiers of section 5.

    Identifiers may only be re-used for quantities with absolutely disjoint scopes. Temporary redefinition of identifiers as in Algol is not permitted.

  4. Since recursion is not specifically catered for there is no need for a run time stack. However, variables in disjoint blocks should be made to share space by the compiler. This can be achieved by keeping current pointers for upper and lower storage and incrementing (decrementing) them at the beginning (end) of a block.

4. Values

  1. <digit> ::= 0|1|2|3|4|5|6|7|8|9
    <unsigned integer number> ::= <digit>*1
    <unsigned long integer number> ::= <unsigned integer number>.<digit>D
    <fractional number> ::= <unsigned integer number>.<digit>|
                                       <fractional number><digit>
    <exponent> ::= <integer number>
    <unsigned real number> ::= <fractional number>|
                               <fractional number>>&<exponent>|
                               <unsigned integer number>&<exponent>
    
    <unsigned long real number> ::= <unsigned integer number>L|
                               <unsigned real number>L
    <K number> ::= <unsigned K number>|MINUS <unsigned K number>
    <octal digit> ::= 0|1|2|3|4|5|6|7
    <octal value> ::=#<octal digit>*1
    <truncated number> ::= <integer number>T<unsigned integer number>
    <count> ::= <integer number> CNT
    <string> ::= "<character>*1"
    <character sequence> ::= '<character>41'
    <integer value> ::= <integer number>|<octal value>|<truncated number>|
                       <count>|<character sequence>
    <long integer value> ::= <integer number> D|<octal value> D
    <real value> ::= <real number>|<octal value> R
    <long real value> ::= <real number> L|<octal value> L
    <unsigned integer> ::= <unsigned integer number>
    
    
  2. #270 45CNT "STRING" MINUS 31T15 '%'
    37 13725.21&24 MINUS 1D 3.14159L
    
  3. Exponents denote an integral power of ten.

    MINUS indicates that the quantity following is to be stored as a negative number. CNT followed by a number means "Store in the top nine bits". This is different to the operator CNT (See Section 8 below).

    Numbers must lie within the limits imposed by hardware.

    A string is a sequence of six bit characters which is stored starting at character position zero of a 1900 word. Strings are space filled to the right to a multiple of four characters. Character sequences normally contain one character only although they may contain up to four. They are a type of integer value and can be considered as a sequence of 6 bit characters zero filled to the left to produce 24 bits. " within a string, and ' within a character sequence are represented by "" and '' respectively.

    A truncated number is formed by producing the binary equivalent of the integer number (which may be signed) and truncating the most significant end to leave only the number of bits indicated by the unsigned integer number.

  4. MINUS, T and the trailing CNT are all compile time operators and are an integral part of the number they are associated with. By contrast NEG and - are run time operators and serve to initiate the particular instruction which should be compiled. See also section 8 below. Truncated numbers may be omitted from the first version.

5. Accumulator Declarations

  1. <INTEGER accumulator> ::= X0|X1|X2|X3|X4|X5|X6|X7
    <modifier> ::= X1|X2|X3
    <LONG INTEGER accumulator> ::= X01|X12|X23|X34|X45|X56|X67|X70
    <REAL accumulator> ::= A1
    <LONG REAL accumulator> ::= A12
    
  2. The integer accumulators correspond to the fixed point accumulators of the 1900 in an obvious way. Similarly for the other types. The LONG REAL accumulator is available only on machines with that hardware.

    The accumulators may be assigned other names by the SYN declaration (see 12 below)

  3. There is no need to implement LONG REAL or LONG INTEGER in the first version of the compiler but "space" should be left for them.

6. Cell declarations

  1. <integer type> ::= INTEGER|LOGICAL
    <long integer type> ::= LONG INTEGER|LONG LOGICAL
    <real type> ::= REAL
    <long real type> ::= LONG REAL
    <K cell declaration> ::= <K type><item>|<K cell declaration>,<item>
    <simple item> ::= <identifier>|<identifier> = <initial value>
    <array item> ::= <identifier>(<array length>)|
                    <identifier>(<array length>) = (<initial value list>)>
    <item> ::= <simple item>|<array item>
    <array length> ::= <unsigned integer number>
    <inital value list> ::= <initial value>|
                           <initial value>=<array length>|
                           <initial value list>,<initial value list>
    <initial value> ::= <K value>|<string>|<fixed address>|<function statement>|
                       <count> + <fixed address>|<count> + <integer number>|
                       <count> + <truncated number>|<count> + <octal value>
    <declaration list> ::= <K cell declaration>|<base declaration>|
                              <declaration list>;<declaration list>
    <base declaration> ::= BASE
    <block declaration>::= <block identifier>:<declaration list>
    <global tail> ::= <block declaration>GLOBEND|<block declaration>;<global tail>
    <global declaration> ::= GLOBAL <global tail>
    <lower block> ::= <declaration list>|<global declaration>|
                     <lower block>;<lower block>
    <lower declaration> ::= LOWER <lower block> LOWEND
    
  2. REAL X, Y, Z; INTEGER I, J = 13,K; LONG REAL P(L);
    REAL XAR(20), NEXT, YAR(10)=(4.3,2.4,0.0,* 6, 1.0); BASE;
    INTEGER Z(20) = (@I,257CNT + @J, 131CNT + 7, MINUS 4,!LDX(1,0);
    LOWER REAL VW, MGB; GLOBAL BUFF:INTEGER B(32) GLOBEND LOWEND ;
    
  3. A cell declaration introduces identifiers and associates them with calls of the specified type. The validity is throughout the block in the head of which the declaration occurs. Moreover the declaration may specify an initial value to be stored in the cell. This is permanent in the sense that it will be reset by any overlay. Initial values may only be assigned to quantities in an outer block or a segment. A string is stored in successive character positions beginning at character 0 and is space filled to a multiple of four characters.

    Initial values must be of the same type as the cell and for this purpose addresses, strings, function statements and values with <count> as a component are considered to be integer.

    If a cell identifier is followed by an integer or an absolute quantity (see section 24) in parenthesis, that number of storage cells will be allocated to make a one dimensional array. The number of 1900 words assigned to each cell is as follows :-

    INTEGER, LOGICAL    -  1 word
    REAL, LONG INTEGER  -  2 words
    LONG REAL           -  4 words
    

    An initial list of m entries specifies initial values for the first m elements of the array. If an initial value is followed by *n it is equivalent to n identical initial values. Each initial value will correspond to one element of the array, unless the initial value is a string, in which case it will fill as many words as necessary.

    All identifiers (except label or procedure identifiers) must be declared before they are used. Thus in the examples I had to be declared before @I was used as an initial value. <fixed address> is the location (to 22 bits) of the K cell or label or procedure concerned, and may possibly also involve a character address. For details see 7, 8 below. The L in the LONG REAL declaration is assumed to have been set by a define statement - see 24 below.

    A global declaration makes COMMON blocks of all the block declarations it contains. The block identifier is the common block name and the decision on whether the block is permanent or overcommon is delayed until consolidate time. Block declarations with the same identifier are added sequentially.

    A block identifier and a cell identifier must not have the same name e.g. GLOBAL JACK: JACK is not allowed.

    All items within a LOWER declaration are forced into the first 4096 words.

    Upper (i.e. non LOWER) non-GlOBAL locations are dealt with in the following way :- the address of the first upper storage location mentioned. is stored in lower and this becomes the base of a "domain" of up to 4096 words. All subsequent cells are stored in consecutive locations and are addressed by their "displacement" from this base. If a base declaration appears a new base is stored and subsequent addresses are relative to that. If 4096 words are declared without a base statement appearing a new base is inserted by default and a comment listed.

    Each non-lower block declaration has a new base associated with its first word and this base is stored in a location which is associated with the block identifier. Additional bases may be introduced by base declarations.

    All lower quantities have a base of zero and a displacement which is their address, regardless of whether they are global or not.

    Upper non-global items will be stored in successive words in the order of declaration. So will items within a global block.

    Either the initial values given to the variables in global block should be identical in all segments or they must be assigned in one segment only.

  4. The compiler must deal with what are effectively a number of compile time stacks. These are:

    • The lower stack - begins at some lower word and contains all lower quantities. Note that other segments will also use lower storage and that lower blocks cannot have bases.
    • The upper stack - all non global upper quantities.
    • The global stacks - one for each block declaration.

    For each stack there must be a stack pointer to the last used (or first unused) word of the stack. This will be incremented as declarations are encountered. and decremented as blocks are left. The pointer for the lower stack is a simple (relative) address. For the upper stack and for each global stack is the current base address (which is stored in lower and will be a relative address) plus an absolute displacement. Exit from block may well cause alteration of the current base as well as the displacement. Obviously the maximum reached by any stack at any point must also be recorded. The cell symbol table entries must contain the following information.

    1. The type of cell
    2. Its base address and the location of its base in lower
    3. Its displacement
    4. The block number of its declaration

    On exit from a block corresponding symbol table entries will be destroyed. Both the items under 2 are needed, the first for compile time calculated, the second for run time use.

    The blocks within a procedure declaration may share storage with each other but the maximum amount of storage declared throughout the definition of the procedure must be reserved throughout the life of the block in which the procedure is declared. (As a first shot, which would probably not waste much in practice, all declarations at any depth would constitute declarations at the level of the block in which the procedure is declared). Character arrays must begin in the first character of a word. Once an array has been declared there is no reason to distinguish between arrays and simple variables.

    All non-global variables go into upper or lower preset. However, global blocks should go into preset if any initial values are set, variable otherwise.

7. Cell designators

  1. <K cell designator> ::= <simple K cell designator>|(<free SMO index>)|
                           <K cell identifier>(<SMO index>)
    <simple K cell designator> ::= <lower K cell identifier>|(<free index>)|
                                  <lower K cell identifier>(<fixed index>)|
                                  <K cell identifier>(<variable index>)
    <variable index> ::= <modifier>|<modifier>+<unsigned integer>|
                        <modifier>-<unsigned integer>
    <free index> ::= <unsigned integer>|<modifier>|<modifier>+<unsigned integer>
    <fixed index> ::= <unsigned integer>|-<unsigned integer>
    <simple SMO index> ::= <simple integer cell designator>|
                          £<K cell identifier>|<block identifier>
    <free SMO index> ::= <simple SMO index>|<simple SMO index>+<free index>
    <SMO index> ::= <free SMO index>|<simple SMO index>-<unsigned integer>|
                   <simple SMO index>+<modifier>-<unsigned integer>
    
  2. A (X1)  (X1 +5) (30)  A(8) A(-8) A(X1) 
    
    A(X1-10) U(X2) U(X3+5) B((6)) A(B) A(B+X1-1) 
    
    U(B+X3-1) (B) U(B(X1-5)+X2-1) U(£U) (BLOCK+3) 
    
    ((X3)) U(£U+X1-70) U(V(X1)) 
    
  3. Cells are denoted by cell designators. In the case of cells of simple lower type (i.e. declared within a LOWER declaration) the designator can consist simply of the identifier associated with that cell. In the case of lower arrays the array name is followed by an index which designates an element of the array. The index value is divided by the number of memory units (words) occupied by each cell and this is used as the element number of the array to be addressed. The first element of an array has number zero. The result of the division must be positive and the remainder zero. Indices can also be applied to simple variables. The simple variable is then treated as an array with an indefinite number of elements whose first element is the simple variable itself. Similarly references can be made to array elements outside the declared size of the array. In the case of upper variables and arrays a special course is adopted to overcome the 12-bit address field of the 1900. This works in the following way :-

    The address of an element A in upper is known as @A and consists of two parts. The first is the base of the domain in which A exists and will be in general a 22 bit address. This is referred to as £A. The displacement of the element from this base in storage units (words) is referred to as $A. This must always be ≤ 4095. If an upper quantity is to be referenced it must have an index following the identifier and this must contain the £A part of the address either as an explicit quantity e. g. U(£U), or by reference to a store location which contains this quantity e.g. U(B+3) where B contains £U possibly as a constituent of its value, or by reference to a modifier e.g. U(X1) where the contents of X1 are similar to B. Thus the reference to an upper quantity outside the index is really only a reference to its $ part. The user is required to set up the store location or the modifier with the correct value himself. Attempts to refer to upper quantities without subscripts or with constant subscripts will be faulted.

    Indices with no preceding address are taken as a reference to an element of the untyped array which begins at word zero of the store and runs to the end of the store. Thus(30) indicates word 30 of tbe store and ((X3)) indicates the word whose address is held in the word whose address is held in the modifier X3. Integer accumulators may be treated as store locations by this means e.g. (1)

    Note that all use of SMO indices will produce a SMO instruction in the object code. The appropriate method of compilation should therefore be in use.

    The constant parts of indices when added into or subtracted from the displacement must produce a result between 0 and 4095 inclusive.

  4. Assuming that A is a lower quantity, B is a lower integer, U and V are upper quantities and V is an integer, and BLOCK is a block identifier the examples of part b are equivalent PLAN addresses in non literal instructions as follows :-

         
        PLASYD                       PLAN                    NOTES   
        ------                       ----                    -----
           A                           A     
      1.   (X1)                      0(1)     
      2.   (X1+5)                    5(1)     
      3.   (30)                      30     
      4.   A(8)                      A+8                       1   
      5.   A(-8)                     A-8                       2   
      6.   A(X1)                     A(1)     
      1.   A(X1-10)                  A-10(1)     
      8.   U(X2)                     $U(2)     
      9.   U(X3+5)                   $U+5(3)     
      10.  B((6))            SMO     6                         3   
                                     B     
      
      11.  A(B)              SMO     B     
                                     A     
      
      12.  A(B+X1-1)         SMO     B     
                                     A-1(1)     
      
      13.  U(B+X3+1)         SMO     B
                                     $U+1(3)                   1   
      
      14.  (B)               SMO     B     
                                     0     
      
      15.  U(B(X1-5)+X2-1)   SMO     B-5(1)     
                                     $U-1(2)                   2   
      
      16.  U(£U)             SMO     £U     
                                     $U                        4   
      
      17.  (BLOCK +3)        SMO     BLOCK A     
                                     3                         5   
      
      18.  ((X3))            SMO     (3)      
                                     0     
      
      19.  U(£U+X1-70)       SMO     £U
                                     $U-70(1)     
      
      20.  U(V(X1))          SMO     $V(X1)     
                                     $U
    

Notes

  1. A+8 and $U+1 must not be ≥ 4K.
  2. A-8 and. $U-5 must be positive or zero.
  3. SMO could be replaced by an SMO macro - see below.
  4. £U is a lower location which contains the address of the domain in which U appears. It can always be treated thus except in an initial value when the domain address itself must be used.
  5. BLOCK A is the address of the initial base of the common block BLOCK.

The pseudo SMO macros for

SMO      N1(N1)
XXX  X   N2(N2)

where SMO has not been produced by !SMO are as follows :-

  1. If the second address is not modified (e.g. 11,14,16,17,18,20) i.e. No M2
          STO     M    WS    [some workspace] 
          LDX     M    N1(M1)  
          XXX     X    N2(M) 
          LDX     M    WS 
    
    Where M is an modifier other than X
  2. If M2 is present but is not the same as X (e.g. possibly 12, 13, 15, 19)
      
          STO    M2    WS   
          ADX    M2    N1(M1)   
          BVSR         * + 1   [in the case of overflow]   
          XXX    X     N2(M2)   
          LDX    M2    WS   
          
  3. M2 ≡ X (e.g. as ii). Let M3 be any modifier other than M2 (Note that a simple macro could be used for the LD or NGX, NGN instructions but is probably not worth it).
          STO   M3   WS   
          LDX   M3   N1(M1)   
          ADX   M3   M2   
          BVSR       * + 1   
          XXX   M2   N2(M3)   
          LDX   M3   WS
    

Note that any previous overflow will be lost in cases (ii) and (iii) and that carry will be cleared by the pseudo SMO which is different from the actual SMO and if carry is set the accumulator M is corrupted by the addition of 1.

8. Accumulator assignments

  1. <K primary> ::= <I accumulator>|<K value>|<K cell designator>
                          (I=::INTEGER|LONG INTEGER)
    <simple K accumulator assignment> ::= <A accumulator>+<K primary>|
             <A accumulator>←NEG<K primary>|<R accumulator>←<R accumulator>|
             <integer accumulator>←CNT<C operand>|<address assignment>
                          (A=::K|LONG K; R=::REAL|LONG REAL)
    <address assignment> ::= <integer accumulator>←<address>|
             <integer accumulator>←<integer accumulator>+<address>
             <integer accumulator>←<integer accumulator>-<K word address>
    <K word address> ::= @<K cell designator>|$<K cell designator>|
                        £<K cell identifier>|@<K cell identifier>(<fixed index>)|
                        $<K cell identifier>(<fixed index>)
    <address> ::= <K word address>|CHAR <unsigned integer>|
                                CHAR <unsigned integer> OF <K word address>
                                         @ <instruction identifier>
    <fixed K word address> ::=  @<fixed K cell designator>|
                                   $<fixed K cell designator>|£<K cell identifier>|
    <fixed address> ::= <fixed K word address>|CHAR <unsigned integer>|
                       CHAR <unsigned integer> OF <fixed K word address>|
                       @<instruction identifier>
    <monadic operator> ::= CARRY|EX|CH|NEG CARRY
    <K accumulator asssignment> ::= <simple K accumulator assignment>|
        <long integer accumulator assignment>/<integer cell designator>|
        <A accumulator assignment><arithmetic operator><K primary>|
        <real accumulator assignment><reverse operator><real primary>|
        <integer accumulator assignment><logical operator><integer primary>|
        <I accumulator assignment><shift operator><C operand>
        <real accumulator>←FLOAT<I cell designator>
          (I=::integer|long integer;A=::INTEGER|REAL|LONG REAL)
    <arithmetic operator> ::= <add operator>|*|/
    <add operator> ::= +|-|++|--
    <reverse operator> ::= FROM|UNDER
    <LOGICAL OPERATOR ::=  AND|OR|ER
    <shift operator> ::= SLL|SRL|SRA|SRAV|SLA|SLC|SRC
    <c operand> ::= <unsigned integer number>|<octal value><modifier>|
                       <simple integer cell designator>
    
  2. X1 ← 3          X1  ← X2              X1  ← A(B+X1-3)   
    A1 ← 3.14159    X12 ← 1D              X2  ← NEG 1   
    X6 ← CNT 12     X0  ← CARRY V(£V)     X70 ← U(X3)   
    X7 ← CH B(X1)   X6  ← '%'             X1  ← CNT X1   
    
    X1 ← @A(3)      X3  ← CHAR 1 OF £C    X6  ← X6+$U   
    
    X6 ← A/B-213    A1  ← A1 UNDER PI     X0  ← B AND #6617   
    X4 ← X1 SLL 6   A1  ← FLOAT B         X1  ← X1*X6   
    X12← X12/B      X4  ← CNT (6)         X7  ← X7 SRA B(X1+3)  
    
  3. An assignment statement allows the values designated on the right of the ← symbol to be assigned to the accumulator on the left. Operators in general parallel closely available machine functions.

    In this document the syntax given in (a) may not bo completely rigorous in that certain operations may not be (im)possible although (not) specified above. Attempts will be made to clear this up in later editions. As a general rule combinations which produce one 1900 machine instruction per operand, possibly with a preceding SMO order, are allowed. The syntax also fails to define certain limitations imposed by the operation of the 1900 e.g. the value following the shift operator should be less than 10 bits. More details of the meanings of operators are given below and in (d).

    Assignments are carried strictly from left to right including the initial assignment. Thus

    X1  ←  X1+X2    is quite different from
    X1  ←  X2+X1    which is however, the same as the sequence
    X1  ←  X2       and
    X1  ←  X1+X1 
    

    Unnecessary load instructions will not be compiled and the two similar sequences will produce identical machine code.

    Operators have their obvious or PLAN meanings where these exist. Possibly unfamiliar operators are as follows :-

    NEG      Negate the following operand
    CNT      Place the following operand in the top 9 bits
    CARRY    Use a load-setting-carry instruction 
    EX       Consider only the bottom 9 bits of the operand
    ++ )     Use a carry setting instruction with integers
    -- )     undefined for other types at present
    FROM     Reverse subtraction - reals only 
    UNDER    Reverse division - reals only
    
    CH       The following operand designates a 6-bit character. 
    FLOAT    Convert the integer in the first word and the fraction in the 
             second to real. 
    

    Address assignments place, subtract or add an address into or from an accumulator. i.e. the same accumulator must be specified. on both sides of . The @ $ and £ symbols are explained in section 7. CHAR <integer number> indicates a 1900 character modifier for that number of characters and the integer number must be in the range 0 to 3. The only way of designating a particular character storage cell is by use of a character address set up in this fashion as an initial value or by assignment as an index.

    For some instructions, multiplication and division of integers in particular, the 1900 order code places some nasty restrictions on operands and introduces messy side effects. If N and X are lower integers the following holds:

       A1←FLOAT N   expects N (1) to be cleared (or set to a fraction) 
       X1←N*X       produces an integer result in X1 but destroys X2 (sets it to zero) 
                    and involves a shift instruction. To obtain a long integer result 
                    more conveniently a function (see 10) should be used. 
       X1←N/X       produce an unrounded integer result in X1 and a remainder in X0 
    or X01←X01/X    (DVS or DVD) 
    

    Assignment of a character sequence to an integer accumulator puts it in the least significant bits with zeros elsewhere.

    Note that FLOAT accesses either an integer and the next word or a non-standard long integer. K cells whose type is not obvious e.g. (3),(X1) are assumed to be of the correct type for the L.H.S.

  4. The primary aim in defining the syntax is to allow only operations which are easily reduced. to machine orders without redundancies. Only where the 1900 order code shows pathological deficiencies is this aim dropped.

    General rules for compilation of assignment statements are :-

    1. X1←X1 should never produce code
    2. Literal operand instructions should be used wherever possible.
    3. The only PLAN type literals generated. are for non-zero, non-integer numbers or integers > 4095 modulus and character sequences of more than 2 characters.
    4. The compiler should never make assumptions about the programmer's intentions without at least flagging them.
    5. Checks should be made on 12-bit fields to ensure that they are 12-bits.
    6. Implied use of accumulators e.g. division, should produce a comment.

    The following is the code produced for the examples of (b) assuming the same declarations as in section 6, plus a lower real PI. More detailed notes follow.

            
            PL 1900                          PLAN EQUIVALENT   
    1.  X1  ← 3                        LDN      1        3
    2.  X1  ← X2                       LDX      1        2
    3.  1   ← A(B+X1-3)                SMO               B
                                       LDX      1        A-3(1)
    4.  A1  ← 3.14159                  LFP               '.3145159E1'
    5.  X12 ← 1D                       LDN      2        1
                                       LDN      1        0
    6.  X2  ← NEG 1                    NGN      2        1
    7.  X6  ← CNT 12                   LDCT     6        12
    8.  X0  ← CARRY V(£V)              SMO               £V
                                       LDXC     0        $V
    9.  X70 ← U(X3)                    LDX      0        $U+1(3)
                                       LDX      7        $U(3)
    
    10. X7  ← CH B(X1)                 LDCH     7        B(1)
    11. X6  ← '%'                      LDN      6        #25
    12. X1  ← CNT X1                   LDCT     1        (1)
    13. X1  ← @A(3)                    LDN      1        A+3
    14. X3  ← CHAR 1 OF £C             LDCT     3        128
                                       ADX      3        £C
    15. X6  ← X6+$U                    ADN      6        $U
    16. X6  ← A/B-213                  LDX      6        A
                                       DVS      5        B
                                       SBN      6        213
    17. A1  ← A1 UNDER PI              FDVD     4        PI
    18. X0  ← B AND #6617              LDX      0        B
                                       ANDN     0        #6617
    
    19. X4  ← X1 SLL 6                 LDX      4        1
                                       SLL      4        6
    20. A1  ← FLOAT B                  FLOAT             B
    21. X1  ← X1*X6                    MPY      1        6
                                       SLA      12       23
    22. X12 ← X12/B                    DVD      1        B
    23. X4  ← CNT X1                   LDCT     4        0(1)
    24. X7  ← X7 SRA B(X1+3)           SMO               B+3(1)
                                       SRA      7        0
    

NOTES

Example 5
This may be difficult to implement and if so the facility should be removed from the language rather than unnecessarily complicating the compiler. Note that the non-carry setting loads are used for the least significant word. In any case LONG will not be in the first implementation.
Example 5
Note that X2 ← -1 is not allowed and X2 ← MINUS 1 is different, translating into LDX 2 '-1'. This is not particularly useful although X2 ← X2*MINUS 1 would be. X2 ← MINUS 32000 is the same as X2 ← NEG 32000.
Example 9
Note that LDX, LDX is used not LDXC, LDX. This allows reals or strings to be placed in a double length accumulator.
Example 10
The character loaded will depend on the contents of X1.
Example 11
A one or two character sequence will always produce a LDN.
Example 12
We recognise this as a modifier. If it had not been, a SMO would have been generated. The same applies to a shift operator (see examples 23 & 24). Note that shifts and CNT have an implied one level bracketting.
Example 13
Were A in upper this would produce 2 instructions LDX 1 £A and ADN 1 $A+3.
Example 14
But + CHARn should be done by n BCHX instructions.
Example 15 & 17
Note no redundant loads.

Long integer operations are similar to the corresponding PLAN macro except that constant loading is more efficient. When the right hand side is an integer the sign bit is removed and propagated through the first word. X12 ← N where N is an integer should produce

LDXC     2        N
NGN      1        0 

If any long integer facility produces problems we should modify the specification rather than introduce inefficiencies into the compiler or object program. Note that CNT can be used as an operator or as part of an integer value. They produce the same results for a simple assignment but by different means e.g.

X1 ← 324CNT    ⇒    LDX   1   '324/0'
X1 ← CNT324    ⇒    LDCT  1   324

The second is obviously better although the other form is essential for

X1 ← X1 + 324CNT    ⇒    ADX   1   '324/0'

EX indicates a LDEX instruction.

9. Cell assignments

  1. <simple K cell assignment> ::=
       <K cell designator>←<K accumulator>|
       <I cell designator>←<0|
       <real cell designator>←0.0|
       <Integer cell designator>←<store operator><integer accumulator>|
       <Integer cell designator>←<part operator><integer accumulator>|
       <I cell designator>←<I cell designator>|
       <simple I cell assignment><add operator><I accumulator>
       <simple I cell designator><logical operator><I accumulator>
       <Long integer cell designator>←NEG<long integer accumulator>
             (I=:: Integer|long Integer)
       <store operator> ::= NEG|CARRY|NEG CARRY
       <part operator> ::= EX|SA|LA|CH
       <K cell assignment> ::= <simple K cell assignment>|
                             <long integer cell designator>←FIX<real accumulator>
    
  2. A ← X1         U(B(X2)+1) ← 0         B ← NEG X2
    XX ← LA X3     A(3) ← X3+X2 AND X5    C(X1) ← CH X7
    X ← A1         W(X1) ← FIX A1         B(4) ← B(4) ++ X0
    (3) ← FIX A1   (3) ← A1               (X1) ←SA X6 
    
  3. A cell assignment is used to assign a value to a designated cell. The values must normally be accumulator values. If an I cell designator appears on each side of the ← symbol then these designators must be identical. (Thus the fifth simple K cell assignment form is X ← X and is useful only as part of the two forms which follow). The designators must also appear on the same line.

    The operators NEG, CARRY, EX and CH are similar to those for accumulator assignments except that EX does not disturb the remaining bits of the cell and the bottom six bits of the accumulator are used for CH, the character position of the cell being determined by the modifier if any. SA and LA mean the bottom 12 and 15 bits respectively, again without disturbing the remaining bits. The FIX operator, causes the largest integer less than the real number to be left in the first word of the long integer cell and a fractional part in the second. Note that it is inefficient to use assignments involving several logical or add operators with cells involving SMO indices.

    K cells whose type is not obvious e.g. (3), (X1) are assumed to be of the correct type for the R.H.S.

  4. The implementation is fairly obvious. Plan equivalents of (b) assuming suitable declarations are as follows:-

            
          PLASYD                       PLAN     
          ------                       ----
    A1 ← X1                     STO      1        A
    U(B(X2)+1) ← 0              SKO               B(2)
                                STOZ              $U+1
    B ← NEG X2                  NGS      2        B
    XX ← LA X3                  DLA      3        XX
    A(3) ← X3+X2 AND X5         STO      3        A+3
                                ADS      2        A+3
                                ANDS     5        A+3
    
    C(X1) ← CH X7               DCH      7        C(1)
    X ← A1                      SFP               X
    W(X1) ← FIX A1              FIX               $W(1)
    B(4) ← ++ X0                ADSC     0        B+4
    (3) ← FIX A1                FIX               3
    (3) ← A1                    SFP               3
    (X1) ← SA X6                DSA      6        (1)
    

10. Function declaration

c) By providing all the 1900 machine functions as standard the need to provide for an alternative method of labelling them is lessened. This section is therefore omitted from this document. The function definition may however, form a convenient way of providing simple local macro facilities which could be incorporated in versions of the compiler other than the first.

All the machine codes are available to the programmer as functions with their PLAN names preceded by the symbol ! with the exceptions that machine codes 111, 113, 115 are the PLAN name followed by the symbol 2, e.g. !SLC2, !NORM2, etc. Additional mnemonics for writing Trusted programs have been introduced namely: !SPP { (set PUC parameter) !ACT (Activate PUC) and !RMS (Request console message).

The method of calling these functions is defined in the next section.

11. Function statements

  1. <function statement> ::= <function identifier>(<X parameter>,<N parameter>)
    <function identifier> ::= !(identifier> 
    <X parameter) ::= <octal digit)|<integer accumulator>|<1ong integer accumulator> 
    <N parameter> ::= <simple K cell designator>|<unsigned integer number>| 
                      <octal value>|<character sequence>|<instruction identifier> 
    
  2. !CDB  (X34,C(X1))  !LDN (X1,4)  !GIVE(0,A(X2+3))  !FAD(3,B) 
    !LFPZ !NULL. 
    
  3. The function statement calls for the execution of one 1900 machine instruction. Note that the use of SMO indices in the cell designator is strictly forbidden. The octal digit and following ',' can be omitted in functions which do not require them (e.g. BVSR). The digit but not the comma may be omitted to imply zero. The N parameter must not exceed 12 bits plus an optional modifier, or must be an instruction identifier.

    Note that !LFPZ and !NUL !SUSAR do not have X or N parameters and !ACT and !SPP have only N parameters as X7 is assumed.

  4. The action is merely to produce a function with the first parameter in the accumulator field and the second in the address field. If a long integer accumulator is specified the first accumulator of the pair is used. No check is made on the use of long accumulators in this way. The effect of the extension of the definition to provide macros is given in Appendix 3.

12. Synonym declarations

  1. <K cell synonym declaration> ::= 
                 <K type> <identifier> <synonymous cell>|
                 <K cell synonym declaration>,<identifier><synonymous cell> 
    
    <synonymous cell> ::= SYN(<fixed K cell designator| 
                           SYN(<integer value>=<initial value> 
    <K accumulator synonym declaration> ::= 
                              ACC<identifier> SYN <K accumulator>| 
                <K accumulator synonym declaration>,<identifie>SYN <K accumulator> 
    
    <fixed K cell designator> ::= <K cell identifier>|<K cell identifier>(<fixed index>)
    
  2. INTEGER A16 SYN A(16)
    INTEGER MEM SYN(0)
    REAL FP SYN (0)
    INTEGER SWITCHES SYN(30)=#770047
    ACC SUM SYN A1
    INTEGER B1 SYN A(-4)
    REAL X = 1.7385
    INTEGER XTOP SYN X, XBUTT SYN X(1)
    
  3. Synonym declarations associate extra names with cells or accumulators. The types associated with synonymous cells need not agree. The last examples show a use of this facility.

    The synonymous cell must have been declared before the synonym declaration. When the original is an integer value the synonym is taken as referring to that absolute location of the program. Only with this type of synonymous declaration can an initial value be set. The synonym given to an absolute location can be used wherever a normal K cell identifier could be used. In particular this facility can be used to make the fixed point accumulators act as K cells as in the second and third example above. Thus although X0←(X1) produces LDX 0 (1), X0←(MEM(1)) produces SMO 1, LDX 0 0. A fixed K cell designator using a fixed index should not be such that the cell designated is in a different domain to the cell designated by the identifier alone.

  4. Synonym declarations need to operate as normal declarations except that the storage, base and displacement assigned to the new identifier are the same as the original or are the absolute value stated. The type bits will however not be similar. Note that SYN<integer value> = <initial value> is accepted.

13. If statements

  1. <relation> ::= <|≤|=|≥|>|NOT=
    <character relation> ::= <CH|≤CH|>CH|≥CH
    <condition> ::= <K accumulator><relation><K primary>|
                   <I accumulator><relation><part address>|
                   <I accumulator><character relation><I primary>|
                   OVERFLOW|FOVERFLOW|CARRY|NOT OVERFLOW|NOT FOVERFLOW|
                   NOT CARRY  (I=:: INTEGER| LONG INTEGER)
    <part address> ::= £<K cell identifier>|$<K cell designator>
    <combined condition> ::= <condition>|<combined condition> AND <condition>
    <alternative condition> ::= <condition>|<alternative condition> OR <condition>
    <compound condition> ::= <combined condition>|<alternative condition>
    <if clause> ::= IF <compound condition> THEN
    <true part> ::= <simple statement> ELSE
    <if statement> ::= <if clause> <statement>|
                      <if clause><true part><statement>
    
  2. IF X0≤0 THEN X2←3
    IF A1 > MINUS 3.75 AND X1 < A(4) THEN A(4)←0 ELSE A(X1)←0
    IF X1 NOT = 0 THEN X3←X3 SLL 2 ELSE
       IF NOT OVERFLOW THEN A1←0.0
    IF X7>'%' THEN GO TO BED
    
  3. A condition is either met or not met. If the condition is met the statement following is obeyed, if not the statement following ELSE if present, is obeyed. A combined condition is met only if all its constituent conditions are met. An alternative condition is met if any of its constituent conditions are met. FOVERFLOW indicates floating point overflow and requires the extended or pseudo extended instruction set. Testing OVERFLOW clears it. If CARRY is part of a multiple condition it should be the first item. Character comparisons depend on 1900 internal 6 bit code. CH implies a character or unsigned comparison.
  4. The statement can be implemented by a fairly straightforward sequence of jumps. OVERFLOW should use BVSR. 076 should be used if available in the instruction set in use. If not a macro produced by dumping X1 and X2 say, SPP 1, testing X1, 2 followed by a restore. Conditions involving 0.0 or 0 to the right of a relation should be specially recognised and compiled efficiently. The remainder will involve subtractions of TXU. TXL can be used for character comparisons. Comparisons with zero should be very efficient. See PLN 12 for details.

14. Case statements

  1. <case clause> ::= CASE <modifier> OF
    <case sequence> ::= <statement>|<case sequence>;<statement>
    <case statement> ::= <case clause><case sequence> CASEND
    
  2. CASE I OF
            A1 ← A1 + B;
            A1 ← A1 - B;
            A1 ← A1 * B;
            A1 ← A1 / B;
            A1 ← A1 UNDER B;
    CASEND
    
  3. Statements in case instructions must translate to single machine instructions. The sequence is considered to be numbered starting at zero and the statement whose ordinal number is the value of the modifier is executed. The modifier is destroyed by this instruction.
  4. Case sequences are stored in upper, the address of the first is added into the modifier and this is followed by a modified OBEY.

15. Goto statements

  1. <go to statement> ::= GOTO <instruction identifier>
    
  2. GOTO L3
    
  3. If the goto crosses block boundaries the blocks are effectively closed. GOTO <procedure> means that no return will be made automatically. The effect of the statement is to transfer control to the labelled statement or to the first instruction of the procedure. GOTO may be written as one or two words.

    Procedures and labels need not be declared before use unless they are external (see section 20).

  4. GOTO a local quantity produces a straight BRN, GOTO a non-local (but previously declared) procedure name produces

         BRN <cue>
    

    where the cue is for the quantity <procedure name> @ unless the <procedure name> has been declared in a LOCAL statement. <procedure name> @ is an associated common area explained in section 20. If a reference is made to a label or procedure name which has not been declared it should be treated as an internal quantity. If the procedure has been declared as LOCAL then <cue> is <procedure name>. This enables segments which do not have associated common areas to be incorporated. Outstanding labels at the end of the segment are errors.

16. Obey statements

  1. <obey statement> ::= OBEY<integer cell designator>
    
  2. OBEY U(V(X1)+1)
    
  3. The integer cell designated is assumed to contain an instruction which is obeyed. The instruction must not cause an illegal sequence of SMO's.
  4. Simple obey statement.

17. For statements

  1. <increment> ::= <integer primary>|-<integer primary>| CHAR
    <limit> ::= <integer primary>|<part address>
    <for clause> ::= FOR <integer accumulator assignment>
                     STEP <increment>
                     UNTIL <limit> DO
    <for statement> ::= <for clause><statement>
    
  2. FOR I  ← 1 STEP 2 UNTIL 7 DO A1  ←  A1+X(I)
    FOR X1 ← CHAR 1 OF @ BUFF STEP CHAR UNTIL ENDBUFF DO (X1) ← CH X7
    FOR X3 ← S STEP -1 UNTIL 0 DO BEGIN A(X3) ← 0;B(X3+1) ← 0 END
    FOR X3 ← $FRED STEP 1 UNTIL $JACK DO X1 ← X1+X3;
    
  3. For statements allow a statement to be executed repeatedly while the integer accumulator takes varying values. At each execution except the last, the accumulator is increased by the increment and tested for non-equality with the limit. If this test succeeds the statement is executed, if not the statement is executed once more and control then passes to the next statement. Note that to terminate the loop other than by jumping out the integer variable must reach exactly the value of the limit (if this cannot be guaranteed a WHILE statement should be used). A step of CHAR, means that the accumulator is considered as a modifier and stepped on by one character address. Note that if a complicated expression is to be used as a limit it must be first calculated and then held in an accumulator or stored. A limit of zero will be more efficient than any other.

  4. There are several ways of implementing this and no one seems to stand out. If the limit is zero a straight 05 group can be used as a test. The restriction that the accumulator must "hit" the limit means that for K cells, a large constant or another accumulator a TXU can be used. It could also be used for small constants although this might produce a lower problem with literals. If so a SBN, 05, ADN could do it at the expense of one instruction. Steps of CHAR should use a BCHX instruction.

18. While statements

  1. <while clause> ::= WHILE <compound condition> DO|DO
    <while statement> ::= <while clause><statement>
    
  2. WHILE A1 < MAX (X1) DO A1 ← A1 + STEP
    
    WHILE X1 < ENDBUFF DO BEGIN
                             X7 ←  (X1)
                             IF X7 = END1SEQ THEN Go To OUT;
                             X1 ← X1 + CHAR 1
                             END
    
  3. A while statement causes the repeated execution of the statement following the while clause as long as the condition is met. A while clause consisting only of DO implies WHILE TRUE DO and can be used for a loop instead of an unconditional GOTO at the end. Conditions involving zero are most efficient.
  4. This can be considered as :-

    label: IF condition THEN BEGIN
                             statement
                             goto label
                             end
    

    with the IF condition omitted for a DO.

19. Blocks

  1. <declaration> ::= <K cell declaration>|<function declaration>|
                       <procedure declaration>|<K cell synonym declaration>|
                       <K accumulator synonym declaration>|<external declaration>|
                       <base declaration>|<global declaration>|
                       <lower declaration>|<define declaration>
    <simple statement> ::= <K accumulator assignment>|<K cell assignment>|
                           <function statement>|<procedure statement>|
                           <case statement>|<block>|<goto statement>|<data statement>|
                           <obey statement>|NULL|<label definition><simple statement>
    <statement> ::= <simple statement>|<if statement>|<include statement>|
                    <interpret statement>|<while statement>|<for statement>|
                    <label definition><statement>
    <label definition> ::= <label identifier> |GLABEL<label identifier> :|ENTRY <digit>:
    <block head> ::= BEGIN|<block head><declaration>;
    <data statement> ::= DATA <initial value>|DATA(<initial value list>)
    <block body> ::= <statement>|<block body>;<statement>|<block body>;<label definition>
    <block> ::= <block head><block body>END
    <program> ::= <statement>
    <compilable segment> ::= <program>|<procedure declaration>
    
  2. BEGIN REAL X ; INTEGER I; I ← 0; PROCA; DATA(3,5);
        L: X ← A1; I ← I+X2 AND X3; X4 ← X4+1
    ENTRY 3: IF X4=0 THEN GO TO L;IF X4 = 1 THEN GO TO OUT ;
             CASE X1 OF A1 ← Z;
                        A1 ← Z(1);
                        NULL
             CASEND;
    GLABEL OUT: END
    
  3. Blocks, labels and statements are similar to Algol. Identifiers can only be used within the. blocks in which they are declared. Semi-colons must be used to terminate statements although extra semi-colons will normally be ignored. NULL is a statement defining no action.Labels define instructions within a block or the end of a block. A GLABEL label is a label which can be referred to in sections of program compiled at different times. Glabels can be "goto"ed. or, if they occur in a procedure, can be called as a procedure. The effect of the latter is as if another similar procedure were declared with the glabel as name and with its first instruction a goto to the glabeled instruction.

    A data statement causes the initial values specified to be stores in successive words at that point. Note that the number of words stored per item is foun,d from the item type so that 0 is not the same as 0.0 and that the programmer must arrange not to obey data statements.

    An ENTRY label specifies an entry point for the program and the digit that follows indicates which entry.

  4. Most of this is dealt with elswhere. NULL generates a 123 order. Algol-like dummy statements generate nothing. Although the syntax is strict about semi-colons the compiler can afford to be generous. For example an extra semi-colon) after NULL or one missing after CASEND (which must end a statement) could be commented on but allowed. Since there is no comment after END facility a great many bogies are removed from that e.g.

                       END
              LABEL1 : END
    

    although having a semi-colon missing could be dealt with properly. The guiding light is: if you expect a terminator and none appears, or if two cell designators or accumulators occur without an operator, insert a semi-colon between the operators and comment. Data can use the initial value mechanism without a type check.

    An ENTRY label merely places the correct jump in one of the words 20-29 and a GLABEL is equivalent to the PLAN ## CUE. It should generate a satisfied cue and unlike PLAN, a local label as well. See also section 20 below. There is in general little distinction between labels and procedure names and each can be used interchangeably.

20. Procedure declarations

  1. <procedure heading> ::= PROCEDURE<procedure identifier>(<integer accumulator>);|
                            PROCEDURE<procedure identifier>(<integer accumulator>,
                                                  <unsigned integer number>);
    <procedure declaration> ::= <procedure heading><statement>|
                                GLABEL <procedure heading><statement>
    <external specification> ::= <instruction identifier>|
                                 <instruction identifier>(<integer accumulator>)
    <external declaration> ::= EXTERNAL <external specification>|
                               <external declaration>,<external specification>
    
  2. PROCEDURE SORT (X0);
       FOR X1 ← £A STEP 1 UNTIL ENDA DO
           BEGIN X6 ← A(X1);X3 ← X1;
             FOR X2 ← X1 + 1 STEP 1 UNTIL ENDA DO
             IF X6 ≤ A(X2) THEN BEGIN X6 ← A(X2); X3 ← X2 END;
             X2 ← A(X1); A(X1) ← X6; A(X3) ← X2;
           END
    PROCEDURE SUM (X1,2);
           BEGIN X2 ← (X1); X5 ← (X1+1);X7 ← 0;
           FOR X2  ← 1 STEP 1 UNTIL X5 DO X7 ← X7+(X2);
           RETURN;
           END;
    EXTERNAL FRED (X1), OUT, JOE (X5);
    
  3. A procedure declaration serves to define a sequence of instructions and to associate an identifier with them. This sequence can then be invoked by a procedure statement or a goto <procedure identifier>. For a procedure statement the accumulator specified in the procedure heading is used as a link and when the end of the sequence of instructions is encountered, a return will be made to the next instruction after the procedure statement, unless the unsigned integer is present. In this case the return is to (n+1)th instruction after the procedure statement where n is the unsigned integer and 0 ≤ n ≤ 63. RETURN is described in 25.

    Procedure declarations can appear in the declarations at the beginning of a block or can be a separately compiled section of program. In the first case communication can be via any variables declared in outer blocks or the accumulators. In the second case communication can only be via accumulators or GLOBALly declared variables. If the link accumulator is used in the procedure body for any other purpose it must be dumped and restored before the end of the procedure is encountered.

    If a separately compiled procedure, or a glabel in a separately compiled segment, is used in another segment the calling segment must contain an external declaration, which specifies the link accumulator to be used where necessary. If a goto only is to be made to a procedure it can be specified as a label and glabels within procedures can be specified as procedures if required. External labels and procedure names must be specified before use.

    In general a jump or call to an external procedure or glabel will cause entry to the overlay mechanism. This can be avoided if it is known that particular procedures or glabels will always be in permanent or always called from the same unit, by preceding the segment by a non-PLASYD directive. This takes one of the following forms:

       LOCAL:<label list>;
       LOCAL ALL;
       LOCAL ALL BUT:<label list>;
    where
    <label list> ::= <procedure identifier>|<glabel identifier>|
                      <label list>,<label list>
    

    This will inhibit the call of the overlay mechanism when this segment is entered from another for: the identifiers in the label list; all glabels and the segment name itself, or all labels and the segment name except those in the glabel list, respectively. When exit is made from a procedure the unit from which it was called must be in store. If the label list contains instruction identifiers referred to in the external declaration then CALLs and GOTOs to these identifiers will address the <procedure name> and not <procedure name>@

  4. For a locally compiled procedure only, the identifier can be treated as a label associated with the link accumulator. Goto statements then produce normal jumps and procedure statements call instructions. Glabels (and in fact all labels) within procedures should have the same link accumulator as the procedure associated with them.

    Separately compiled procedures and all glabels produce in addition a common area called <identifier>@ e.g. PROCEDURE JACK produces COMMON JACK@. This is a five word permanent common area containing the following information:

    STO   1   %AAX1            [This is a LOWER COMMON AREA]
    CALL  1   %EROL            [The overlay package]
              Area/unit no.    [Handled by s/c.]
    LDX   1   %AAX1            [cue for the procedure]
    BRN       JACK
    

    This ensures that the program segments can be mixed into (almost) any order of overlays. If no overlay calls are in fact made little extra code is executed but this can be eliminated and storage space saved by the LOCAL directive. This should be checked for before the BEGIN or PROCEDURE which starts a segment and the compiler must be capable of compiling either the sequence described above for glabels and segment names or no common area but a program cue<identifier>@ which is identical to the program cue for the identifier itself. In either mode of operation identifiers in a special list, or marked specially, must be treated in the other mode. No directive or a LOCAL; directive causes the first mode to be entered. LOCAL ALL; and LOCAL ALL BUT: involve the second mode and a label list if present is noted for exception treatment.

    Note that local procedures and labels or glabels must always be jumped to directly.

    All external procedures and glabels must be specified before use. This specification could cause a blank cue to be generated whether or not the specified quantity is later used.

21. Procedure statements

  1. <procedure statement> ::= <instruction identifier>
    
  2. SORT
    
  3. This involves the execution of the appropriate procedure body using the designated link. A label or glabel identifier could be used in place of a procedure identifier providing the link was correctly taken care of. A procedure can only be called in this way if it is

    1. already declared
    2. external and already specified
    3. declared within the current block or within an enclosed block.

    Procedures declared within parallel blocks cannot be called unless no return is expected since crossing block boundaries will cause the loss of corresponding storage.

  4. This produces a

        CALL <link>   <identifier>
    

    for a local procedure or a call to the associated common area <identifer>@ for external quantities. This latter will need revision for EBM (Mode 4 compilation).

    Undefined identifiers are assumed to be local and both the address and the link will need to be filled in when the label or procedure is encountered.

22. Include statements

  1. <include statement> ::= INCLUDE (<identifier>)|INCLUDE(<identifier>,SL)
    
  2. INCLUDE (DATASTATMNTS)
    
  3. Sections of PLASYD program which do not contain include statements may be stored by the PLASYD system and assigned an identifier. These sections can then be included in any segment that requires them by mentioning the identifier in an include statement. The facility is particularly useful for common data declarations and define declarations. The include statement should appear on a line by itself and the identifier must conform with 1900 subfile names.

  4. Action should be to switch off the listing and call in the operating system with the subfile identifier as a parameter. The subfile will then be accessed by the operating system and passed to the compiler as normal source. When the end of the subfile is reached the operating system should cause the listing to be switched on again. Alternatively, possibly at the user's request, listing of the included section should continue without increasing the line number, to aid editing. If SL is present the INCLUDE subfile is short listed.

23. RETURN

  1. <return statement> ::= RETURN | RETURN(<unsigned integer>)
    
  2. RETURN
    RETURN (3)
    
  3. The first form of RETURN causes the compiled program to exit from the procedure in which the RETURN statement appears and return to the (n+1)th statement after the procedure call. n is specified in the procedure heading (see 20), or is 0 if absent. In the second form of the statement the unsigned integer, m, overrides n and control is returnd to the (m+1)th instruction after the procedure statement. The link must if necessary be restored into the accumulator before the RETURN statement. Note that a RETURN is automatically compiled at the end of a procedure so that an explicit RETURN statement is only needed for exit from the body of the procedure or in order to override the n of the procedure heading.

  4. RETURN is compiled as EXIT X n where X is the link accumulator and n defined in the procedure heading. RETURN (m) is compiled as EXIT Xm.

24. Define

  1. <define declaration> ::= DEFINE<equation>|<define declaration>,<equation>
    <equation> ::= <definee> = <expression>
    <definee> ::= <identifier>
    <term> ::= <integer value>|<definee>
    <expression> ::= <absolute expression>|<term>|
                     <expression><D operator><term>
    <absolute expression> ::= $<upper K cell identifier>|
                              $<upper K cell identifier><fixed index>|
                              @<fixed K cell designator>-@<fixed K cell designator>|
                              £<K cell identifier>-£<K cell identifier>|
                              @<instruction identifier>-@<instruction identifier>
    <D operator> ::= + | - | * | /
    
  2. DEFINE I = 3,A=1
    DEFINE J = I + 5/2
    DEFINE K = @X - @ Y*I
    
  3. The expression is evaluated from left to right over twenty four bits and the resulting value is associated with the definee. All items in the expressions, including labels, must have been previously defined or declared. There is no need for the types of the cell identifiers of an absolute expression to agree but the two cells specified must either both be in the same common block or both in non-common lower storage or both in non-common upper storage. The difference between two addresses is a number of 1900 words. After a define statement the definee can be used wherever an integer value is allowed in the rest of the segment. If the value of the expression is positive it can be used where an unsigned integer is allowed. In particular it can be used as an assignment operand, an array length or an initial value, e.g.

    INTEGER A(I) = (K*I) ; 
    X1←J 
    
  4. The expression is evaluated strictly from left to right and whenever the definee is subsequently met it is replaced by the corresponding integer. The sign of the integer must be tested in cases where unsigned integers are required (e.g. array lengths). DEFINE x =$FRED is not allowed if FRED is declared in LOWER as the displacement of FRED is dependent on the address in lower and is not an absolute quantity when the DEFINEE is declared.

25. NON PLASYD

  1. <nonplasyd identifier> ::= <identifier>
    <nonplasyd specification> ::= <nonplasyd identifier> |
                                  <nonplasyd identifier> (<integer accumulator>)
    <nonplasyd declaration> ::= NONPLASYD <nonplasyd specification>|
                                <nonplasyd declaration>, <nonplasyd specification>                        
    <nonplasyd GOTO statement> ::= GOTO <nonplasyd identifier>|
                                   GOTO <nonplasyd identifier>(<unsigned integer number>)
    <nonplasyd procedure statement> ::= <nonplasyd identifier>|
                                         <nonplasyd identifier>(<unsigned integer number>)
    
  2. NONPLASYD JACK, JOHN (X0), JOE (X1)
    JACK; JOHN; JOE (3);
    GOTO JOE; GOTO JACK (6);
    
  3. Nonplasyd declarations serve to introduce separately compiled procedures or glabels in the same way as an external declaration (see 20), but also specify that these are not in a standard plasyd form (e.g. they may have been compiled in PLAN). Such procedures may have multiple entry points.

    If no integer follows the nonplasyd identifier in a goto or procedure statement the identifier will be branched to or called in the same way as an external procedure. If an integer, n, follows the identifier, however, the branch or call will be made to the nth word following that specified by the identifier.

  4. JACK (3); produces CALL <link><identifier+3>
    GO TO JACK (3); produces BRN <identifier+3>
    

26. MEMBER

  1. <priority> ::= <unsigned integer number>
    <member number> ::= <unsigned integer number>
    <member statement> ::= MEMBER (<member number>,<priority>)
    
  2. MEMBER(2,25)
    
  3. The member statement allows the user when compiling multimember programs to specify the member number and priority of individual members. The statement must appear before the head of a procedure similar to LOCAL. It need only appear once for each member although there may be more than one segment in a member.

27. BRINGOVERLAY

  1. <bringoverlay statement> ::= BRINGOVERLAY <instruction identifier>
    
  2. BRINGOVERLAY JACK
    
  3. The bringoverlay statement allows users to bring into core store an overlay without actually entering the overlay. Any instruction identifier in the required overlay can be specified, provided this identifier has been specified in an overlay list.

  4. The code produced is

    STO   1   %AAX1   [This is a LOWER COMMON area]
    CALL  1   %EROL   [The overlay package]
               Area/Unit no.[Handled by s/c]
    LDX   1   %AAX1
    

A1. --Removed--

A2. Input/Output

A3. Functional macros

A4. --Removed--

A5. Syntactic Definitions

A6. Definition Numbers

A7. PLASYD Syntax