CDC 6000 Pascal compilers

The CDC 6000 compiler was used as the basis for several other compilers on other machines. When a Pascal implementor needed a compiler, he/she could use either the P4 source as a basis, or the CDC 6000 compiler, or write it from scratch. The reason you might prefer to use the machine specific CDC 6000 compiler as a starting point is that (unlike the P4 compiler) it was a full implementation of Pascal, without any features left off. It also was a full optimizing compiler.

Read this report written by Niklaus Wirth, On “PASCAL” Code generation, and the CDC6000 Computer, Stanford University, 1972

On this page listings from 1972, 1974, 1976 of the Zürich compilers and the surviving (1986) CDC 6000 compiler at Minnesota University.

The 1972 Compiler

The following listing was provided by John Reagan, currently Master Compiler Engineer at VMS Software, formally of Digital Equipment (DEC), Compaq and HP.
Main compiler code in Pascal
The 1972 Compiler was the last version of the original, unrevised Pascal language before Pascal reached the form most folks know as Standard Pascal. It is different in many ways, for example, there was no program header, write/ln and read/ln were considered CDC extentions to the language, dynamic pointers were introduced by a statement, and other differences.
The language of the compiler is described in the 1970 document, see the Articles page.
The method used to create the first Pascal compiler, described by U. Ammann in The Zurich Implementation, was to write the compiler in a subset of unrevised Pascal itself, then hand-translate the code to SCALLOP, a CDC specific language. The compiler was then bootstrapped, or compiled using the Pascal source code and the SCALLOP based compiler, to get a working compiler that was written in Pascal itself. Then, the compiler was extended to accept the full unrevised Pascal language.

The 1974 compiler

The following listings were scanned from listings provided by Bob Felts: CDC 6000 Pascal 3.4 Update 10 compiler.
Main compiler code in Pascal
Cross-reference
Runtime library code in Compass, the CDC 6000 assembly language
The 1974 compiler was the first of the revised compilers. That is, it was rewritten in the “revised Pascal” language that was the Pascal language we recognize today. The “Pascal-P implementation notes” imply that the compiler was Pascal-P ported specifically to the CDC 6000 series computer, and indeed the 1974 CDC Pascal compiler appears to match P2 better than any of the other compilers. As the CDC compiler was modified, it resembled Pascal-P less and less, which is natural.

The 1976 Compiler

The following listings were scanned from listings provided by Mr. John Dykstra.
Main compiler code in Pascal
Runtime library code in Pascal
Runtime library code in Compass, the CDC 6000 assembly language
An error translation routine
The compiler listing is dated 1976. The scans were taken from a listing direct from a CDC 6000 series computer, and bear some unique features to such a listing. The name and line number appears at the right of the listing. Because the listings were wider than a 8 1/2 inch sheet of paper the line numbers to the right have one or more digits cut off. This compiler comes from the revised Pascal that forms the basis of the Pascal User Manual and Report, second edition. The compiler source is not written in standard Pascal, nor would it have been even if the compiler had been written at the time of the standard. It uses several of the CDC 6000 specific extentions, and it has the generation of CDC 6000 machine instructions imbedded in it. It is a one piece compiler, it takes in Pascal on one end, and issues CDC 6000 object code out of the other. The layout of the compiler is similar to the P4 project, which is not an accident. The P4 system was derived from this compiler. The compiler was written in, and compiled for, the revised Pascal language that most of us think of as Standard Pascal. The documents that describe this are described on the Articles page.
U. Ammann described the creation of the revised compiler in The Zürich Implementation, The 1970 compiler (above) was rewritten completely to arrive at the revised Pascal compiler. This was done both because the new Pascal language was different, and also because the experience of writing the old compiler had suggested better code structure for the new compiler. The new compiler was written in unrevised, or 1970 Pascal code. This resulted in a compiler that compiled using the old compiler, but accepted the revised language Pascal. Then, the compiler code itself was hand translated to the new language, and translated by the new compiler that was compiled by the old compiler. This resulted in the new compiler running on itself, and thus a full bootstrap. Of course, at this point you might well wonder what hand translation of the first version of the source on the new compiler from unrevised to revised Pascal might mean, which U. Ammann does not go into. Basically, it is just what you do if the unrevised and revised languages are not quite compatible. Otherwise, if the unrevised compiler was a subset of the revised language, you could just recompile it without changes. This is not nearly as much of a project as translation to SCALLOP, and used in the first compiler. It just means changing to accommodate the differences in the languages, which were substantially similar.

The 1984 Compiler

The CDC compiler continued to evolve past 1976. Most of the changes in what is contained here as the 1984 compiler were made at the University of Minnesota by Dave Bianchi and Jim Miner (who appears as a reviser of the forth edition Pascal User manual and Report). The material contained is marked copyright, but the University of Minnesota has graciously granted permission for it to appear. The University of Minnesota group extended the implementation in a few ways, for example it contains the otherwise statement on case statements. Otherwise, it appears to be a straightforward implementation of the original Zürich compiler, and it continued to be run on the CDC 6000 series computers. The University of Minnesota implementation is important for several reasons:

  • It contains the last known code revision of the CDC compiler.
  • It is well documented.
  • It is exists in machine readable and runnable form.
  • It obeys, with compiler options, the ISO Pascal Standard.

Modification history – History of changes to the source.
Pascal compiler – The main compiler code
Pascal Include Generator – Program to process includes and error information.
Pascal Library – Contains runtime support library routines in Pascal.
Pascal Error Messages – Contains error messages in various languages.
Pascal Runtime Support – Contains Pascal runtime support in Compass, the CDC 6000 assembly language.
Pascal System Support -Contains the run time system in Compass, the CDC 6000 assembly language.
Pascal System Texts – Contains constants and macros used in the compiler, in Compass.

Note that the listings were created by a card listing program (as in punched cards), and have type and sequencing information at the right hand side. This information can be easily removed by clipping everything from column 75 on. It was retained here for historical purposes.
Note also that all of the sources appear in upper case text. The CDC computer native character instruction set only had one case of character.

The documentation files for the compiler:
Pascal-6000 Installation Handbook – Details how to install the release tape.
Pascal-6000 Internal Reference Manual – Overview of program internals.
Pascal-6000 Library Information – Details of the local library.
PASPLOT – a Pascal Plotting Package – Details of an applications package.
SUMMARY OF CHANGES TO PASCAL-6000 – As it says.surveys changes from the last to this release
Pascal-6000 Release 4 Upgrade Guide
Prose Instruction Manual – Manual for Prose, a text formatter.
Pascal-6000 Writeup – The main users manual for the compiler.

Based upon a page and files supplied by by Scott A. Moore

P4 Compiler


Relevant articles about the portable Pascal Px compilers (see also the Articles page for Pascal Reports etc)

Book by Martin Daniels and Steven Pemberton Pascal implementation: The P4 Compiler, online version, local copy
A line by line description of the source.

ETH Pascal Programming Language Technical information:

Portable Compiler project New Edition H.H. Naegeli, 16.02.77
Portable Compiler project Pascal P4 Urs Ammann, Kesav Nori, Christian Jacoby May 76
Pascal P4 interpreter
Lists binary codes P-codes
Cross referencer
P4 Pascal Compiler P-Code listing
Procedural Cross Referencer

Downloads

Pascal P4 adapted to more standard Pascal
The files in this archive are:

  • int.p – P4 code interpreter
  • comp0.p – original compiler as distributed
  • comp1.p – same compiler with bugs fixed up to Pascal Newsletter #12
  • comp2.p – as above but with experimental changes to eliminate the last of the machine dependent code
  • comp.p – lower case, entabbed and stripped version of comp2.p some typos in comp?.p have been fixed
  • compvax.p – essentially the same as comp.p but with changes to allow it to compile under ‘pc’
  • compdiffs – differences between compvax.p and comp.p
  • compvax.errs – warning messages
  • compvax.map – line numbers of procedures and functions

Note that the characters for ^ and ‘ are ‘ and # in the compiler sources.

Pascal P4 adapted to ISO7185 Pascal by Scott Moore

Pascal P4 adapted to more standard Pascal, with examples

Pascal-S Concurrent Pascal-S

Pascal-S is a subset of Pascal, and was originally written by Niklaus Wirth.
Moti Ben-Ari has built on Pascal-S in his Principles of Concurrent Programming, resulting in Concurrent Pascal-S.

Compared to Wirth’s version of Pascal-S, case statement, records and reals are swiped from this edition of Pascal-S. M. Ben-Ari modified Wirth’s original compiler/interpreter in 1980 to include some basic features that were able to simulate concurrent programming.

First, a cobegin s1; …; sn coend block structure was added, allowing concurrent execution of the statements s1 … sn, which were required to be global procedure calls. These cobegin … coend blocks could not be nested within one another.

Second, the use of semaphores was introduced, with a semaphore data type (really synonymous with the integer data type) and the semaphore operations wait(s) and signal(s), corresponding to Dijkstra’s P(s) and V(s), respectively.

Downloads:

post

Pascal-S

Pascal-S is a subset of Pascal selected for introductory programming courses. The implementation is especially designed to provide comprehensive and transparant error diagnostics and economical service for small jobs.
The system consists of a compiler and an interpreter and is defined as a single, self-contained Pascal program.
Pascal-S is written in Pascal, and forms an excellent introduction to the art of designing small compilers.

Ben-Ari built on Pascal-S in the first version of his “Principles of concurrent programming” and introduced concurrency, see the Pascal-S Copascal page.

It is a interesting to see how many CDC-Pascal specialities are built into this compiler/interpreter.

  • Keywords are recognized by a binary search through a list of alfa’s (a standard datatype in CDC-Pascal) which are a 60-bit machine word packed with 10 6-bit characters. Since both DO and DOWNTO are keywords it is apparent from the ordering of the list that space comes after letters in the CDC character set <.li>
  • Some of the handling of large integers will only succeed on a CDC pascal implementation programs data gave the desired results
  • In Simpleexpression a 36 is emitted to negate both reals and integers, but the interpreter does this for both reals and integers s(.t.).i := – s(.t.).i;
    On the CDC this actually works for reals too

Corrections to the original (Jan van de Snepscheut):

  • line 295 (counting from 1 starting at program Pascal-S) is
    gen1(mulc, ttab[t].size); gen0(add)
    whereas the version printed in the book accidentally reads
    gen1(mulc, ttab[t].size)
    the corrected versions also implements boolean negation
  • the procedure funcdeclaration in the version printed in the book is
    erroneous. The first line on page 376 in the book should read
    if lev>1 then dx:=-1
    the last line of the procedure should read
    gen1(exit,itab[f].resultadr-dx); lev:=lev-1; dx:=odx

Wirth’s original paper is reprinted in Barrons book. Another version of Pascal-S appears in Snepscheut’s book and this uses symbolic names and contains a small peephole optimizer.
Publications where Pascal-S appeared in source format are:

  • PASCAL-S: A Subset and its Implementation, by Niklaus Wirth, Zurich : Eidgenossische Technische Hochschule, 1975. 61 s., Berichte des Instituts fur Informatik;
  • Pascal – The Language and its Implementation, by D. W. Barron, Chichester :
    John Wiley and Sons, 1980. 201 s. , ill., Wiley Series in Computing
  • Principles of Concurrent Programming, by M. Ben-Ari, Englewood Cliffs, N.J. :
    Prentice-Hall, Inc., 1982, 172 s. , ill.
  • What Computing is All About, by Jan L. A. van de Snepscheut



Downloads:


Some information on this page has been published by Scott Moore on the Standard Pascal pages and by Birger Nielsen (pages now lost).

Edison – a Multiprocessor Language

The Edison System, 1982, is comprised of both an operating system and programming environment. The system language, also named Edison, is simple yet powerful. The Edison language is comprised of only a few basic commands and structures. However, these basic fundamentals have been carefully chosen to establish the necessary foundation to produce powerful and extensive applications. The Edison System possesses adequate development facilities, yet is contained in a very small quantity of code. Per Brinch Hansen’s final development system for a PDP-11 contains approximately 10,000 lines of program text. This text includes the operating system, the compiler, the editor, the diskette formatting program, necessary assembly code, and other utility programs. This establishes a powerful yet small environment for the development of concurrent programs.

Software Practice and Experience, Volume 11 No 4. Devoted to the Edison papers, Per Brinch Hansen, see below.
Programming a Personal Computer, Per Brinch Hansen
The book describing thee Edison system, design, development, and listing of programs including compiler in the Edison language, and the interpreter/runtime written in PDP-11 Alva language.
The Design of Edison
(from Software Practice and Experience Vol 11, No 4), Per Brinch Hansen
The Development of Edison, Michael Wonderlich
The EDISON Multiprocessor Language and it’s port to OpenVMS
The Edison-ES programming language

Edison v1 compiler/interpreter

1987, R Kym Horsell
Compiler/interpreter for he Edison language, written in C.
Edisonv1 includes:
– a C preprocessor, cpp, which handles #include and #define commands inside Edison programs.
– an Edison compiler, edcomp, that translates Edison source code into a virtual (stack) machine code.
– an Edison interpreter, edrun, that loads and links machine code files.
– a runtime system stub.
– example programs culled from various textbooks on parallel and concurrent programming.
Local copy of the archive now lost on the internet

P de Wacht Edison compiler archive

Compiler for Edison in C and lex

Sources of Edison (compiler, operating system)


Software Practice and Experience, Volume 11 No 4, April 1981

A whole edition of this magazine devoted to the Edison system by Per Brinch Hansen, as sole author.

Available here complete! In parts, partially scanned like introduction and Edison Programs, partially as separate articles in PDF or HTMl format.


Design of Edison

The article on page 363 –

Edison Programs

Scan of page 397 – Edison programs

Language report: Edison – a Multiprocessor Language

The article Edison – a Multiprocessor Language on page 315 – in html format

by Per Brinch Hansen
Computer Science Department, University of Southern California,
Los Angeles, California 900007, USA


SUMMARY

This paper defines a programming language called Edison. The language
is suitable for teaching the principles of concurrent programming
and for designing reliable real-time programs for multiprocessor systems.
Edison is block structured and includes modules, concurrent statements,
and when statements.

KEY WORDS: Edison Programming language Multiprocessing Modules
Concurrent statements When statements


CONTENTS

  1. LANGUAGE OVERVIEW
  2. SYMBOLS AND SENTENCES
    1. Syntactic rules
    2. Characters
    3. Basic symbols
    4. Separators
    5. Character strings
  3. PROGRAMS AND EXECUTION
  4. NAMED ENTITIES
    1. Standard names
    2. Declarations
    3. Blocks, scopes, and contexts
    4. Modules
  5. VALUES, OPERATIONS, AND TYPES
    1. Type declarations
  6. CONSTANTS
    1. Constant declarations
  7. ELEMENTARY TYPES
    1. Type integer
    2. Arithmetic operators
    3. Type boolean
    4. Boolean operators
    5. Type character
    6. Enumeration types
    7. Elementary constructors
    8. Elementary relations
  8. RANGES
  9. RECORD TYPES
    1. Record constructors
    2. Record relations
  10. ARRAY TYPES
    1. Array constructors
    2. Array relations
  11. SET TYPES
    1. Set constructors
    2. Set relations
    3. Set operators
  12. CONSTRUCTORS
  13. VARIABLES
    1. Variable declarations
    2. Variable operands
    3. Field variables
    4. Indexed variables
    5. Retyped variables
  14. EXPRESSIONS
    1. Retyped factors
  15. STATEMENTS
    1. Skip statements
    2. Assignment statements
    3. Procedure calls
    4. If statements
    5. While statements
    6. When statements
    7. Concurrent statements
  16. PROCEDURES
    1. Complete procedures
    2. Parameters
    3. Functions
    4. Split procedures
    5. Library procedures
  17. PROGRAMS
  18. SYNTAX SUMMARY
  19. ACKNOWLEDGMENT
  20. INDEX

1. LANGUAGE OVERVIEW

This paper defines the programming language Edison. The language
is suitable both for teaching the principles of concurrent programming
and for designing reliable real-time programs for a multiprocessor
system.

The overriding concern in the design of Edison was to achieve
simplicity in the design of medium-sized programs of 1000-2000 lines
of text. This aim led to the selection of a small number of abstract
concepts for modular programming. In particular, the issues of
modularity, concurrency, and synchronization were
separated into distinct language features.

An Edison program describes operations on named entities called
constants, variables, and procedures. The constants and variables
have data values of fixed types. The types determine the possible
values of these entities and restrict the operations that can
be performed on them.

The data types integer, boolean, and character are standard types.
Other types are introduced by enumerating their values
or by describing how the values are composed from other values.
The composition methods for new types are the well-known arrays,
records, and sets. Every type has a name, and two operands are
of the same type only if their types are denoted by the same
name and have the same scope.

The computation of new data values from existing
values is described by expressions in which the operands
are constants, variables, and function calls, while the operators
are the conventional arithmetic, boolean, set, and relational
operators. The computation of composite values in terms of other values
is described by expression lists called constructors.

Statements describe operations such as the assignment of
values to variables and the execution of procedures. The if,
while and when statements describe a choice
among substatements to be executed depending on the truth values of
expressions. The concurrent statement denotes simultaneous
execution of several substatements as concurrent processes.
Process synchronization is controlled by when
statements. The execution of a when statement delays
a process until an expression is true and then performs
an operation on the common variables shared by the processes.
Concurrent processes can only execute when statements one
at a time.

The named entities and statements of a program are grouped into
blocks of two kinds, called procedures and modules. Blocks can
be combined to form other blocks in a nested fashion.

A procedure is a group of named entities and statements that
describe an operation on operands of fixed types. The operands
(known as parameters) may vary from one execution of
the procedure to another.
Each parameter is either a variable or another procedure.
The named entities introduced by a procedure are local
to the procedure and cannot be used outside it. Each execution
of the procedure creates a fresh instance of its parameters
and local variables. These entities disappear again
when the execution of the procedure terminates.

A module is a group of named entities that fall into
two categories: (1) local entities that can only be used within
the module, and (2) exported entities that can be used both
within the module and within the immediately-surrounding block.
The module entities exist as long as the entities of the
immediately-surrounding block. A module serves
to ensure that its local entities are only operated upon
by well-defined procedures which are exported from
the module to the immediately-surrounding block. To ensure
that the local variables are initialized before they are used,
a module includes a statement part that is executed when the module
entities are created.


2. SYMBOLS AND SENTENCES

The programming language Edison is a formal notation
in which programs can be written. The programs are texts
composed of symbol sequences known as sentences.

The language is described in terms of syntactic forms.
A syntactic form is a named class of symbols or sentences with
common properties. The definition of a syntactic form
consists of syntactic rules that define how sentences of the form
are composed and semantic rules that define the meaning of these sentences.

2.1. Syntactic rules

A syntactic rule described in a variant of the Backus-Naur notation
has the form

    S: E

where S stands for the name of the syntactic form while E stands for
a syntax expression that defines the corresponding class of sentences.
The name S consists of a capital letter possibly followed by small letters
and spaces.

Example of a syntactic rule:

    Parameter group:
      ['var'] Variable group # Procedure heading

A syntactic expression has the form

    T1 # T2 # ... # Tn

where T1, T2,…, Tn stand for terms that define classes of sentences.
A sentence of this form is composed by writing a sentence belonging to anyone of
the classes.

Example of a syntax expression:

    ['var'] Variable group # Procedure heading

A syntax term has the form

    F1 F2... Fn

where F1, F2,…, Fn stand for the syntax factors that define classes
of sentences. A sentence of the form is composed by writing a sentence of each
class in the order shown.

Example of a syntax term:

    ['var'] Variable group

A syntax factor has one of the four forms:

  1.     [E]*
    

    This form is an abbreviation for the syntax expression Empty # E # E E # E E E…
    where the name Empty denotes the empty sentence while E denotes a syntax
    expression. A sentence of this form is composed by writing either nothing
    or a finite sequence of sentences of the class E.

    Examples of a syntax factor:

        [Letter # Digit # '_']*
    

     

  2.     [E]
    

    This form is an abbreviation for the syntax expression Empty # E.
    A sentence of this form is composed by writing either nothing or
    a sentence of the class E.

    Example of a syntax factor:

        ['var']
    

     

  3.     N
    

    where N denotes the name of a syntactic form. A sentence of this
    form is composed according to the syntactic rule named N.

  4.  

    Example of a syntax factor:

        Variable group
    

     

  5.     'C1 C2... Cn'
    

    where C1, C2,…, Cn denote characters. A symbol of this form
    is composed of the characters written in the order shown. In particular,
    the syntax factors ‘#’, ‘:’, ‘[‘, ‘]’, ‘*’, and ”’ denote
    the characters #, :, [, ], *, and ‘ used as program symbols.

  6.  

    Example of a syntax factor:

        'var'
    
  7.  

2.2. Characters

    Character:
     Graphic character # New line character
    Graphic Character:
     Letter # Digit # Special character # Space
    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'
    Digit:
     '0' # '1' # '2' # '3' # '4' # '5' # '6' # '7' # '8' # '9'
    Special character:
     '"' # ''' # '(' # ')' # '*' # '+' # ',' # '-' # '.' #
     ':' # ';' # '&amp;lt;' # '=' # '&amp;gt;' # '[' # ']' # '_'

Characters are used to form basic symbols
(see Section 2.3).
A graphic character is represented by a graphic picture
or the deliberate omission thereof (a space). A new line
character marks the end of each line of text.

The character set may be extended with more letters and special
characters. In particular, the letters may be extended with capital
letters. The meaning of capital letters is explained in sections
2.3 and
4.


2.3. Basic symbols

    Basic symbol:
     Special symbol # Word symbol # Name # Numeral #
     Graphic symbol
    Special symbol:
     '+' # '-' # '*' # '=' # '&amp;lt;&amp;gt;' # '&amp;lt;' # '&amp;lt;=' # '&amp;gt;' # '&amp;gt;=' #
     ':=' # '(' # ')' # '[' # ']' # '.' # ',' # ':' # ';'
    Word symbol:
     'also' # 'and' # 'array' # 'begin' # 'cobegin' #
     'const' # 'div' # 'do' # 'else' # 'end' # 'enum' #
     'if' # 'in' # 'lib' # 'mod' # 'module' # 'not' #
     'or' # 'post' # 'pre' # 'proc' # 'record' # 'set' #
     'skip' # 'val' # 'var' # 'when' # 'while' #

The basic symbols are either special symbols, word symbols,
names
(see Section 4),
numerals
(see Section 7.1),
or graphic symbols
(see Section 7.5).

The special symbols and the word symbols have fixed meanings
which will be defined later.

Any capital letter used in a word symbol is considered equivalent
to the corresponding small letter. In this report the word
symbols are printed in boldface type.

2.4. Separators

    Separator:
     Space # New line character # '"' Comment '"'
    Comment:
     [Character]*

The character ” cannot occur within a comment.

Any basic symbol preceded by one or more separators stands
for the basic symbol itself. Two adjacent word symbols or names must be
separated by at least one separator.

Example:

    "This is a comment"

2.5. Character strings

    Character list:
     ''' Graphic character '''
      [',' ''' Graphic character ''']*
    Character string:
     ''' Graphic character [Graphic character]* '''

A character list denotes a sequence of graphic characters.
Character lists are used in constructors
(see Section 12).

A character string is an abbreviation for a character list that
contains the same sequence of graphic characters.

Example of character lists:

    '.'
    'E', 'd', 'i', 's', 'o', 'n'

Examples of character strings:

    '.'
    'Edison'

3. PROGRAMS AND EXECUTION

A program is a description of one or more related data processes,
each process taking place in a number of separate steps. In each step
a well-defined action (an operation) is performed on a set
of entities (the operands).

The act of following a program text and performing the operations
described by it is called the execution of a program (and its operations).
A person or device that executes a program (or part of it) is called
a processor.

The operands of a program generally denote data values that
either remain fixed (constants) or change during the execution (variables).

The operations are generally rules for deriving new data values (results)
from previous data values given by operands. Operations may also use data
values to determine the order in which subsequent operations are to
be executed.

The execution of an operation will have one of three outcomes:

  1. Termination: after a finite time the processor completes the operation.
  2. Failure: after a finite time the processor detects that the operation
    is meaningless and cannot continue the execution of the program.

 

  • Cycling: the processor executes the same cycle of operations
    endlessly.The execution of certain operations may be influenced by properties
    that are not fully described in this report since they vary from
    processor to processor. Such properties are said to be system dependent.

    A program may prescribe a sequence of operations to be carried out
    strictly one at a time. Such a sequence is known as a process.
    A program may also allow several processes to take place simultaneously.
    They are know as concurrent processes.


    4. NAMED ENTITIES

        Name:
         Letter [Letter # Digit # '_']*
    

    Any capital letter used in a name is considered equivalent to
    the corresponding small letter. The word symbols cannot be used
    as names. Apart from that names may be chosen freely.

    A name denotes an entity used in a program. The entity is
    either a constant
    (see Section 6),
    a data type
    (see Section 5),
    a record field
    (see Section 9),
    a variable
    (see Section 13),
    or a procedure
    (see Section 16).

    Examples:

        char
        s
        table
        matrix1
        rc4000a
        end_of_file
    

    4.1. Standard names

        Standard name:
         'bool' # 'char' # 'false' # 'int' # 'true'
    

    The standard names denote the standard types bool, char, int,
    and the truth values false, true
    (see Section 7).
    These names can be used throughout a program without being declared.

    4.2. Declarations

        Declaration:
         Constant declaration list # Type declaration #
         Variable declaration list # Procedure declaration #
         Module declaration
    

    A declaration introduces names to denote program entities
    and describes some of their properties. The entities are either
    constants
    (see Section 6.1),
    types
    (see Section 5.1),
    variables
    (see Section 13.1),
    procedures
    (see Section 16),
    or modules
    (see Section 4.4).

    The use of a name within a program to denote an entity must be
    preceded by a declaration which introduces the name and describes
    the entity it stands for (unless the name is a standard name).
    A declaration of an entity is generally valid within
    one block only
    (see Section 4.3).
    Outside this block the same name
    can be declared and used with other meanings.

    4.3. Blocks, scopes, and contexts

    A block is a piece of program text consisting of (1) declarations
    of named entities, and (2) statements which define operations on
    these entities. The only possible kinds of
    blocks are procedures
    (see Section 16),
    modules
    (see Section 4.4),
    and programs
    (see Section 17).

    Generally a block Q can be a part of another block P in which case
    P is said to contain Q. The block Q is then called an inner block
    of P, while P is called a surrounding block of Q. In general
    a program will consist of a hierarchy of nested blocks.

    The innermost block in which a declaration of a named entity appears
    is called the origin of that declaration.

    The scope of a named entity x is that part of the program text in
    which the name x may be used to denote the entity. A named entity
    is said to be known within its scope.

    The scope generally extends from the declaration of the entity to
    the end of its origin, with the following additional rules:

    1. If the origin is a module M then the scope may be extended to
      the end of the immediately-surrounding block B. The entity is
      then said to be exported from M to B
      (see Section 4.4).
  • If the same name is declared with another meaning in an inner
    block of the origin then the scope does not include the inner block.A given name can only be declared with one meaning in the same block.
    And a name cannot be exported to a surrounding block in which the same
    name is declared with another meaning.

    The meaning of a name used at some point in a block is determined
    by the following rules:

    1. Local entity: if the use of the name is preceded by a declaration
      in the same block of an entity of that name then the use of the name
      denotes the entity.

 

 

  • Exported entity: if the use of the name is preceded by a module
    in the same block from which a declared entity of that name is exported
    to the block then the use of the name denotes the entity.

 

 

  • Global entity: if neither of the above apply then the name has the
    same meaning it has in the immediately-surrounding block at the point
    where the given block begins.When several processes are executed concurrently or when
    a single process calls one or more procedures recursively,
    several instances of a named entity may exist simultaneously.
    At any given moment, however, a process can only operate
    on a single instance of every entity that is know to the process
    at the moment.

    When a process executes a statement it operates on known
    entities selected from a set of entities the current context
    of the process. The context consists of (1) an instance of every
    entity declared in the procedures surrounding the statement,
    and (2) an instance of every entity declared in the modules
    contained in these procedures.

    When a process refers to a known entity an instance of that entity
    is located in the current context of the process in accordance
    with the scope rules.

    Throughout this report the phrase ‘the current context’
    refers to the current context of the process that performs a given
    operation.

    The dynamic changes of contexts are further explained in Sections
    4.4,
    15.3,
    15.7
    and
    17.

    4.4. Modules

    A module is a block that introduces two kinds of named entities
    known as local and exported entities. The module also describes
    an initial operation on these entities.

    The local entities can only be used within the module. The exported
    entities can be used both within the module and within the block
    that immediately surrounds the module.

    A module is either contained in a procedure or in another module.
    When a procedure body is executed an operation known as module
    initialisation is performed on all modules declared within the
    procedure body.

    The initialisation of a module M take place in three steps:

    1. The local and exported entities declared in M are created
      and added to the current context.

 

 

  • The modules declared in M are initialised one at a time in the
    order written.

 

  • The initial operation of M is performed.When the execution of the procedure terminates the entities
    of the module (and those of its inner modules) disappear again.

        Module declaration:
         'module' [Local declaration # Exported declaration]*
           Statement part
        Local declaration:
         Declaration
        Exported declaration:
         '*' Declaration
        Statement part:
         'begin' Statement list 'end'
    

    A module declaration describes a module by means of declarations
    of local and exported entities and by a statement part which
    describes the initial operation by means of a statement list
    (see Section 15).

    An export symbol * in front of a module declaration has no effect.
    Exported entities are discussed further in Sections
    6.1,
    7.6,
    9,
    10,
    11,
    13.1
    and
    16.

    Example:

        module
          const max = 10
          array stack[1 : max] (int)
          var lifo : stack; size : int
        
          *proc push(x : int)
          begin size := size+1; lifo[size] := x end
        
          *proc pop(var x : int)
          begin x := lifo[size]; size := size - 1 end
        
          *proc empty : bool
          begin val empty := (size = 0) end
        
        begin size := 0 end
    

    5. VALUES, OPERATIONS, AND TYPES

    Data are physical phenomena chosen by convention to
    represent facts or ideas. The same fact or idea can be represented
    by a variety of different data. The common notion of data representing
    the same fact or idea will be called a value.

    Data values are grouped into classes called types. A type is
    a named set of values. Each value is of one and only one type.

    The operands that yield data values during execution are constants
    (see Section 6),
    variables
    (see Section 13),
    and expressions
    (see Section 14).

    Any value yielded by an operand during execution will be of one and
    only one type. The operand type can be determined from the program
    text without executing it.

    Standard operations on values are denoted by symbols called operators.
    New operations are described in terms of previously defined operations
    by means of procedures
    (see Section 16).

    Every operation applies to operands of fixed types and delivers
    results of fixed types.

    The types integers, boolean, and character are standard types — types
    that are available without being declared. All other types must be introduced
    by means of type declarations.

    5.1. Type declarations

        Type declaration:
         Enumeration type declaration # Record type declaration #
         Array type declaration # Set type declaration
    

    A type declaration describes a new type which is either an enumeration
    type
    (see Section 7.6),
    record type
    (see Section 9),
    array type
    (see Section 10),
    or set type
    (see Section 11).


    6. CONSTANTS

    A constant is a fixed value of a fixed type.

        Constant symbol:
         Numeral # Truth symbol # Character symbol #
         Enumeration symbol # Constant symbol
    

    A constant symbol denotes a constant and is either a numeral
    (see Section 7.1),
    a truth symbol
    (see Section 7.3),
    an enumeration symbol
    (see Section 7.6),
    or a constant synonym
    (see Section 6.1).

    6.1. Constant declarations

        Constant declaration list:
         'const' Constant declaration
          [';' Constant declaration]*
        Constant declaration:
         Constant synonym '=' Constant symbol
        Constant symbol:
         Name
    

    Every constant declaration introduces a name, called a constant synonym,
    to denote a constant. A constant declaration cannot be of the form
    x = x where x is the synonym.

    The scope rules
    (see Section 4.3)
    apply to declared constants. A constant
    c declared in a module is exported to the immediately-surrounding
    block by exporting the constant declaration list that introduces c
    (see Section 4.4).

    Example:

        const namelength = 12; on = true; last = '.';
         nl = char(10); lf = nl
    

    7. ELEMENTARY TYPES

    An elementary type consists of a finite set of successive
    values, called elementary values.

    The values of any elementary type can be mapped onto a finite set
    of successive integer values (and vice versa). The integer value
    that corresponds to an elementary value x is called
    the ordinal value of x and is denoted int(x).

    The elementary types comprise the standard types integer,
    boolean, and character as well as the enumeration types introduced
    by type declarations.

    7.1. Type integer

    The standard type integer is an elementary type denoted
    by the standard name int. The integer values are a finite
    set of successive whole numbers including both positive and negative
    values. The range of integers is system-dependent. For any
    integer value x we have int(x) = x.

        Numeral:
         Digit [Digit]*
    

    A numeral is a conventional decimal notation for a non-negative
    integer value. Negative integer values must be denoted by
    expressions
    (see Section 14).

    Examples:

        0
        1351
    

    7.2. Arithmetic operands

    The arithmetic operators apply to operands of type
    integer and yield a result of type integer. When applied
    to two operands of type integer the operators +, -,
    *, div, mod denote addition, subtraction,
    multiplication, division, and modulo, respectively.
    The results of
    x div y
    and
    x mod y
    are the truncated quotient of x divided by y
    and the remainder of x div y. They satisfy
    the relation
    x = (x div y) * y + x mod y.

    When applied to a single operand of type integer + and –
    are conventional sign operators.

    An arithmetic operation terminates if the result is within
    the range of integers; otherwise, it fails.

    7.3. Type boolean

    The standard type boolean is an elementary type denoted by
    the standard name bool.

        Truth symbol:
         'false' # 'true'
    

    The truth symbols are standard names that denote the boolean
    values. The boolean values have the ordinal values int(false) = 0
    and int(true) = 1.

    7.4. Boolean operators

    The boolean operators not, and, or
    denote negation, disjunction, and conjunction, respectively.
    They apply to one or two operands of type boolean and yield
    a result of type boolean according to the following rules:

        not false = true          not true = false
        x and false = false       x and true = x
        x or false = x            x or true = true
    

    where x denotes an arbitrary boolean value. A boolean
    operation always terminates.

    7.5. Type character

    The standard type character is an elementary type denoted by the
    standard name char. The set of characters and their
    ordinal values are system dependent
    (see Section 2.2).

        Character symbol:
         Graphic symbol # Control symbol
        Graphic symbol:
         ''' Graphic character '''
        Control symbol:
         'char' '(' Numeral ')'
    

    A character symbol denotes a value of type character. A graphic
    symbol 'c' denotes the graphic character c.
    A control symbol char(n) denotes the character with the
    ordinal value n.

    Examples:

        'a'
        '0'
        ';'
        char(10)
    

    7.6. Enumeration types

        Enumeration type declaration:
         'enum' Type name '(' Enumeration symbol list ')'
        Enumeration symbol list:
         Enumeration symbol [',' Enumeration symbol]*
        Type name:
         Name
        Enumeration symbol:
         Name
    

    An enumeration type declaration introduces a name, called a type name,
    to denote an elementary type and introduces a list of names, called
    enumeration symbols, to denote the successive values of the type.

    The values of an enumeration type enum T(c0,c1,…,cn)
    have the ordinal values
    int(c0) = 0,
    int(c1) = 1, …,
    int(cn) = n.

    The scope rules
    (see Section 4.3)
    apply to an enumeration type and its values. An enumeration type declared
    in a module can be exported together with its values to the
    immediately-surrounding block
    (see Section 4.4).

    Example:

         enum task(flow, scan, log)
         enum filekind(empty, scratch, ascii, code)
    

    7.7. Elementary constructors

        Elementary constructor:
         Type name '(' Expression ')'
    

    An elementary constructor denotes a mapping of the values
    of one elementary type onto the values of a (usually different)
    elementary type. The type name must denote an
    elementary type and the expression must be of an elementary type.

    The elementary constructor int(x) denotes the ordinal
    value of an elementary value x of type T.
    If y is the ordinal value of x,
    that is int(x) = y, then T(y) = x.
    For a value y of any elementary type we have T(y) =
    T(int(y))
    .

    Examples:

        int(slot)
        bool(1 - x)
        char(x + int('0'))
        task(x)
    

    7.8. Elementary relations

    The relational operators =, <>, <, <=, >, >=
    denote the relations equal, not equal, less, not greater,
    greater, and not less. These operators apply to two operands
    of the same elementary type and yield a result of type boolean.

    These operators have their conventional meaning for operands
    of type integer: they yield the value true if the operand values
    satisfy the relations, and the value false
    if they do not. If x and y are values
    of another elementary type then x = y has
    the same value as int(x) = int(y), and similarly
    for the other relations.

    These operations always terminate.


    8. RANGES

    A range is a finite set of successive elementary values of the same
    type from a lower bound x to an upper bound y both included (where x <= y).
    The type of the values is know as the range type.

        Range symbol:
         Lower bound ':' Upper bound
        Lower bound:
         Constant symbol
        Upper bound:
         Constant symbol
    

    A range symbol denotes a range. The bounds are denoted by constant
    symbols which must be of the same elementary type (the range type).

    Ranges are used to define the possible index values of array types
    (see Section 10).

    Examples:

        1 : namelength
        false : true
        'a' : 'b'
        flow : log
    

    9. RECORD TYPES

    A record type consists of a finite set of values, called
    record values. Each record value consists of a finite sequence of
    other values known as fields. Each field is of some known
    type. The set of record values consists of all the possible
    sequences of the possible field values.

        Record type declaration:
         'record' Type name '(' Field list ')'
        Field list:
         Field group [';' Field group]*
        Field group:
         Field name [',' Field name]* ':' Field type
        Field name:
         Name
        Field type:
         Type name
    

    A record type declaration introduces a type name to denote a record
    type. The field list introduces names, called field names, to denote
    the fields. A group of fields have the known type given by another type
    name, called the field type.

    A record type declaration cannot use its own type name as a field type.
    The scope rules
    (see Section 4.3)
    apply to a record type and its fields.
    A record type declared within a module can be exported to the
    immediately-surrounding block
    (see Section 4.4),
    but the corresponding field names
    remain local to the module and cannot be exported from it.

    Examples:

          record semaphore(count : int)
          record time(hour, minute, second : int)
          record attributes(kind : filekind; address : int; protected : bool)
          record entry(id : name; attr : attributes)
    

    9.1. Record constructors

        Record constructor:
         Type name '(' Expression list ')'
        Expression list:
         Expression [',' Expression]*
    

    A record constructor denotes a record value of the type given by
    the type name. The expression list must contain one expression for each
    field of the record type. The order in which the expressions are listed
    in the record constructor and the order in which the field names are listed
    in the record type declaration define a one-to-one correspondence
    between the expressions and the fields. The expressions must be of the same
    types as the corresponding fields.

    The result of executing a record constructor is a record value in
    which the fields are the values obtained by evaluating the corresponding
    expressions in the order written. The execution terminates if the
    evaluation of the expressions terminates.

    Examples:

        semaphore(0)
        time(x, y+5, 0)
        attributes(code, x, true)
        entry(name('edit'), attributes(code, x, true))
    

    9.2. Record relations

    The relational operators = and <> apply to operands of the same record
    type and yield a result of type boolean. Two record values x and y
    of the same type are equal (denoted x = y) if all the corresponding
    fields of the values are equal. The relation x <> y has the same
    value as not (x = y).

    These operations always terminate.


    10. ARRAY TYPES

    An array type consists of a finite set of values, called
    array values. Each array value consists of a finite sequence of other
    values known as elements. The elements are of the same known type. The set
    of array values consists of all the possible sequences of the possible
    element values.

    The elements are distinguished by their position in the array value.
    The positions are denoted by the successive values in a range known as
    the index range. The position of an element is called its index value.

    An array type with n elements of type character is called a
    string of length n.

        Array type declaration:
         'array' Type name '[' Index range ']'
          '(' Element type ')'
        Index range:
         Range symbol
        Element type:
         Type name
    

    An array type declaration introduces a name to denote an
    array type. The index range is given by a range symbol
    (see Section 8).
    The known type of the elements is given by another type name, called
    the element type.

    An array type declaration cannot use its own type name as the
    element type. The scope rules
    (see Section 4.3)
    apply to an array type. An array type declared within a module can be exported
    to the immediately-surrounding block
    (see Section 4.4).

    Examples:

        array name [1 : namelength] (char)
        array poll [false : true] (int)
        array timetable ['a' : 'b'] (time)
        array namelist [flow : log] (name)
    

    10.1. Array constructors

        Array constructor:
         Type name '(' Expression list ')'
    

    An array constructor denotes an array value of the type given by
    the type name. The expression list
    (see Section 9.1)
    must contain one
    expression for each element of the array value (unless the array type
    is a string type). The order in which the expressions are listed
    in the array constructor and the order in which the array elements
    are arranged by the index values define a one to one correspondence
    between the expressions and the elements. The expressions must be of the
    element type given by the array type declaration.

    An array constructor for a string type of length n
    must contain m expressions of type character (where
    1 <= m <= n). This is an abbreviation for an array value consisting
    of the character values given by the m expressions followed
    by n - m spaces.

    The result of executing an array constructor is an array value in
    which the elements are the values obtained by evaluating the corresponding
    expressions in the order written. The execution terminates if the evaluation
    of the expressions terminates.

    Examples:

        name('do',nl,c)
        poll(x+1, y)
        timetable(time(12,30,0), time(x,y+5,0))
        namelist(name('flow'), name('scan'), name('log))
    

    10.2. Array relations

    The relational operators = and <> apply to operands of the same array
    type and yield a result of type boolean. Two array values x and y of the
    same type are equal (denoted x = y) if all the corresponding
    elements of the values are equal. The relation x <> y has
    the same value as not (x = y).

    These operations always terminate.


    11. SET TYPES

    A set type consists of a finite set of values, called set values.
    Each set value consists of a finite (possibly empty) set
    of other values. These other values are known as
    the members of the set value. The members are of the same known
    elementary type, called the base type.

    A member must have an ordinal number in the range 0 : setlimit
    where the upper bound is a system-dependent integer called the set
    limit
    (see Sections 7, 8).

    The range of possible members is called the base range of the set type.
    The set of set values consists of all the possible subsets (including
    the empty one) that can be formed from the values in the base range.

        Set type declaration:
         'set' Type name '(' Base type ')'
        Base type:
         Type name
    

    A set type declaration introduces a type name to denote a set type.
    The known base type is given by another type name and must be
    elementary.

    The scope rules
    (see Section 4.3)
    apply to a set type. A set type
    declared within a module can be exported to the immediately-surrounding
    block
    (see Section 4.4).

    Examples:

        set intset(int)
        set boolset(bool)
        set charset(char)
        set taskset(task)
    

    11.1. Set constructors

        Set constructor:
         Type name ['(' Expression list ')']
    

    A set constructor denotes a set value of the type given by the type name.
    The expression list (if any) consists of one or more expressions
    of the base type given by the set type declaration
    (see Section 9.1).

    The result of executing a set constructor is a set value in which
    the members are the values obtained by evaluating the expressions in
    the order written. The evaluation fails if any of the expression
    values are outside the base range.

    A set constructor without an expression list denotes the
    empty set, which has no members.

    Examples:

        intset
        boolset(x = y)
        charset('0123456789')
        taskset(scan, log)
    

    11.2. Set relations

    The relational operation in applies to operands v and x
    where x denotes a set value of type T while v denotes an elementary
    value of the base type. The relation v in x is
    true if the value v is a member of the set x. The evaluation
    of the relation fails if the value of v is outside the base range.
    The empty set T has no members, that is (v in T) = false
    for all values v in the base range.

    The relational operators = and <> apply to operands x and y
    of the same set type. The relation x = y is true if (v in x)
    = (v in y) for all values v in the base range. The relation
    x <> y has the same values as not (x = y). These operations
    always terminate.

    11.3. Set operators

    The set operators +, -, * denote union, difference, and intersection,
    respectively. These apply to operands x and y of the same set type
    and yield a result of that type.

    For any value v in the base range of the set type:

        v in (x+y)    means   (v in x) or (v in y)
        v in (x-y)    means   (v in x) and not (v in y)
        v in (x*y)    means   (v in x) and (v in y)
    

    The operations always terminate.


    12. CONSTRUCTORS

        Constructor:
         Elementary constructor # Record constructor #
         Array constructor # Set constructor
    

    A constructor denotes a mapping of one or more values of fixed
    types onto a value of a (usually different) type. It is either
    an elementary constructor
    (see Section 7.7),
    a record constructor
    (see Section 9.1),
    an array constructor
    (see Section 10.1),
    or a set constructor
    (see Section 11.1).


    13. VARIABLES

    A variable is a named entity that may assume any of the values of
    a known type. The value of a variable may be used in expressions
    (see Section 14)
    to compute other values and may be changed by means of
    assignments
    (see Section 15.2).

    A variable of a record or array type consists of a group of other
    variables known as subvariables. A variable of an elementary type or a set
    type has no subvariables. A variable that is not a subvariable
    of any other variable is called a whole variable.

    13.1. Variable declarations

        Variable declaration list:
         'var' Variable group [';' Variable group]*
        Variable group:
         Variable name [',' Variable name]* ':' Type name
        Variable name:
         Name
    

    Every variable group in a variable declaration list introduces
    one or more names, called variable names, to denote whole variables of the known
    type given by the type name.

    Other whole variables known as parameters and function variables are
    introduced by procedures
    (see Section 16).

    The scope rules
    (see Section 4.3)
    apply to every whole variable.
    A whole variable v declared in a module is exported to the
    immediately-surrounding block by exporting the variable
    declaration list that introduces v
    (see Section 4.4).

    Example:

        var x, y, size : int; full, free : bool; c, slot : char;
         job : task; s : semaphore; file : entry;
         answers : poll; schedule : timetable; tasks : namelist;
         months : intset; digits : charset;
    

    13.2. Variable operands

        Variable symbol:
         Whole variable symbol # Subvariable symbol #
         Retyped variable symbol
        Whole variable symbol:
         Variable name # Function variable symbol
        Subvariable symbol:
         Field variable symbol # Indexed variable symbol
    

    A variable symbol denotes a whole variable, a subvariable, or
    a retyped variable
    (see Section 13.5)
    used as an operand.

    A whole variable is denoted by a known variable name or by
    a function variable symbol
    (see Section 16.3).

    A subvariable is denoted by a field variable symbol
    (see Section 13.3)
    or an indexed variable symbol
    (see Section 13.4).

    The evaluation of a variable symbol involves locating the corresponding
    variable in the current context. This is called variable selection.
    The selection of a whole variable always terminates. The selection
    of a subvariable is described later.

    If a variable symbol occurs within an expression
    (see Section 14)
    the corresponding variable is first selected and then a copy
    of its value is obtained. This is called variable retrieval.
    The retrieval terminates if the selection does.

    Examples of whole variable symbols:

        x
        s
        file
        answers
        schedule
        tasks
        val empty
    

    13.3. Field variables

    A variable of a record type is called a record variable. It
    contains a subvariable for each field of the record value. The
    subvariables are known as field variables. Their types are the
    corresponding field types given by the record type declaration.

        Field variable symbol:
         Record variable symbol '.' Field name
        Record variable symbol:
         Variable symbol
    

    A field variable symbol v.f consists of a record variable symbol
    v followed by a field name f.

    A field variable is selected in two steps:

    1. The record variable is selected.
    2. The field value given by the field name is selected within
      the record variable.

    The selection of the field variable terminates if the selected
    of the record variable does.

    If v denotes a record variable of type T then the relation

    v = T(v.f1, v.f2, …, v.fm)

    is true, where v.f1, v.f2, …, v.fm denotes the values of the field
    variables of v.

    Examples:

        s.count
        schedule[c].second
        file.attr.kind
    

    13.4. Indexed variables

    A variable of an array type is called an array variable. It contains
    a subvariable for each element of the array value. The subvariables
    are known as indexed variables. Their type is the element type
    given in the array type declaration.

        Indexed variable symbol:
         Array variable symbol '[' Index expression ']'
        Array variable symbol:
         Variable symbol
        Index expression:
         Expression
    

    An indexed variable symbol v[e] consists of an array variable symbol
    v followed by an index expression e.
    The index expression is an expression of the
    same type as the index range given in the array type declaration.

    An indexed variable is selected in three steps:

    1. The array variable is selected.

     

  • The index expression is evaluated to obtain an index value.
  •  

     

  • The indexed variable corresponding to the index value is
    selected within the array variable.The selection of an indexed variable terminates if the selection
    of the array variable terminates and if the evaluation of the index
    expression yields an index value within the index range. The
    selection fails if the index value is outside the index range.

    If v denotes an array variable of type T then the relation

    v = T(v[e1], v[e2], …, v[em])

    is true where v[e1], v[e2], …, v[em] denote the values
    of the indexed variables of v.

    Examples:

        answers[false]
        schedule[c]
        tasks[job][x+1]
        file.id[12]
    

    13.5. Retyped variables

    In most computers data values are held as binary numerals known as
    stored values. The following describes a system depended operation
    that only applies to computers in which stored values of the same
    type occupy the same amount of storage.

    If the stored values of two types occupy the same amount of
    storage the types are said to be of the same length.

    An operation known as retyping maps the values of one type
    onto another type of the same length in such a way that the
    corresponding values of the two types have the same stored values.

    If x denotes a variable of type T1 then x : T2 denotes the
    same variable considered to be of another type T2 of the
    same length. The variable x : T2 is called a retyped variable.

    A selection of possible subvariables of x : T2 proceeds as if
    x was of type T2.

    A retrieval of x : T2 yields a value of type T2 with the same
    stored value as the value of x.

    An assignment
    (see Section 15.2)
    to x : T2 of a value y of type
    T2 assigns a value to x with the same stored value as the value of y.

        Retyped variable symbol:
         Variable symbol ':' Type name
    

    A retyped variable is denoted by a variable symbol followed by a known
    type name.

    Example:
    schedule

    : attributes


    14. EXPRESSIONS

        Expression:
         Simple expression
          [Relational operator Simple expression]
        Relational operator:
         '=' # '&amp;lt;&amp;gt;' # '&amp;lt;' # '&amp;lt;=' # '&amp;gt;' # '&amp;gt;=' # 'in'
        Simple expression:
         [Sign operator] Term #
         Simple expression Adding operator Term
        Sign operator:
         '+' # '-'
        Adding operator:
         '+' # '-' # 'or'
        Term:
         [Term Multiplying operator] Factor
        Multiplying operator:
         '*' # 'div' # 'mod' # 'and'
        Factor:
         Simple operand # '(' Expression ')' #
         'not' Factor # Retyped factor
        Simple operand:
         Constant symbol # Constructor #
         Variable symbol # Procedure call
    

    An expression denotes a rule for computing a value of a fixed
    type known as the expression type. An expression consists of operands
    denoting values and operators denoting operations on the values. Parentheses
    may be used to prescribe the order in which the operators are to be applied
    to the operands. The execution of an expression is known as its evaluation.

    An operator denotes a standard operation on the values of one or two
    operands. The same operator may stand for several different operations depending
    on the operand types. The execution of an operator yields a single
    value as described in Sections
    7.2,
    7.4,
    7.8,
    9.2,
    10.2,
    11.2
    and
    11.3.

    Each operator restricts the operands to which it may be applied
    to belong to certain types only. The syntactic rules for expressions, which
    describe no restrictions arising from types, include many forms that are
    invalid.

    The value of an expression is found either as the value of
    a simple expression or by applying a relational operator
    to the values of two simple expressions.

    The value of a simple expression is found either as the value of a term,
    or by applying a sign operator to the value of a term, or by applying
    an adding operator to the values of another simple expression and a term.

    The value of a term is found either as the value of a factor,
    or by applying a multiplying operator to the values of another term and a
    factor.

    The value of a factor is found either as the value of a simple operand,
    or another expression, or by applying a not operator to the value of
    another factor, or by evaluating a retyped factor
    (see Section 14.1).

    The value of a simple operand is found either as the value of a constant
    (see Section 6),
    a constructor
    (see Section 12),
    a variable
    (see Section 13.2),
    or a procedure call
    (see Section 15.3).

    Examples of simple operands:

        false
        attributes(code, x, true)
        schedule[c].second
        gcd(189, 215)
    

    Examples of factors:

        ... all the examples above ...
        (1 &amp;lt;= x)
        not full
        s : int
    

    Examples of terms:

        ... all the examples above ...
        5 * x div y
        (1 &amp;lt;= x) and (x &amp;lt;= namelength)
    

    Examples of simple expressions:

        ... all the examples above ...
        -10
        x + y - 1
    

    Examples of expressions:

        ... all the examples above ...
        1 &amp;lt;= x
        c in digits
    

    14.1. Retyped expressions

    If x denotes a value of type T1 then x : T2 denotes a value of type T2
    with the same stored value as the value of x. The types T1 and T2
    must be of the same length
    (see Section 13.5).
    The operand x : T2 is called a retyped factor. Its value is system dependent.

        Retyped factor:
         Factor ':' Type name
    

    A retyped factor consists of a factor followed by a known type name.

    Example:

        s : int
    

    15. STATEMENTS

        Statement:
         Skip statement # Assignment statement #
         Procedure call # If statement #
         While statement # When statement #
         Concurrent statement
        Statement list:
         Statement [';' Statement]*
    

    A statement denotes one or more operations and determines (at least
    partially) the order in which these operations are to be executed.
    A statement is either a skip statement
    (see Section 15.1),
    an assignment statement
    (see Section 15.2),
    a procedure call
    (see Section 15.3),
    an if statement
    (see Section 15.4),
    a while statement
    (see Section 15.5),
    a when statement
    (see Section 15.6),
    or a concurrent statement
    (see Section 15.7).

    A statement list denotes execution of a sequence of statements.

    The statements of a statement list are executed one at a time
    in the order written.

    Examples of statement lists:

        full := false
        send(x); read(x)
    

    15.1. Skip statements

        Skip statement:
         'skip'
    

    The word symbol skip denotes the empty operation. The
    execution of a skip has no effect and always terminates.

    15.2. Assignment statements

        Assignment statement:
         Variable symbol ':=' Expression
    

    An assignment statement denotes assignment of a value given by
    an expression to a variable. The variable and the expression must be
    of the same type.

    An assignment statement is executed in three steps:

    1. The variable is selected.

     

  • The expression is evaluated to obtain a value.
  •  

     

  • The value is assigned to the variable.An assignment to a subvariable of a whole variable assigns
    a value to the subvariable without changing the values of the remaining
    subvariables.

    If v denotes a record variable of the type

          record T (f1 : T1; f2 : T2; ...; fm : Tm)
    

    then

           v.f1 := e1    means    v := T(e1, v.f2, ..., v.fm)
           v.f2 := e2    means    v := T(v.f1, e2, ..., v.fm)
    			  ...
           v.fm := em    means    v := T(v.f1, v.f2, ..., em)
    

    where f1, f2, …, fm are the field names of the record type T
    while e1, e2, …, em are expressions of the field type T1, T2, …, Tm.

    Similarly, if v denotes an array of the type

          array T [i1 : im] (Te)
    

    then

          v[i1] := e1    means    v := T(e1, v[i2], ..., v[im])
          v[i2] := e2    means    v := T(v[i1], e2, ..., v[im])
    			      ...
          v[im] := em    means    v := T(v[i1], v[i2], ..., em)
    

    where i1, i2, …, im are the index values of the array type T while
    e1, e2, …, em are expressions of the element type Te.

    Examples:

        x := x + 1
        c := char(x + int('0'))
        full := false
        job := log
        val empty := (size = 0)
        file := entry(name('edit'), attributes(code, x, true))
        s.count := s.count + 1
        schedule[c] := time(12, 30, 0)
    

    15.3. Procedure calls

        Procedure call:
         Procedure name ['(' Argument list ')']
        Argument list:
         Argument [',' Argument]*
        Argument:
         Value argument # Variable argument # Procedure argument
        Value argument:
         Expression
        Variable argument:
         Variable symbol
        Procedure argument:
         Procedure name
    

    A procedure call denotes execution of a known procedure given by
    the procedure name
    (see Section 16).

    The argument list denotes operands that may be operated upon by the
    procedure. The argument list must contain one argument for each parameter
    of the procedure. The order in which the arguments are written in the
    procedure call and the order in which the parameters are listed in the procedure
    declaration define a one to one correspondence between the arguments
    and the parameters.

    Each argument is either a value argument, a variable argument, or
    a procedure argument.

    A value argument must correspond to a value parameter and must be
    an expression of the same type as the corresponding parameter.

    A variable argument must correspond to a variable parameter and must be
    a variable symbol of the same type as the corresponding parameter.

    A procedure argument must correspond to a procedure parameter
    and must be the name of a procedure with the same heading as the
    corresponding parameter (apart from the choice of procedure and
    parameter names).

    The execution of a procedure call takes place in six steps:

    1. The parameters of the procedure called are created one at
      a time in the order listed:

    A value parameter is created as a fresh variable which is
    assigned the value obtained by evaluating the corresponding value argument.

    A variable parameter is created by selecting the corresponding
    variable argument.

    A procedure parameter is created by selecting the corresponding
    procedure argument and selecting a context associated with the
    argument (as described below).

  • A new current context is formed from a context associated
    with the procedure called extended with the parameters.
  •  

    The procedure body is then executed as described in steps (3)-(5):

     

  • The auxiliary entries declared in the procedure body are created
    and added to the current context. The initial values of the auxiliary
    variables are undefined.
  •  

     

  • The local modules of the procedure are initialised one at a time
    in the order written. This extends the current context further as
    described in Section 4.4. The current context is then also
    attached as an attribute to all procedures declared in the
    body (and to all procedures declared in the local modules
    of the body).
  •  

     

  • The statement part of the procedure body is executed.
  •  

     

  • The old context, used prior to the call is re-established
    as the current context.During the execution of the procedure body every operation
    on a variable parameter stands for the same operation performed on
    the corresponding variable argument,
    and every call of a procedure parameter stands
    for the same call of the corresponding procedure argument in the context
    associated with the argument. These parameters are said to be bound
    to the corresponding arguments during the execution of the
    procedure body.

    When a procedure call is used as a statement it must refer to a
    general procedure
    (see Section 16.1).

    When a procedure call is used as an operand in an expression
    it must refer to a function
    (see Section 16.3).
    The execution of a function computes a value of a fixed type given by
    the procedure declaration.

    Examples:

        init
        receive(x)
        gcd(189, 215)
    

    15.4. If statements

        If statement:
         'if' Conditional statement list 'end'
        Conditional statement list:
         Conditional statement ['else' Conditional statement]*
        Conditional statement:
         Boolean expression 'do' Statement list
        Boolean expression:
         Expression
    

    An if statement denotes a single execution of a conditional
    statement list.

    A conditional statement list denotes execution of one
    of several conditional statements (or none of them). Each conditional
    statement consists of an expression of type boolean and a statement list.

    The execution of an if statement consists of executing the conditional
    statement list once.

    The execution of a conditional statement list consists of first
    evaluating the boolean expressions one at a time in the order written
    until one yielding the value true is found or until all have
    been found the yield the value false. If the value obtained
    from an expression is true then the statement list that follows
    the expression is executed; otherwise, none of the statement
    lists are executed. In the latter case, the statement lists are
    said to be skipped.

    Examples:

        if x mod y &amp;lt;&amp;gt; 0 do send(x) end
    
        if job = flow do flow_analysis
        else job = scan do alarm_scanning
        else job = log do data_logging
        else true do error end
    

    15.5. While statements

        While statement:
         'while' Conditional statement list 'end'
    

    A while statement denotes one or more executions of a
    conditional statement list
    (see Section 15.4).

    The execution of a while statement consists of executing the conditional
    statement list repeatedly until all the statement lists are skipped.

    If statement lists continue to be executed forever then the execution cycles.

    Examples:

        while x &amp;lt;&amp;gt; last do send(x); read(x) end
    
        while x &amp;gt; y do x := x - y
        else x &amp;lt; y do y := y - x end
    

    15.6. When statements

        When statement:
          'when' Synchronized statement 'end'
        Synchronized statement:
         Conditional statement list
    

    A when statement consists of a conditional statement list
    known as a synchronized statement. This is a mechanism which can be
    used to give concurrent processes exclusive access to
    common variables when their values satisfy certain conditions.

    A process executes a when statement in two phases:

    1. Synchronization phase: the process is delayed until no other process
      is executing the critical phase of a when statement.

     

  • Critical phase: the synchronized statement is executed as
    described in Section
    15.4.
    If the statement lists are skipped
    the process returns to the synchronizing phase;
    otherwise the execution of the when statement is terminated.Each synchronizing phase of a process lasts a finite time only
    provided that the critical phase of all other concurrent processes
    terminate.

    Concurrent processes are further discussed in Section
    15.7.

    Examples:

        when true do s.count := s.count + 1 end
    
        when s.count &amp;gt; 0 do s.count := s.count - 1 end
    
        when free do x := 1; free := false
        else x &amp;gt; 0 do x := x + 1 end
    

    15.7. Concurrent statements

        Concurrent statement:
         'cobegin' Process statement list 'end'
        Process statement list:
         Process statement ['also' Process statement]*
        Process statement:
         Process constant 'do' Statement list
        Process constant:
         Constant symbol
    

    A concurrent statement denotes execution of a process statement list.
    The process statement list consists of process statements to be
    executed simultaneously. Each process statement describes a process by
    means of a constant symbol (the process constant) and a statement
    list. The type and meaning of process constants are system dependent.
    They may, for example, be used to specify the amount of storage
    required by a process or the processor that must perform the process.

    The execution of a concurrent statement consists of executing the
    process statements simultaneously. The relative ordering of operations
    performed by different processes is unspecified. The execution of such
    operations may generally overlap in time (unless they are described by
    when statements). The execution of a concurrent statement terminates
    when all the concurrent processes terminate.

    When a process reaches a concurrent statement the current context
    of that process becomes the initial context of each of the concurrent
    processes.

    The variable instances in the initial context of the processes are called
    common variables because they can be operated upon by all the
    processes. The common variables enable processes to exchange
    values during their execution.

    When a process calls one or more procedures its its initial
    context is extended with variable instances that are inaccessible
    to the other processes. They are called the private variables of the
    process.

    Two common variables are said to be disjoint if they are different
    variable instances or if none of them is a subvariable of the other;
    otherwise, they are called intersecting variables.

    If each of several concurrent processes only operates on
    private variables and disjoint, common variables then the effect
    of executing a concurrent statement is the same as the effect
    of executing the process statements one at a time in any order.

    But, if concurrent processes operate on intersecting, common
    variables then the effect of executing a concurrent statement is generally
    unpredictable since nothing is known about the order in which the processes
    operate on these variables. However, by restricting the operations on
    intersecting, common variables to well-defined disciplines
    under the control of modules
    (see Section 4.4),
    procedures
    (see Section 16),
    and when statements
    (see Section 15.6)
    it is possible to formulate concurrent statements that make predictable
    use of such variables. The theories used to reason about concurrent
    statements, when statements, and common variables are beyond
    the scope of this report.

    When concurrent processes terminate, the execution of
    all procedures called by these processes has also ended. Consequently,
    the private variables of the processes have disappeared leaving
    only the common variables in the context. The execution of the
    program now continues as a single process in the current context
    of common variables.

    The meaning of variable retrieval
    (see Section 13.2)
    and assignment
    (see Section 15.2)
    defined earlier is valid only if these operations
    are performed one at a time on a given variable. Concurrent processes
    can ensure that this assumption is satisfied by performing all
    operations on intersecting, common variables within when statements.
    The assumption is always satisfied for operations on private variables
    since each of these variables can be used only by a single process
    which performs all its operations (including those on variables) one
    at a time.

    If any of the concurrent processes reaches a concurrent
    statement the execution fails.

    Examples:

        cobegin 1 do print end
    
        cobegin 1 do producer
        also 2 do consumer end
    
        cobegin 1 do node(b[0], b[1])
        also 2 do node(b[1], b[2])
        also 3 do node(b[2], b[0])
        also 4 do send(b[0], 9999) end
    

    16. PROCEDURES

        Procedure declaration:
         Complete procedure declaration # Split procedure part #
          Library procedure declaration
    

    A procedure declaration describes a named procedure. It is either
    a complete procedure
    (see Section 16.1),
    a split procedure
    (see Section 16.4),
    or a library procedure
    (see Section 16.5).

    A procedure declared in a module can be exported to the
    immediately-surrounding block
    (see Section 4.4).

    16.1. Complete procedures

        Complete procedure declaration:
         Procedure heading Procedure body
        Procedure heading:
         'proc' Procedure name ['(' Parameter list ')']
           [':' Function type]
        Procedure name:
         Name
        Function type:
         Type name
        Procedure body:
         [Declaration]* Statement part
    

    A complete procedure declaration defines a procedure completely.
    The procedure heading introduces a name, called a procedure name, to denote
    the procedure and describes the parameters by a parameter list
    (see Section 16.2).
    If the heading includes a known type name, called the function
    type, the the procedure is a function
    (see Section 16.3);
    otherwise, it is a general procedure.

    The procedure body consists of declarations
    (see Section 4.2)
    which describe auxiliary entities used by the procedure and a statement
    part
    (see Section 4.4)
    which describes a sequence of operations on the
    parameters and auxiliary entities.

    A procedure acts as a block
    (see Section 4.3).
    The parameters and
    auxiliary entities are local to the procedure and can only be used
    within the procedure body. The procedure name is local to the
    immediately-surrounding block.

    The execution of the procedure body is invoked by executing a procedure
    call
    (see Section 15.3).

    A procedure may call itself recursively.

    Examples:

        proc init begin full := false end
    
        proc consumer
        var y : char
        begin receive(y);
          while y &amp;lt;&amp;gt; last do
            write(y); receive(y)
          end;
          write(y); write(nl)
        end
    
        proc wait(var s : semaphore)
        begin when s.count &amp;gt; 0 do s.count := s.count - 1 end end
    
        proc push(c : int)
        begin size := size + 1; lifo[size] := c end
    
        proc gcd(x, y: int): int
        begin
          while x &amp;gt; y do x := x - y
          else x &amp;lt; y do y := y - x end;
          val gcd := x
        end
    

    16.2. Parameters

        Parameter list:
         Parameter group [';' Parameter group]*
        Parameter group:
         Value parameter group # Variable parameter group #
         Procedure parameter
        Value parameter group:
         Variable group
        Variable parameter group:
         'var' Variable group
        Procedure parameter:
         Procedure heading
    

    A parameter list describes one or more group of parameters.

    A value parameter group introduces a group of local variables
    known as value parameters. Each value parameter is assigned the
    value of an argument before the procedure body is executed.

    A variable parameter group introduces a group of local variables known
    as variable parameters. Each variable parameter denotes a variable
    argument which is selected before the procedure body is executed.

    A procedure parameter introduces a procedure heading to denote
    a procedure argument and its associated context which are selected before
    the procedure body is executed.

    Examples:

        x, y : int
        var s : semaphore
        id : name; proc lookup(x : name; var y : attributes)
    

    16.3. Functions

    A function is a procedure that describes the computation of a single
    value of a fixed type (the function type). A function call can be used as
    an operand in an expression. The procedure body of a function assigns the value
    of the function to a local variable, called the function variable. The last
    value assigned to this variable during the execution of the procedure
    body becomes the value of the procedure call that invoked
    the execution.

        Function variable symbol:
          'val' Procedure name
    

    A function variable is denoted by the procedure name of the given
    function. The function variable is only known in the body of the function.

    Examples of a function variable symbol:

        val gcd
    

    16.4. Split procedures

    In a procedure that contains mutually recursive procedures some procedure
    calls must precede the corresponding procedure bodies in the program text.
    A procedure that is called in this way must have its declaration split into
    two parts: a predeclaration that precedes these calls and a postdeclaration
    that follows them.

        Split procedure part:
         Procedure predeclaration # Procedure postdeclaration
        Procedure predeclaration:
         'pre' Procedure heading
        Procedure postdeclaration:
         'post' Complete procedure declaration
    

    A procedure predeclaration is a procedure heading that describes how
    to call a split procedure. The procedure name introduced by the procedure
    heading can be used in the program text that extends from the predeclaration
    to the end of the block in which the predeclaration appears.

    A procedure postdeclaration is a complete procedure declaration that
    describes how to call and execute a split procedure. The pre- and post declarations
    must appear in the same block in that order but may be separated by other
    declarations in the same block. The procedure headings of the pre- and
    post declarations must be identical.

    A split procedure declared in a module is exported to the
    immediately-surrounding block
    (see Section 4.4)
    by exporting the corresponding predeclaration.

    Example:

        pre proc variable_symbol(succ : symbols)
        ... other declarations ...
        post proc variable_symbol(succ : symbols)
        begin ... end
    

    16.5. Library procedures

    A program library is a group of procedures that can be called
    by a program without being included in the program. The library
    procedures, which have the form of separate programs
    (see Section 17),
    cannot use global variables or global procedures
    (see Section 4.3).

    A program may call a library procedure if the program contains a declaration
    of the procedure heading and a description of where the procedure body
    is located in the library.

        Library procedure declaration:
         'lib' Procedure heading '[' Library key ']'
        Library key:
         Expression
    

    A library procedure declaration describes a library procedure by
    means of a procedure heading and a library key. The library key
    is an expression that indicates the location of
    the procedure body in the library. The type of the expression is system
    dependent.

    When the library procedure is called the library key is
    evaluated and used to locate the procedure body in the library.
    The execution of the body then proceeds as described earlier
    (see Section 15.3).

    The procedure heading used in the program and the procedure heading used
    in the library to describe the procedure must be the same.

    Example:

        lib proc edit(source, dest : name) [name('edit')]
    

    17. PROGRAMS

        Program:
         [Constant declaration list # Type declaration]*
          Complete procedure declaration
    

    A program consists of a declaration of constants, types, and a single,
    complete procedure
    (see Sections 6.1,
    5.1,
    and
    16.1).

    A program acts as a block
    (see Section 4.3).
    The declared entities
    can be used throughout the program.

    The execution of the program consists of executing a call
    of the procedure in a system dependent context. Initially, the program
    is executed as a single process in the given context.

    Example:

          "This program defines two processes connected by a buffer module.
          A producer process reads a sequence of characters terminated by
          a period and sends them through the buffer to a consumer process
          that receives the characters and writes them. The procedures for
          reading and writing characters are system dependent parameters
          of the program."
        
        const last = '.'; nl = char(10)
        
        proc copier(proc read(var c : char); proc write(c : char))
        
          module
            var slot : char; full : bool
        
          * proc send(c : char)
            begin when not full do slot := c; full := true end end
        
          * proc receive(var c : char)
            begin when full do c := slot; full := false end end
        
          begin full := false end
        
          proc producer
          var x : char
          begin read(x);
            while x &amp;lt;&amp;gt; last do
              send(x); read(x)
            end;
            send(x)
          end
        
          proc consumer
          var y : char
          begin receive(y);
            while y &amp;lt;&amp;gt; last do
              write(y); receive(y)
            end;
            write(y); write(nl)
          end
        
        begin
          cobegin 1 do producer
          also 2 do consumer end
        end
    

    18. SYNTAX SUMMARY

    The following is a list of the syntactic forms of the language.
    Trivial syntactic forms have been omitted. Some forms have been
    eliminated by replacing all references to their names with the
    corresponding syntax expressions. Other forms that were defined
    recursively earlier have been replaced by equivalent ones that are
    defined iteratively. Separators and character strings, which are
    alternative representations of other syntactic forms, are defined
    elsewhere
    (see Sections 2.4
    and
    2.5).

    Name:

     

    Letter [Letter # Digit # ‘_’]*

    Numeral: 

     

    Digit [Digit]*

    Character symbol: 

     

    ”’ Graphic character ”’ # ‘char’ ‘(‘ Numeral ‘)’

    Constant symbol: 

     

    Constant name # Numeral # Character symbol

    Constant declaration: 

     

    Constant name ‘=’ Constant symbol

    Constant declaration list: 

     

    ‘const’ Constant declaration
    [‘;’ Constant declaration]*

    Enumeration symbol list: 

     

    Constant name [‘,’ Constant name]*

    Enumeration type declaration: 

     

    ‘enum’ Type name ‘(‘ Enumeration symbol list ‘)’

    Field group: 

     

    Field name [‘,’ Field name]* ‘:’ Type name

    Field list: 

    Field group [‘;’ Field group]*

    Record type declaration:

  •  

     

    ‘record’ Type name ‘(‘ Field list ‘)’

    Range symbol: 

    Constant symbol ‘:’ Constant symbol

    Array type declaration:

  •  

     

    ‘array’ Type name ‘[‘ Range symbol ‘]’ ‘(‘ Type name ‘)’

    Set type declaration: 

    ‘set’ Type name ‘(‘ Type name ‘)’

    Type declaration:

  •  

     

    Enumeration type declaration # Record type declaration #
    Array type declaration # Set type declaration

    Variable group: 

     

    Variable name [‘,’ Variable name]* ‘:’ Type name

    Variable declaration list: 

     

    ‘var’ Variable group [‘;’ Variable group]*

    Parameter group: 

     

    [‘var’] Variable group # Procedure heading

    Parameter list: 

     

    Parameter group [‘;’ Parameter group]*

    Procedure heading: 

     

    ‘proc’ Procedure name [‘(‘ Parameter list ‘)’]
    [‘:’ Type name]

    Complete procedure declaration: 

     

    Procedure heading [Declaration]* Statement part

    Procedure declaration: 

     

    ‘pre’ Procedure heading #
    [‘post’] Complete procedure declaration #
    ‘lib’ Procedure heading ‘[‘ Expression ‘]’

    Module declaration: 

     

    ‘module’ [Declaration # Exported declaration]*
    Statement part

    Declaration: 

     

    Constant declaration list # Type declaration #
    Variable declaration list # Procedure declaration #
    Module declaration

    Exported declaration: 

     

    ‘*’ Declaration

    Variable symbol: 

     

    Variable name # ‘val’ Procedure name #
    Variable symbol ‘.’ Field name #
    Variable symbol ‘[‘ Expression ‘]’ #
    Variable symbol ‘:’ Type name

    Expression list: 

     

    Expression [‘,’ Expression]*

    Constructor: 

     

    Type name [‘(‘ Expression list ‘)’]

    Factor: 

     

    Constant symbol # Constructor # Variable symbol #
    Procedure call # ‘(‘ Expression ‘)’ #
    ‘not’ Factor # Factor ‘:’ Type name

    Multiplying operator: 

     

    ‘*’ # ‘div’ # ‘mod’ # ‘and’

    Term: 

     

    Factor [Multiplying operator Factor]*

    Adding operator: 

     

    ‘+’ # ‘-‘ # ‘or’

    Simple expression: 

     

    [‘+’ # ‘-‘] Term [Adding operator Term]*

    Relational operator: 

    ‘=’ # ‘<>’ # ‘<‘ # ‘<=’ # ‘>’ # ‘>=’ # ‘in’

    Expression:Simple expression
    [Relational operator Simple expression]

    Argument:Expression # Variable symbol # Procedure name

    Argument list:Argument [‘,’ Argument]*

    Procedure call:Procedure name [‘(‘ Argument list ‘)’]

    Conditional statement:Expression ‘do’ Statement list

    Conditional statement list:Conditional statement [‘else’ Conditional statement]*

    Process statement:Constant symbol ‘do’ Statement list

    Process statement list:Process statement [‘also’ Process statement]*

    Statement:’skip’ # Variable symbol ‘:=’ Expression #
    Procedure call #
    ‘if’ Conditional statement list ‘end’ #
    ‘while’ Conditional statement list ‘end’ #
    ‘when’ Conditional statement list ‘end’ #
    ‘cobegin’ Process statement list ‘end’

    Statement list:Statement [‘;’ Statement]*

    Statement part:’begin’ Statement list ‘end’

    Program:[Constant declaration list # Type declaration]*
    Complete procedure declaration

    ACKNOWLEDGMENT

    The programming language Edison was developed for a multiprocessor system built by Mostek Corporation. This language report was first
    written in January 1979 and was then revised in July 1979, January 1980, and September 1980. In writing (and rewriting) this report I have benefitted greatly from the constructive criticism of Peter Naur. I have also received helpful suggestions from Jon Fellows, David Gries, and Habib Maghami.


PDP-10 Pascal compiler

Archive with the DECUS DEC-System-10 Pascal compiler, including sources.

This compiler is a descendent of the Zürich Pascal compilers.

      
      
                            Mitteilung 40
      
                        On DECSystem-10 Pascal
      
                              H.-H. Nagel
     
      
                            IFI-HH-M-40/76
      
      
                    Auf der DECUS-Konferenz am 9.9.76
      
                    in Munchen gehaltern Vortrag
      
                            On DECSystem-10 PASCAL

                                  H.-H. Nagel
                            Institute fuer Informatik
                              Universitaet Hamburg
                              Schlueterstrasse 70
                               D-2000 Hamburg 13
      
      
      These notes attempt to give some information about the pro-
      gramming language PASCAL and its implementation for the DEC-
      System-10 with the intent to induce the reader to make himself
      acquainted with the literature quoted and possibly to explore
      the applicability of PASCAL for his own programming tasks.
      
      The programming language PASCAL has been defined by Wirth /1,2/
      and implemented several times in his group /3,4,5/.  It is
      strongly recommended to read "PASCAL - User Manual and Report"
      /6/ since it contains an introduction to the language and the
      definition of Standard PASCAL together with the options im-
      plemented for the CDC 6000 series computers.  Our DECSystem-10
      implementation of PASCAL strives to contain Standard PASCAL as a 
      subset and as many of the CDC 6000 PASCAL options as possible.
      
      These short notes will not be able to convey a flavor of this
      language - for that the reader is referred to the literature
      quoted.  It may suffice to indicate the intentions behind the
      design of PASCAL by relating it to two other programming lan-
      guages which - as PASCAL - consider ALGOL 60 as their root.
      
      - SIMULA /7/ is a superset of ALGOL-60 which has been developped
        originally to provide extensions for the simulation of multiple
        process systems.  The CLASS concept has been introduced with
        SIMULA.  This concept has later proven to be a very powerful
        and fruitful addition to the field of programming languages.

        Moreover, SIMULA broadens the scope of applicability by
        introducing e.g. the character type as a basic ingredient.
        Whereas SIMULA retained ALGOL-60 as a subset and the ensue-
        ing restrictions.

      - PASCAL has been designed without accepting the preceding
        ALGOL-60 as a subset thus gaining the freedom to explore
        new grounds.  The overriding design principle has been to
        strike a balance between the language capabilities and the
        resulting implementation efforts as well as the requirements
        for the runtime support.  Therefore, PASCAL emphasizes the
        practical aspects of going beyond ALGOL-60, in contrast to

      - ALGOL 68 /8/ which emphasizes the theoretical aspects of 
        exploring the design possibilities for programming languages
        beyond ALGOL-60.


      Any attempt to strike a balance is likely to leave somebody unsatisfied.  
      It is not surprising, therefore, that the publication of PASCAL has resulted 
      in a protracted discussion of its advantages and shortcomings /9-14, 
      to quote but a few/.  This can be taken as a very healthy sign of life 
      - PASCAL is one of the very few languages which have fought their way to 
      general acceptance and wide use without the backing of a manufacture. 
      This claim is supported by the following list of computer systems for 
      which a PASCAL implementation is available

      - Burroughs B5700 and B6700
      - CDC 6000 and CDC 3600 and CDC 7600
      - CII 10070
      - HITAC 8700/8800
      - IBM 360 and IBM 370
      - ICL 1900
      - DECSystem-10 (and DECSystem-20)
      - PDP-11
      - Philips P1400
      - Systems Engineering Laboratories SEL 8600
      - TI 980 A
      - Telefunken TR 440
      - UNIVAC 1100 under EXEC 8 and 1108
      - Xerox Sigma 7
      - Dietz MINCAL 621

      Further information about PASCAL activities can be obtained
      by writing to

             PASCAL User's Group
             c/o Andy Mickel
             University Computer Center
             227 Experimental Engineering Building
             University of Minnesota
             Minneapolis/Minnesota 55455
             USA

      PASCAL has not only been accepted as a practical programming language.  
      It has - in addition - exerted a profound influence upon the design of 
      programming languages.  To give a few examples for this claim:

      - Systems Implementation Languages /e.g. 15, 16/
      - Data Base Language Extensions /e.g. 17, 18/
      - Research into Program Proving /e.g. 19, 20, 21/
          amoungst other things based upon the axiomatic definition
          of PASCAL /22/
      - Language Portability /e.g. 23, 24, 25/
      - Programming languages to facilitate the formulation of par-
          allel processes:  CONCURRENT PASCAL /26/


      Having indicated some of the more general implications of PASCAL 
      I would like to concentrate the remaining remarks on the PASCAL 
      implementation for the DECSystem-10 and the application of this 
      implementation.

      The historical development of our implementation is given in
      the following diagram

        1972        }
                }
                 }        Bootstrap attempt with CDC-6400 PASCAL compiler
                  }           (simulating a CDC-6400 on a PDP-10:
                 }                         90 minutes for compilation)
                }
                }
                }
        1973         }
                  }        Bootstrap of PASCAL-compiler for
                 }           hypothetical stack machine by simulating
                }           this stack machine on the PDP-10:  10 minutes
                }
                }
        1974         }        Upgrading the compiler into a competitive
                  }           tool for small program development
                 }
                }        Development of a version which generates
                }        relocatable object code compatible with
                }         LINK-10 and an interactive source level debugging
                }          option
                } 
                }
        1975        }
                 }        Fully implement STANDARD PASCAL
                  }
                 }
                }
        1976        }
                 }        Adapt to DECSystem-10 Concise Command Language
                  }        Add large range of options (including most of
                 }        the PASCAL-6000. ones) to provice a
                }        comfortable programming environment for
                }        large systems.


      The first two steps up until November 1973 have been described in /24/.  
      The following upgrading step and the related experiences are documented in /27/.  
      The work done since autumn 1974 has been described in /28-32/.

      Today, the DECSystem-10 PASCAL is used at our institute for
      a wide variety of teaching and research purposes as indicated
      by the following examples:


      - Introductory programming courses for students in Informatik
          since autumn 1973
      - Transfer of the Montreal Portable Compiler Writing System
          /33, 34/
      - Natural Language Understanding
      - Embedding of Relational Data Base Systems /18/
      - Dialogue Language Research /35/
      - Scene Analysis /36, 37/

      A version of our PASCAL compiler distributed in July 1975 has found 
      widespread use as exemplified by a tabulation of installations:

          Other Users of our PDP-10 PASCAL-system
          _______________________________________

                           Universities              Industry         Total
                           &amp; Colleges
        Europe                        11                 4                 15
        USA + Canada                22                15                 37
        South America                 2                                  2
        Australia                 1                                  1
                           __________________________________________
                                36                19                 55

                      e.g. Brandeis         e.g. BBN
                           Caltech              E.I. Du Pont
                           Carnegie-Mellon    Tektronix
                           Univ. of Pittsburgh
                           UC at Irvine
                           Univ. of Illinois
                           Cornell University


      One should notice the remarkable number of non-university installations 
      as an indication that PASCAL has clearly outgrown any categorization as 
      an "academic" language.  This widespread acceptance has motivated further 
      work on improving our implementation /29/.  
      This work has been completed in December 1976 including removal of errors 
      brought to our attention and incorporating formal procedure/function parameters. 
      The latter has been implemented by H. Linde at our institute based upon an 
      addition by G. V. D. Kraats under the supervision of Dr. C. Bron at Twente 
      Technical Hoogeschool /38/.  
      
      Our current PASCAL compiler version may be characterized as follows:

      Features of current PDP-10 PASCAL-system
      ________________________________________

      - 1 pass compiler for superset of STANDARD PASCAL
                High segment 28K  -  reentrant
                Low segment  19K
        compiles 62 lines per sec ( ~ 37 characters/line)
                 on KA-10
        compiler and significant part of runtime support written in
        PASCAL, rest of runtime support in well-commented MACRO-10.
      - generates relocatable object code compatible with LINK-10
      - access to FORTRAN-Library (SIN, COS, EXP, ...) built in
      - Interactive source level debugging system
      - Post Mortem Dump Facility
           covering all declared varables
           and the content of stack and heap
           can be activated interactively, too
      - Automatic Conversion of Scalar and SET-Variables for TEST-I/O!
      - Optional runtime checks for
        - value out of (sub)range
        - array indices
        - arithmetic overflow
        - zero divide
      - Can be activated via Concise Command Language
        e.g. COMPILE        LOAD        EXECUTE
      - Separate Compilation of Procedures
      - Cross reference and Indentation Program
      - PASCAL Manual for DECSystem-10 Implementation

      According to a very recent agreement with DEC, this signifi-
      cantly improved compiler version is being distributed by DECUS
      starting January 1977.

      It may be mentioned that PASCAL has been implemented as a
      cross-compiler for Dietz MINCAL 621 minicomputers at our instal-
      lation.  Moreover, a two-pass cross-compiler for CONCURRENT
      PASCAL /26/ incorporating an intermediate code step of very
      general structure for easy adaptation to byte-oriented mini-
      computers like Dietz MINCAL 621, DEC PDP-11, Interdata M85 has
      been written in PASCAL /39/.  This Concurrent PASCAL compiler
      is being used already for prociding production programs in a
      local minicomputer network for scene analysis.

     /1/ N. Wirth, The Programming Language PASCAL,
         Acta Informatica vol. 1, 35-63 (1971)

     /2/ N. Wirth, The Programming Language PASCAL, (Revised Report),
         Berichte der Fachgruppe Computerwissenschaften Nr. 5, ETH
         Zurich, July 1973

     /3/ N. Wirth, The Design of a PASCAL Compiler,
         Software - Practice and Experience vol. 1, 309-333 (1971)

     /4/ U. Ammann, The Method of Structured Programming Applied 
         to the Development of a Compiler,
         International Computing Symposium 1973, A. Gunther et al.
         (eds.), North Holland Publishing Co., Amsterdam 1974

     /5/ U. Ammann, Die Entwicklung eines PASCAL Compilers nach
         der Methode des Strukturierten Programmierens,
         Dissertation ETH Zurich 5456, Juris Druck und Verlag,
         Zurich 1975

     /6/ K. Jensen and N. Wirth, PASCAL - User Manual and Report,
         Lecture Notes in Computer Science vol. 18(1974) and Springer
         Study Edition (1975), both Springer Verlag, Berlin-Heidelberg-
         New York

     /7/ O.J. Dahl and K. Nygaard, SIMULA - an ALGOL-Based Simula-
         tion Language
         Comm. ACM vol. 9, 671-678 (1966)

     /8/ A. van Wijngaarden (ed.), B.J. Mailloux, J.E.L. Peck,
         C.H.A. Koster, Report on the Algorithmic Language Algol 68,
         Numerische Mathematik vol. 14, 79-218 (1969)

     /9/ A.N. Habermann, Critical comments on the Programming Lan-
         guage PASCAL,
         Acta Informatica vol. 3, 47-57 (1973)

    /10/ O. Lecarme and P. Desjardins, Reply to a Paper by
         A.N. Habermann on the Programming Language PASCAL,
         SIGPLAN Notices vol. 9, number 10, pp. 21-27 (1974)

    /11/ O. Lecarme and P. Desjardins, More Comments on the Pro-
         gramming Language PASCAL,
         Acta Informatica vol. 4, 231-243 (1975)

    /12/ R. Conradi, Further Critical Comments on PASCAL, Particular-
         ly as a Systems Programming Language,
         SIGPLAN Notices vol. 11, number 11, pp. 8-25 (Nov. 1976)

    /13/ N. Wirth, On the Design of Programming Languages,
         Information Processing 1974, J.L. Rosenfeld (ed.), pp. 386-
         393, North-Holland Publ. Co., Amsterdam 1974

    /14/ N. Wirth, An Assessment of the Programming Language PASCAL,
         IEEE Trans. on Software Engineering vol. 1, 192-198 (1975)

    /15/ B.L. Clark and F.J.B. Ham, The Project SUE, System Lan-
         guage Reference Manual, Techn. Report CSRG-42,
         Computer Systems Research Group, Univ. of Toronto, Canada, 1974
         
    /16/ M. Rain et al., MARY - a Portable Machine Oriented Pro-
         gramming Language,
         MOL Bulletin No. 3, 1973, Computing Centre at the Univer-
         sity, N-7034 Trondheim NTH Norway

    /17/ J.M. Smith and D.C.P. Smith, Data Base Abstraction,
         Proc. Conference on Data:  Abstraction, Definition and
         Structure, Salt Lake City/Utah, March 22-24, 1976;
         appeared in SIGPLAN Notices vol. 11 (1976) (special issue)p.71

    /18/ J.W. Schmidt, Extending PASCAL by a Data Structure Re-
         lation:  PASCAL as a Host Language for a Relational Data
         Base,
         Kurzvortrag aug der GI-Jahrestagung 29. Sept.- 1. Okt.
         1976, Stuttgart
         see also
         J.W. Schmidt, Untersuchung einer Erweiterung von PASCAL 
         zu einer Datenbanksprache,
         IfI-HH-M-28/76, Institut fuer Informatik der Universitaet
         Hamburg, Marz 1976

    /19/ Shigeru Igarashi, R.L. London and D.C. Luckham, Automatic
         Program Verification I:  A Logical Basis and its Implemen-
         tation, STAN-CS-73-365
         Stanford/Calif., May 1973

    /20/ F.W. v. Henke and D.C. Luckham, Automatic Program Verifi-
         cation III:  A Methodology for Verifying Programs,
         STAN-CS-74-474, Stanford/Calif., December 1974

    /21/ E. Marmier, Automatic Verification of PASCAL Programs,
         Dissertation ETH Zurich Nr. 5629 (1975)

    /22/ C.A.R. Hoare and N. Wirth, An Axiomatic Definition of
         the Programming Language PASCAL, Acta Informatica vol. 2,
         335-355 (1973)

    /23/ J. Welsh and C. Quinn, A PASCAL compiler for the ICL 1900
         series computer,
         Software - Practice and Experience, vol. 2, 73-77 (1972)

    /24/ G. Friesland et al., A PASCAL Compiler Bootstrapped on
         a DECSystem-10,
         Lecture Notes in Computer Science vol. 7, 101-113, Springer
         Verlag, Berlin-heidelberg-New York 1974

    /25/ K.V. Nori et al., The PASCAL-(P)-Compiler Implementation Notes
         Berichte der Fachgruppe Computerwissenschaften Nr. 10, ETH
         Zurich, Dezember 1974

    /26/ P. Brinch Hansen, The Programming Language CONNCURRENT PASCAL,
         IEEE Trans. on Software Engineering vol. 1, 199-207 (1975)

    /27/ C.-O. Grosse-Lindemann and H.-H. Nagel, Postlude to a
         PASCAL-Compiler Bootstrap on a DECSystem-10,
         Software - Practice and Experience vol. 6, 29-42 (1976)

    /28/ Erweiterung von Sprachdefinition, Compiler und Laufzeit-
         unterstutzung bei PASCAL-Erfahrungen und Ergebnisse eines
         Praktikumsprojektes im Informatik-Grundstudium, studenti-
         sche Beitrage, uberarbeitet und erganzt von H.-H. Nagel,
         Mitteilung Nr. 16 des Instituts fur Informatik der Uni-
         versitat Hamburg, Mai 1975

    /29/ H.-H. Nagel, PASCAL for the DECSystem-10:  Experiences
         and further Plans,
         Mitteilung Nr. 21 des Instituts fur Informatik der Univer
         sitat Hamburg, November 1975

    /30/ B. Nebel and B. Pretschner, Erweiterung des DECSystem-10
         PASCAL-Compilers um eine Moglichkeit zur Erzeugung eines
         Post-Mortem-Dump,
         Mitteilung IfI-HH-M-34/76, Institut fur Informatik der
         Universitat Hamburg, Juni 1976

    /31/ P. Putfarken, Pruefhilfen fuer PASCAL-Programme, Diplom-
         arbeit, Institut fur Informatik der Universitat Hamburg,
         November 1976

    /32/ E. Kisicki and H.-H. Nagel, PASCAL for the DECSystem-10,
         Manual,
         Mitteilung IfI-HH-M-37/76, Institut fur Informatik der
         Universitat Hamburg, Dezember 1976
         (This manual is available as a computer readable file)

    /33/ O. Lecarme and G.V. Bockmann, A (truly) Usable and Port-
         able Compiler Writing System,
         Information Processing 1974, J.L. Rosenfeld (ed.),
         North-Holland Publ. Co., Amsterdam 1974, pp. 218-221

    /34/ M. Behrens and G. Friesland, Benutzungsanleitung fuer das 
         Compiler-Writing-System Montreal, angepasst an das DEC-
         System-10,
         IfI-HH-M-30/76, Institut fur Informatik der Universitat
         Hamburg, April 1976

    /35/ I. Kupka, H. Oberquelle and N. Wilsing, Projekt einer
         Rahmendialogsprache - RDS,
         IfI-HH-M-9/74, Institut fur Informatik der Universitat
         Hamburg, Oktober 1974

    /36/ H.-H. Nagel, Experiences with Yakimovsky's Algorithm
         for Boundary and Object Detection in Real World Images,
         Proc. 3rd International Joint conference on Pattern Re-
         cognition, Coronado/Cal., November 8-11, 1976, pp. 753-758


    /37/ H.-H. Nagel, Formation of an Object Concept by Analysis
         of Systematic Time Variations in the Optically Percep-
         tible Environment,
         Computer Graphics and Image Processing (in press)

    /38/ G.V.D. Kraats, Diploma Thesis, Dr. Bron (Supervisor),
         Technische Hogeschool Twente, Enschede

    /39/ B. Bruegge et al., Concurrent Pascal Compiler fuer Klein-
         rechner,
         Institut fur Informatik der Universitat Hamburg, Dezember
         1976

Px compilers

The Pascal-P compiler was created in 1973, then went through several versions, which so far have not been available. Ch. Jacobi gives an overview of the Pascal-P versions in PUG newsletter #4:

Name Origination Year Source Description
Pascal P1 Zurich 1973 No Either of the early Pascal-P systems (released in March and July 1973 respectively)
Pascal-P2 Zurich 1974 Yes The Pascal-P system released in May 74
Pascal-P3 Zurich 1976 No The new Pascal-P system with the same hypothetical machine as the one underlying the Pascal P2 system
Pascal-P4 Zurich 1976 Yes The new Pascal-P system with a slightly modified hypothetical machine (allowing a more efficient implementation)

The versions of P1 that existed have (so far) not been available. The revised version, P2, is available, and was used as the basis for the UCSD system. P3 was a “step” implementation used to bridge between P2 and P4, and is also not obtainable.

The last major version of Pascal-P was P4.

PL/0

PL/0 is a small educational language designed and implemented by Wirth to be used as an example of compiler development.

The language was presented by Niklaus Wirth in his book “Algorithms + Data Structures = Programs” (1975). Later versions of this book did not contain PL/0, but the small compilers did appear in the Compiler Construction series.

His later book “Compilerbau” or “Compiler Construction”, 1976) provided also the full source code of PL/0 compiler written in Pascal. Later editions (3rd, 1984)  the PL/0 compiler was rewritten in Modula and enhanced a bit with e.g. print statements.

After Oberon was conceived the example language was succeeded by Oberon-0. Sources of these PL/0 and Oberon-0 compilers”

See the Books by Wirth page for the relevant Compiler Construction books.
Note that PL/0 only appeared in the 1975 English version of Algorithms + Data Structures = Programs, it is not present in the German version Algorithmen und Data Structuren book of 1975.

PL/0 1975 Pascal version from Compilerbau (1977) and Algorithms + Data Structures = Programs (1976)

Chapter 5 of Algorithms and Data Structures

The capabilities of the language were intentionally, for study, limited:

–the only data type are integer numbers. Still all constants and variables used have to be declared explicitly, not deduced at compile-time.
–the only operators provided are arithmetical and comparison ones.
–there is one built-in function odd which checks whether the integer argument is odd.
– there are no input/output routines; instead the compiler prints the new value of each variable whenever it gets changed.
– the flow control structures are represented by if-then and while-do constructs, as well as user-defined procedures (which can’t accept any parameters).

The syntax of PL/0 (1975 version) described in extended Backus-Naur form

program = block .

block = [ const ident = number {, ident = number} ;]
        [ var ident {, ident} ;]
        { procedure ident ; block ; } statement .

statement = [ ident := expression | call ident 
              | ? ident | ! expression 
              | begin statement {; statement } end 
              | if condition then statement 
              | while condition do statement ].

condition = odd expression |
            expression (=|#|&amp;lt;|&amp;lt;=|&amp;gt;|&amp;gt;=) expression .

expression = [ +|-] term { (+|-) term}.

term = factor {(*|/) factor}.

factor = ident | number | ( expression )

Elements of syntax

Case-sensitivity yes
Variable assignment :=
Variable declaration var
Block begin … end
Physical (shallow) equality =
Physical (shallow) inequality #
Comparison < >
Function definition procedure <name>; <body>;
Function call call <name>
Sequence ;
If – then if <condition> then <trueBlock>
Loop forever while 1 = 1 do <loopBody>
While condition do while do <loopBody>

To compile with Delphi, Freepascal, or any compiler where object is a reserved name: rename identifier ‘object’. For FPC add {$mode ISO} to allow the goto.

program pl0(input,output);
{pl/0 compiler with code generation}
label 99;
const norw = 11;     {no. of reserved words}
   txmax = 100;      {length of identifier table}
   nmax = 14;        {max. no. of digits in numbers}
   al = 10;          {length of identifiers}
   amax = 2047;      {maximum address}
   levmax = 3;       {maximum depth of block nesting}
   cxmax = 200;      {size of code array}
type symbol =
   (nul,ident,number,plus,minus,times,slash,oddsym,
    eql,neq,lss,leq,gtr,geq,lparen,rparen,comma,semicolon,
    period,becomes,beginsym,endsym,ifsym,thensym,
    whilesym,dosym,callsym,constsym,varsym,procsym);
    alfa = packed array [1..al] of char;
    object = (constant,varible,proc);
    symset = set of symbol;
    fct = (lit,opr,lod,sto,cal,int,jmp,jpc);   {functions}
    instruction = packed record
                     f: fct;           {function code}
                     l: 0..levmax;     {level}
                     a: 0..amax        {displacement address}
                  end;
{   lit 0,a  :  load constant a
    opr 0,a  :  execute operation a
    lod l,a  :  load varible l,a
    sto l,a  :  store varible l,a
    cal l,a  :  call procedure a at level l
    int 0,a  :  increment t-register by a
    jmp 0,a  :  jump to a
    jpc 0,a  :  jump conditional to a   }
var ch: char;         {last character read}
    sym: symbol;      {last symbol read}
    id: alfa;         {last identifier read}
    num: integer;     {last number read}
    cc: integer;      {character count}
    ll: integer;      {line length}
    kk, err: integer;
    cx: integer;      {code allocation index}
    line: array [1..81] of char;
    a: alfa;
    code: array [0..cxmax] of instruction;
    word: array [1..norw] of alfa;
    wsym: array [1..norw] of symbol;
    ssym: array [char] of symbol;
    mnemonic: array [fct] of
                 packed array [1..5] of char;
    declbegsys, statbegsys, facbegsys: symset;
    table: array [0..txmax] of
           record name: alfa;
              case kind: object of
              constant: (val: integer);
              varible, proc: (level, adr: integer)
           end;
procedure error(n: integer);
begin writeln(' ****',' ': cc-1, '^',n: 2); err := err+1
end {error};
 
procedure getsym;
   var i,j,k: integer;
 
   procedure getch;
   begin if cc = ll then
      begin if eof(input) then
                 begin write(' program incomplete'); goto 99
                 end;
         ll := 0; cc := 0; write(cx: 5,' ');
         while not eoln(input) do
            begin ll := ll+1; read(ch); write(ch); line[ll]:=ch
            end;
         writeln; readln; ll := ll + 1; line[ll] := ' ';
      end;
      cc := cc+1; ch := line[cc]
   end {getch};
 
begin {getsym}
   while ch  = ' ' do getch;
   if ch in ['a'..'z'] then
   begin {identifier or reserved word} k := 0;
      repeat if k &amp;lt; al then
         begin k := k+1; a[k] := ch
         end;
         getch;
      until not(ch in ['a'..'z','0'..'9']);
      if k &amp;gt;= kk then kk := k else
         repeat a[kk] := ' '; kk := kk-1
         until kk = k;
      id := a; i := 1; j := norw;
      repeat k := (i+j) div 2;
         if id &amp;lt;= word[k] then j := k-1;
         if id &amp;gt;= word[k] then i := k+1
      until i &amp;gt; j;
      if i-1 &amp;gt; j then sym := wsym[k] else sym := ident
   end else
   if ch in ['0'..'9'] then
   begin {number} k := 0; num := 0; sym := number;
      repeat num := 10*num + (ord(ch)-ord('0'));
         k := k+1; getch
      until not(ch in ['0'..'9']);
      if k &amp;gt; nmax then error(30)
   end else
   if ch = ':' then
   begin getch;
      if ch = '=' then
      begin sym := becomes; getch
      end else sym := nul;
   end else
   begin sym := ssym[ch]; getch
   end
end {getsym};
 
procedure gen(x: fct; y,z: integer);
begin if cx &amp;gt; cxmax then
           begin write(' program too long'); goto 99
           end;
   with code[cx] do
      begin f := x; l := y; a := z
      end;
   cx := cx + 1
end {gen};
 
procedure test(s1,s2: symset; n: integer);
begin if not(sym in s1) then
        begin error(n); s1 := s1 + s2;
           while not(sym in s1) do getsym
        end
end {test};
 
procedure block(lev,tx: integer; fsys: symset);
   var dx: integer;     {data allocation index}
      tx0: integer;     {initial table index}
      cx0: integer;     {initial code index}
   procedure enter(k: object);
   begin {enter object into table}
      tx := tx + 1;
      with table[tx] do
      begin name := id; kind := k;
         case k of
         constant: begin if num &amp;gt; amax then
                              begin error(30); num :=0 end;
                      val := num
                   end;
         varible: begin level := lev; adr := dx; dx := dx + 1;
                  end;
         proc: level := lev
         end
      end
   end {enter};
 
   function position(id: alfa): integer;
      var i: integer;
   begin {find indentifier id in table}
      table[0].name := id; i := tx;
      while table[i].name &amp;lt;&amp;gt; id do i := i-1;
      position := i
   end {position};
 
   procedure constdeclaration;
   begin if sym = ident then
      begin getsym;
         if sym in [eql, becomes] then
         begin if sym = becomes then error(1);
            getsym;
            if sym = number then
               begin enter(constant); getsym
               end
            else error(2)
         end else error(3)
      end else error(4)
   end {constdeclaration};
 
   procedure vardeclaration;
   begin if sym = ident then
           begin enter(varible); getsym
           end else error(4)
   end {vardeclaration};
 
   procedure listcode;
      var i: integer;
   begin {list code generated for this block}
      for i := cx0 to cx-1 do
         with code[i] do
            writeln(i:5, mnemonic[f]:5, 1:3, a:5)
   end {listcode};
 
   procedure statement(fsys: symset);
      var i, cx1, cx2: integer;
      procedure expression(fsys: symset);
         var addop: symbol;
         procedure term(fsys: symset);
            var mulop: symbol;
            procedure factor(fsys: symset);
               var i: integer;
            begin test(facbegsys, fsys, 24);
               while sym in facbegsys do
               begin
                  if sym = ident then
                  begin i:= position(id);
                     if i = 0 then error(11) else
                     with table[i] do
                     case kind of
                        constant: gen(lit, 0, val);
                        varible: gen(lod, lev-level, adr);
                        proc: error(21)
                     end;
                     getsym
                  end else
                  if sym = number then
                  begin if num &amp;gt;  amax then
                           begin error(30); num := 0
                           end;
                     gen(lit, 0, num); getsym
                  end else
                  if sym = lparen then
                  begin getsym; expression([rparen]+fsys);
                     if sym = rparen then getsym else error(22)
                  end;
                  test(fsys, [lparen], 23)
               end
            end {factor};
 
         begin {term} factor(fsys+[times, slash]);
            while sym in [times, slash] do
             begin mulop:=sym;getsym;factor(fsys+[times,slash]);
              if mulop=times then gen(opr,0,4) else gen(opr,0,5)
             end
         end {term};
      begin {expression}
         if sym in [plus, minus] then
            begin addop := sym; getsym; term(fsys+[plus,minus]);
               if addop = minus then gen(opr, 0,1)
            end else term(fsys+[plus, minus]);
         while sym in [plus, minus] do
            begin addop := sym; getsym; term(fsys+[plus,minus]);
               if addop=plus then gen(opr,0,2) else gen(opr,0,3)
            end
      end {expression};
 
      procedure condition(fsys: symset);
         var relop: symbol;
      begin
         if sym  = oddsym then
         begin getsym; expression(fsys); gen(opr, 0, 6)
         end else
         begin expression([eql, neq, lss, gtr, leq, geq]+fsys);
            if not(sym in [eql, neq, lss, leq, gtr, geq]) then
               error(20) else
            begin relop := sym; getsym; expression(fsys);
               case relop of
                  eql: gen(opr, 0, 8);
                  neq: gen(opr, 0, 9);
                  lss: gen(opr, 0, 10);
                  geq: gen(opr, 0, 11);
                  gtr: gen(opr, 0, 12);
                  leq: gen(opr, 0, 13);
               end
            end
         end
      end {condition};
 
   begin {statement}
      if sym = ident then
      begin i := position(id);
         if i = 0 then error(11) else
         if table[i].kind &amp;lt;&amp;gt; varible then
            begin {assignment to non-varible} error(12); i := 0
            end;
         getsym; if sym = becomes then getsym else error(13);
         expression(fsys);
         if i &amp;lt;&amp;gt; 0 then
            with table[i] do gen(sto, lev-level, adr)
      end else
      if sym = callsym then
      begin getsym;
         if sym &amp;lt;&amp;gt; ident then error(14) else
            begin i := position(id);
               if i = 0 then error(11) else
               with table[i] do
                  if kind=proc then gen(cal, lev-level, adr)
                  else error(15);
               getsym
            end
      end else
      if sym = ifsym then
      begin getsym; condition([thensym, dosym]+fsys);
         if sym = thensym then getsym else error(16);
         cx1 := cx; gen(jpc, 0, 0);
         statement(fsys); code[cx1].a := cx
      end else
      if sym = beginsym then
      begin getsym; statement([semicolon, endsym]+fsys);
         while sym in [semicolon]+statbegsys do
         begin
            if sym = semicolon then getsym else error(10);
            statement([semicolon, endsym]+fsys)
         end;
         if sym = endsym then getsym else error(17)
      end else
      if sym = whilesym then
      begin cx1 := cx; getsym; condition([dosym]+fsys);
         cx2 := cx; gen(jpc, 0, 0);
         if sym = dosym then getsym else error(18);
         statement(fsys); gen(jmp, 0, cx1); code[cx2].a := cx
      end;
      test(fsys, [], 19)
   end {statement};
 
begin {block} dx:=3; tx0:=tx; table[tx].adr:=cx; gen(jmp,0,0);
   if lev &amp;gt; levmax then error(32);
   repeat
      if sym = constsym then
      begin getsym;
         repeat constdeclaration;
            while sym = comma do
               begin getsym; constdeclaration
               end;
            if sym = semicolon then getsym else error(5)
         until sym &amp;lt;&amp;gt; ident
      end;
      if sym = varsym then
      begin getsym;
         repeat vardeclaration;
            while sym = comma do
               begin getsym; vardeclaration
               end;
            if sym = semicolon then getsym else error(5)
         until sym &amp;lt;&amp;gt; ident;
      end;
      while sym = procsym do
      begin getsym;
         if sym = ident then
            begin enter(proc); getsym
            end
         else error(4);
         if sym = semicolon then getsym else error(5);
         block(lev+1, tx, [semicolon]+fsys);
         if sym = semicolon then
            begin getsym;test(statbegsys+[ident,procsym],fsys,6)
            end
         else error(5)
      end;
      test(statbegsys+[ident], declbegsys, 7)
   until not(sym in declbegsys);
   code[table[tx0].adr].a := cx;
   with table[tx0] do
      begin adr := cx; {start adr of code}
      end;
   cx0 := 0{cx}; gen(int, 0, dx);
   statement([semicolon, endsym]+fsys);
   gen(opr, 0, 0); {return}
   test(fsys, [], 8);
   listcode;
end {block};
 
procedure interpret;
   const stacksize = 500;
   var p,b,t: integer; {program-, base-, topstack-registers}
      i: instruction; {instruction register}
      s: array [1..stacksize] of integer; {datastore}
   function base(l: integer): integer;
      var b1: integer;
   begin b1 := b; {find base l levels down}
      while l &amp;gt; 0 do
         begin b1 := s[b1]; l := l - 1
         end;
      base := b1
   end {base};
 
begin writeln(' start pl/0');
   t := 0; b := 1; p := 0;
   s[1] := 0; s[2] := 0; s[3] := 0;
   repeat i := code[p]; p := p + 1;
      with i do
      case f of
      lit: begin t := t + 1; s[t] := a
           end;
      opr: case a of {operator}
           0: begin {return}
                 t := b - 1; p := s[t + 3]; b := s[t + 2];
              end;
           1: s[t] := -s[t];
           2: begin t := t - 1; s[t] := s[t] + s[t + 1]
              end;
           3: begin t := t - 1; s[t] := s[t] - s[t + 1]
              end;
           4: begin t := t - 1; s[t] := s[t] * s[t + 1]
              end;
           5: begin t := t - 1; s[t] := s[t] div s[t + 1]
              end;
           6: s[t] := ord(odd(s[t]));
           8: begin t := t - 1; s[t] := ord(s[t] = s[t + 1])
              end;
           9: begin t := t - 1; s[t] := ord(s[t] &amp;lt;&amp;gt; s[t + 1])
              end;
          10: begin t := t - 1; s[t] := ord(s[t] &amp;lt; s[t + 1])
              end;
          11: begin t := t - 1; s[t] := ord(s[t] &amp;gt;= s[t + 1])
              end;
          12: begin t := t - 1; s[t] := ord(s[t] &amp;gt; s[t + 1])
              end;
          13: begin t := t - 1; s[t] := ord(s[t] &amp;lt;= s[t + 1])
              end;
          end;
      lod: begin t := t + 1; s[t] := s[base(l) + a]
           end;
      sto: begin s[base(l)+a] := s[t]; writeln(s[t]); t := t - 1
           end;
      cal: begin {generate new block mark}
              s[t + 1] := base(l); s[t + 2] := b; s[t + 3] := p;
              b := t + 1; p := a
           end;
      int: t := t + a;
      jmp: p := a;
      jpc: begin if s[t] = 0 then p := a; t := t - 1
           end
      end {with, case}
   until p = 0;
   write(' end pl/0');
end {interpret};

begin {main program}
   for ch := chr(0) to chr(255) do ssym[ch] := nul;
   word[ 1] := 'begin     ';      word[ 2] := 'call      ';
   word[ 3] := 'const     ';      word[ 4] := 'do        ';
   word[ 5] := 'end       ';      word[ 6] := 'if        ';
   word[ 7] := 'odd       ';      word[ 8] := 'procedure ';
   word[ 9] := 'then      ';      word[10] := 'var       ';
   word[11] := 'while     ';
   wsym[ 1] := beginsym;     wsym[ 2] := callsym;
   wsym[ 3] := constsym;     wsym[ 4] := dosym;
   wsym[ 5] := endsym;       wsym[ 6] := ifsym;
   wsym[ 7] := oddsym;       wsym[ 8] := procsym;
   wsym[ 9] := thensym;      wsym[10] := varsym;
   wsym[11] := whilesym;
   ssym[ '+'] := plus;       ssym[ '-'] := minus;
   ssym[ '*'] := times;      ssym[ '/'] := slash;
   ssym[ '('] := lparen;     ssym[ ')'] := rparen;
   ssym[ '='] := eql;        ssym[ ','] := comma;
   ssym[ '.'] := period;     ssym[ '#'] := neq;
   ssym[ '&amp;lt;'] := lss;        ssym[ '&amp;gt;'] := gtr;
   ssym[ '['] := leq;        ssym[ ']'] := geq;
   ssym[ ';'] := semicolon;
   mnemonic[lit] := '  lit';   mnemonic[opr] := '  opr';
   mnemonic[lod] := '  lod';   mnemonic[sto] := '  sto';
   mnemonic[cal] := '  cal';   mnemonic[int] := '  int';
   mnemonic[jmp] := '  jmp';   mnemonic[jpc] := '  jpc';
   declbegsys := [constsym, varsym, procsym];
   statbegsys := [beginsym, callsym, ifsym, whilesym];
   facbegsys  := [ident, number, lparen];
   page(output); err := 0;
   cc := 0; cx := 0; ll := 0; ch := ' '; kk := al; getsym;
   block(0, 0, [period]+declbegsys+statbegsys);
   if sym &amp;lt;&amp;gt; period then error(9);
  if err=0 then interpret else write(' errors in pl/0 program');
99: writeln
end.
post

Concurrent and Sequential Pascal, Solo

Per Brinch Hansen announced Sequenatila and Concurrent Pascal in the Pascal User Group Newsletter nr 4, July 1976:

Concurrent Pascal is a programming language designed by Per Brinch Hansen for writing concurrent computing programs such as operating systems and real-time computing monitoring systems on shared memory computers. A separate language, Sequential Pascal, is used as the language for applications programs run by the operating systems written in Concurrent Pascal. Both languages are extensions of Niklaus Wirth’s Pascal, and share a common threaded code interpreter.
Several constructs in Pascal were removed from Concurrent Pascal for simplicity and security:
– Variant records
– Goto statement, and labels
– Procedures as parameters
– Packed arrays
– Pointer types
– File types, and associated standard input/output procedures
These omissions make it possible to guarantee, by a combination of compile-time checks and minimal run-time checking in the threaded-code interpreter, that a program can not damage itself or another program by addressing outside its allotted space.

Concurrent Pascal includes class, monitor, and process data types. Instances of these types are declared as variables, and initialized in an init statement.
Classes and monitors are similar: both package private variables and procedures with public procedures (called procedure entries). A class instance can be used by only one process, whereas a monitor instance may be shared by processes. Monitors provide the only mechanism for interprocess communication in a Concurrent Pascal program.
Only one process can execute within a given monitor instance at a time. A built in data type, the queue, together with operations delay and continue, are used for scheduling within monitors. Each variable of type queue can hold one process. If many processes are to be delayed in a monitor, multiple queue variables, usually organized as an array, must be provided. The single process queue variable gives a monitor full control over medium-term scheduling, but the programmer is responsible for unblocking the correct process.
A process, like a class or monitor, has local variables, procedures, and an initial statement, but has no procedure entries. The initial statement ordinarily executes forever, calling local procedures, class procedures, and monitor procedures. Processes communicate through monitor procedures. Language rules prevent deadlock by imposing a hierarchy on monitors. But nothing can prevent a monitor from erroneously forgetting to unblock a delayed process (by not calling continue) so the system can still effectively hang up through programming errors.
The configuration of processes, monitors, and classes in a Concurrent Pascal program is normally established at the start of execution, and is not changed thereafter. The communication paths between these components are established by variables passed in the init statements, since class and monitor instance variables cannot be used as procedure parameters.
Solo
The single-user operating system Solo is written in the programming language Concurrent Pascal. It supports the development of Sequential and Concurrent Pascal programs for the PDP 11/45 computer. Input/output are handled by concurrent processes. Pascal programs can call one another recursively and pass arbitrary parameters among themselves. This makes it possible to use Pascal as a job control language. Solo is the first major example of a hierarchical concurrent program implemented in terms of abstract data types (classes, monitors and processes) with compile-time control of most access rights

The Architecture of Concurrent Programs, 1977.
About the languages and Solo operating system.
Most of the book is covered in the following articles.
A Concurrent Pascal Compiler for Minicomputers
Afred C. Hartmann (who wrote the compiler!)
Concurrent Pascal Introduction July 1975
Concurrent Pascal Machine October 1975
Concurrent Pascal Report June 1975
Distributed processes:
a Concurrent Programming Concept, 1978
Experience with Modular Concurrent Programming, 1977
IEEE Programming Language Concurrent Pascal, 1975
Monitors and Concurrent Pascal:
A Personal History, 1993
Multiprocessor architecture for Concurrent Programs, 1978
The Structure of the Nadex Operating System
Robert Ypung, Virgil Wallentine 1981
Network: A Multiprocessor Program
Overview of Concurrent Pascal for the Interdata, 1978
The Programming Language Concurrent Pascal, 1975
Reproducable Testing of Monitors, 1978
Scheduling in Concurrent Pascal
Schneider, Bernmstein, 1978
The Solo Operating System:
Processes, Monitors and Classes, 1976
The Solo Operating system:
A Concurrent Pascal Program, 1976
Solo32: A Concurrent Pascal Operating System
with Unix Interface, Martin Wilde, 1984

The archive with the sources of Solo and the Pascal compilers Concurrent and Sequential Pascal for a PDP-11/34

From http://www.bitsavers.org/bits/DEC/pdp11/Brinch_Hansen_SOLO/

LIST(CATALOG,ALL,CONSOLE)
CONSOLE: 
SOLO SYSTEM FILES

AUTOLOAD     SCRATCH      PROTECTED         1 PAGES
BACKUP       SEQCODE      PROTECTED         4 PAGES
BACKUPMAN    ASCII        PROTECTED         3 PAGES
BACKUPTEXT   ASCII        PROTECTED        14 PAGES
BUILDBATTEXT ASCII        UNPROTECTED       1 PAGES
BUILDTEXT    ASCII        UNPROTECTED       4 PAGES
CARDS        SEQCODE      PROTECTED         5 PAGES
CARDSMAN     ASCII        PROTECTED         2 PAGES
CARDSTEXT    ASCII        PROTECTED        12 PAGES
CATALOG      SCRATCH      PROTECTED        15 PAGES
CDISKTEXT    ASCII        UNPROTECTED      10 PAGES
COMMANDS     ASCII        UNPROTECTED       1 PAGES
CONSOLE      SEQCODE      PROTECTED         1 PAGES
CONSOLEMAN   ASCII        PROTECTED         1 PAGES
CONSOLETEXT  ASCII        PROTECTED         8 PAGES
COPY         SEQCODE      PROTECTED         4 PAGES
COPYMAN      ASCII        PROTECTED         2 PAGES
COPYTEXT     ASCII        PROTECTED        12 PAGES
CPASCAL      SEQCODE      PROTECTED         7 PAGES
CPASCALMAN   ASCII        PROTECTED         3 PAGES
CPASCALTEXT  ASCII        PROTECTED        18 PAGES
CPASS1       SEQCODE      PROTECTED        20 PAGES
CPASS1TEXT   ASCII        PROTECTED        54 PAGES
CPASS2       SEQCODE      PROTECTED        26 PAGES
CPASS2TEXT   ASCII        PROTECTED        72 PAGES
CPASS3       SEQCODE      PROTECTED        35 PAGES
CPASS3TEXT   ASCII        PROTECTED        90 PAGES
CPASS4       SEQCODE      PROTECTED        27 PAGES
CPASS4TEXT   ASCII        PROTECTED        71 PAGES
CPASS5       SEQCODE      PROTECTED        20 PAGES
CPASS5TEXT   ASCII        PROTECTED        56 PAGES
CPASS6       SEQCODE      PROTECTED        16 PAGES
CPASS6TEXT   ASCII        PROTECTED        53 PAGES
CPASS7       SEQCODE      PROTECTED        18 PAGES
CPASS7TEXT   ASCII        PROTECTED        56 PAGES
CPTEXT       ASCII        UNPROTECTED       2 PAGES
DISK         SEQCODE      PROTECTED         2 PAGES
DISKMAN      ASCII        PROTECTED         1 PAGES
DISKTEXT     ASCII        PROTECTED         9 PAGES
DO           SEQCODE      PROTECTED        11 PAGES
DOMAN        ASCII        PROTECTED         3 PAGES
DOTEXT       ASCII        PROTECTED        26 PAGES
EDIT         SEQCODE      PROTECTED         8 PAGES
EDITMAN      ASCII        PROTECTED         5 PAGES
EDITTEXT     ASCII        PROTECTED        20 PAGES
FILE         SEQCODE      PROTECTED        20 PAGES
FILEMAN      ASCII        PROTECTED         3 PAGES
FILETEXT     ASCII        PROTECTED        54 PAGES
IO           SEQCODE      PROTECTED         4 PAGES
IOTEXT       ASCII        PROTECTED        13 PAGES
JOB          SEQCODE      PROTECTED        40 PAGES
JOBBUFFER1   SCRATCH      PROTECTED        20 PAGES
JOBBUFFER2   SCRATCH      PROTECTED        20 PAGES
JOBINPUT     SEQCODE      PROTECTED         3 PAGES
JOBINPUTTEXT ASCII        PROTECTED         6 PAGES
JOBOUTPUT    SEQCODE      PROTECTED         2 PAGES
JOBOUTPUTTXT ASCII        PROTECTED         6 PAGES
JOBPREFIX    ASCII        PROTECTED         1 PAGES
JOBSERVICE   SEQCODE      PROTECTED         3 PAGES
JOBSERVICETX ASCII        PROTECTED         8 PAGES
JOBSTREAM    CONCODE      PROTECTED        17 PAGES
JOBSTREAMTXT ASCII        PROTECTED        50 PAGES
KERNELTEXT1  ASCII        UNPROTECTED     134 PAGES
KERNELTEXT2  ASCII        UNPROTECTED     129 PAGES
KERNELTEXT3  ASCII        UNPROTECTED     147 PAGES
KERNELTEXT4  ASCII        UNPROTECTED     171 PAGES
LIST         SEQCODE      PROTECTED         7 PAGES
LISTMAN      ASCII        PROTECTED         2 PAGES
LISTTEXT     ASCII        PROTECTED        19 PAGES
MAKETEMP     SEQCODE      PROTECTED         4 PAGES
MAKETEMPMAN  ASCII        PROTECTED         1 PAGES
MAKETEMPTEXT ASCII        PROTECTED        12 PAGES
MOVE         SEQCODE      PROTECTED         2 PAGES
MOVEMAN      ASCII        PROTECTED         1 PAGES
MOVETEXT     ASCII        PROTECTED        10 PAGES
MTOPTEXT     ASCII        UNPROTECTED       4 PAGES
NEXT         SCRATCH      PROTECTED       255 PAGES
PIPELINE     CONCODE      PROTECTED         4 PAGES
PIPELINETEXT ASCII        PROTECTED         8 PAGES
PREFIX       ASCII        PROTECTED         6 PAGES
PRINTER      SEQCODE      PROTECTED         3 PAGES
PRINTERMAN   ASCII        PROTECTED         2 PAGES
PRINTERTEXT  ASCII        PROTECTED        11 PAGES
READ         SEQCODE      PROTECTED         4 PAGES
READMAN      ASCII        PROTECTED         2 PAGES
READTEXT     ASCII        PROTECTED        12 PAGES
REALTIME     CONCODE      PROTECTED        11 PAGES
REALTIMETEXT ASCII        PROTECTED        23 PAGES
RKBOOTTEXT   ASCII        UNPROTECTED       6 PAGES
SOLO         CONCODE      PROTECTED        18 PAGES
SOLOBATTEXT  ASCII        UNPROTECTED       4 PAGES
SOLOCOPY     ASCII        PROTECTED         1 PAGES
SOLOFILES    ASCII        PROTECTED         1 PAGES
SOLOTEXT     ASCII        PROTECTED        52 PAGES
SPASCAL      SEQCODE      PROTECTED         7 PAGES
SPASCALMAN   ASCII        PROTECTED         3 PAGES
SPASCALTEXT  ASCII        PROTECTED        18 PAGES
SPASS1       SEQCODE      PROTECTED        20 PAGES
SPASS1TEXT   ASCII        PROTECTED        53 PAGES
SPASS2       SEQCODE      PROTECTED        26 PAGES
SPASS2TEXT   ASCII        PROTECTED        73 PAGES
SPASS3       SEQCODE      PROTECTED        35 PAGES
SPASS3TEXT   ASCII        PROTECTED        91 PAGES
SPASS4       SEQCODE      PROTECTED        26 PAGES
SPASS4TEXT   ASCII        PROTECTED        65 PAGES
SPASS5       SEQCODE      PROTECTED        19 PAGES
SPASS5TEXT   ASCII        PROTECTED        54 PAGES
SPASS6       SEQCODE      PROTECTED        16 PAGES
SPASS6TEXT   ASCII        PROTECTED        53 PAGES
SPASS7       SEQCODE      PROTECTED        18 PAGES
SPASS7TEXT   ASCII        PROTECTED        56 PAGES
START        SEQCODE      PROTECTED         3 PAGES
STARTMAN     ASCII        PROTECTED         3 PAGES
STARTTEXT    ASCII        PROTECTED        11 PAGES
SUPERMAC     ASCII        UNPROTECTED      30 PAGES
TAPE         SEQCODE      PROTECTED         3 PAGES
TAPEMAN      ASCII        PROTECTED         2 PAGES
TAPETEXT     ASCII        PROTECTED        14 PAGES
TEMP1        SCRATCH      PROTECTED       255 PAGES
TEMP2        SCRATCH      PROTECTED       255 PAGES
TOTAPETEXT   ASCII        UNPROTECTED       4 PAGES
WRITE        SEQCODE      PROTECTED         2 PAGES
WRITEMAN     ASCII        PROTECTED         1 PAGES
WRITETEXT    ASCII        PROTECTED         9 PAGES
XMAC         ASCII        UNPROTECTED       1 PAGES
   125 ENTRIES
  3391 PAGES