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).

Articles by Wirth et al

Collection of mostly historical articles on Pascal, by Niklaus Wirth and others. From the Pascal compilers to recollections.

On certain Basic Concepts of Programming Languages, Wirth, May 1967
What can we do about the Unnecessary Diversity of Notation for Syntactic Definitions?, Wirth, 1977

An Axiomatic Definition of the Programming Language Pascal, Wirth, Hoare, November 1972
A Collection of Pascal Programs Wirth, Wirth, July 1979
Data Structures and Algorithms Informatics, Wirth August 1984
Error Recovery in Descent Parsers, Urs Ammann. Mai 1978
Implementations of Pascal on Systems With No Control Characters, Wirth, June 1973
The Programming Language Pascal (Revised Report), November 1972
On Code Generation in a PASCAL Compiler, Urs Amnann
On Code Generation in a PASCAL Compiler, Urs Amnann, eth-3056-01
Pascal-P Compiler Implementation Notes, K.V. Nori, Urs Ammann, Christian Jacobi, 1974
Planned Changes To The Programming Language PASCAL, Wirth, June 1972
P-Machine Description, ETH, Januari 73
Program development by step-wise refinement, Wirth, January 1971
The Zurich Implementation, Urs Amman
The Pascal(P) Compiler:_Implementation_Notes, K.V. Nori, U. Ammann, K.Jensen, H.H. Naegeli, Dec 1974
The Programming Language_Pascal, Wirth, 1970
The Programming Language Pascal (Revised Report), Wirth, November 1972
The Programming Language_Pascal (Revised Report), Wirth, July 1973
A Pascal processor Validation Suite, Wichman, Sale, March 1980
Pascal Newsletter May 1974
Page 1 History of Pascal documented. Page 6 Wirth describes Pascal 6000-3.4. Page 18 Wirth describes Pascal-P (the P-machine, probably P1)
Program development by step-wise refinement, Wirth, January 1971
On the Composition of Well-structured Structured Programs, Wirth, 1974
Effective Technology transfer, Wirth 1995
Essay on programming, Wirth, March 1999
Programming Languages_What To_Demand And How To Assess Them, Wirth, April 1976
Recollection On the Development of Pascal, Wirth, 1993
Recollection On the Development of Pascal, Wirth 1993
Recollection On the Development of Pascal, Wirth 1983

A Plea for Lean Software, Wirth, February 1995
Good Ideas, Through the Looking Glass, Wirth, 2006
Good Ideas, Through the Looking Glass, Wirth, 2005
On the Design of Programming Languages, Wirth, 1974
Turing Award, Wirth, 1984
Type Extensions, Wirth 1988
What can we do about the Unnecessary Diversity of Notations for Syntactic Definitions, Wirth ,1977
A plea for Lean Software, Wirth, February 1995
Zwanzig Jahre Institut Informatik. F. Bauer, Edsger Dijkstra, 1988
Finite State Machines, Programmable Logic Devices, and the Crux of Growing Complexity, 2008
The Year of Informatics, 2008
Computers and Computing A Personal Perspective, December 2015
A Triptychon of Digital Circuits, August 2005
Was ist ein Denkplatz, und warum erstreben wir ihn?
Als Computer noch erklärbar waren, 2008
A Brief History of Software Engineering, 2008
A Note on Division, 2008
An Essay on Programming, 1999

Carlo Pescio A Few Words with Niklaus Wirth Software Development, Vol. 5 No. 6, June 1997

Lilith section updated

I have added the repository by Jos Dreesen on Lilith and the Emulith emulator with a local copy.
Jos maintains a ftp with just the files, I made it available as web pages here with higher availability and easier viewing of images and videos.

Emulith

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

Project Oberon

Hardware FPGA implementation document by Niklaus Wirth

Project Oberon emulators

Emulator for the Oberon RISC machine by Peter de Wachter

Oberon RISC Emulator for Pascal Markus Greim

Project Oberon emulator in JavaScript and Java  Michael Schierl

Pipistrella hardware FPGA

Here is a summary of acronyms and version names jwr robrts net gleaned from
various messages and sources. Please provide feedback and corrections
as appropriate.

ALO ARM Linux Oberon (Oberon in LNO family, for ARM CPU eg Raspberry Pi)
ETHO ETH Oberon (ETH is Eidgen?ssische Technische Hochschule Z?rich)
LEO Linux ETH Oberon [ETHO 2.4.3 for Linux x86]
LNO Linux Native Oberon
NO Native Oberon
OCP Oberon Community Platform
OLR Oberon Linux Revival

Is ETH-Linux-Oberon the same as LEO or LNO? (Probably it is LEO.) Is
Linux-ETH-Oberon the same as LEO? Same as ETH-Linux-Oberon?
See https://lists.inf.ethz.ch/pipermail/oberon/2015/007996.html
and https://lists.inf.ethz.ch/pipermail/oberon/2008/005410.html

BB BlackBox Component Builder, Component Pascal IDE
from Oberon Microsystems, http://www.oberon.ch/blackbox.html
CP Component Pascal
[A dialect in the Oberon family most similar to Oberon-2]

AOS Active Object System (2003)
UnixAOS Unix-based AOS
WinAOS Windows-based AOS
Bluebottle New system based on AOS kernel (2005)
A2 New system after Bluebottle (2008)
See http://www.oberon.ethz.ch/ for AOS/Bluebottle/A2 history
Crazy-Fresh Bluebottle [see http://www.ethoberon.ethz.ch/] Crazy-Fresh
A2 [see http://sourceforge.net/projects/a2oberon/files/]

The following appear to be versions of the language definition itself.
In another message another day I plan to identify documentation for each.

Original Oberon (1987/88/90)
Revised Oberon (1992) [later called Oberon-07]
Oberon-2 is a compatible superset of Revised Oberon (1992)
Oberon-07 is a new language based on Oberon and Oberon-SA
See http://oberon07.com/ and http://oberon07.com/FAQ.xhtml
See https://www.inf.ethz.ch/personal/wirth/Oberon/Oberon07.pdf
See https://www.inf.ethz.ch/personal/wirth/Oberon/Oberon07.Report.pdf
Project Oberon (1992) Ceres-based NS32032 implementation of Revised Oberon
see http://www.ethoberon.ethz.ch/WirthPubl/ProjectOberon.pdf
Project Oberon (2013) FPGA-based RISC5 implementation of Oberon-07
see http://www.projectoberon.com/ and
https://www.inf.ethz.ch/personal/wirth/
Oakwood Guidelines for Oberon-2 Compiler Developers

Other names found for various Oberon implementations and versions include:

Oberon S3 = Oberon System 3 (Became ETH Oberon)
Oberon V4 (Associated with both ETH and University of Linz)
See http://sourceforge.net/projects/oberon/ and
http://www.ssw.uni-linz.ac.at/Research/Projects/Oberon.html
See http://users.cms.caltech.edu/~cs140/140a/Oberon/system_faq.html for
Oberon = V1 ( V2 V4 | System3 )
Oberon V1 [Original Oberon??]
Oberon V2 [??]
Oberon V4 [Started at ETH, more development at University of Linz]
Oberon System3 [Became ETH Oberon]

Native Oberon [Based on ETH Oberon]
(see http://www.oberon.ethz.ch/downloads/index for current versions)
(see http://www.oberon.ethz.ch/archives/systemsarchive/native_new)
PC Native Oberon [for Intel-compatible PCs]
PC Native Oberon for Dummies [for Windows installation]
Linux-based Native Oberon [LNO]
SharkOberon [for DEC Shark Network Computers, ARM-based]
Native Oberon Alpha [http://www.oberon.ethz.ch/faq/faqnativealfabeta]
Native Oberon Beta [see same link as Alpha]

Versions at http://www.oberon.ethz.ch/archives/languagearchive/genealogy
Oberon
Oberon-V
Oberon X
Active Oberon
Oberon-SA
Active Oberon for .NET
Object Oberon
Oberon-2
Concurrent Oberon
Action Oberon
Oberon-D
Component Pascal

Versions at http://www.ethoberon.ethz.ch/genealsys.html not already above
SPARC-Oberon
MacOberon
DEC-Oberon
RISC Oberon
MS-DOS Oberon
Chameleon Oberon
HP-Oberon
Oberon for Windows
Spirit of Oberon
Hybrid Oberon
Oberon for Linux
Oberon Linux PPC
more versions named according to supporting OS?

Another acronym observed is OP2, which is a Portable Oberon compiler
by R Crelier

School of Niklaus Wirth: The Art of Simplicity

School of Wirth

Got myself an excellent book on the Art of Simplicity. Niklaus Wirth designed programming langauages like Pascal and sequels like Modula-2 and Oberon.  His style and dedication to simplicity in a clear writing and presentation style made a great impression on me.

This book gives unique insights in what has happened and is still happening in the school of Niklaus Wirth. Excellent book!

From the Back Cover

Niklaus Wirth is one of the great pioneers of computer technology and winner of the ACM’s A.M. Turing Award, the most prestigious award in computer science. He has made substantial contributions to the development of programming languages, compiler construction, programming methodology, and hardware design. While working at ERH Zurich, he developed the languages Pascal and Modula-2. He also designed an early high performance workstation, the Personal Computer Lilith, and most recently the language and operating system Oberon.
While Wirth has often been praised for his excellent work as a language designer and engineer, he is also an outstanding educator – something for which he is not as well known. This book brings together prominent computer scientists to describe Wirth’s contributions to education. With the exception of some of his colleagues such as Professors Dijkstra, Hoare, and Rechenberg, all of the contributors to this book are students of Wirth. The essays provide a wide range of contemporary views on modern programming practice and also illuminate the one persistent and pervasive quality found in all his work: his unequivocal demand for simple solutions. The authors and editors hope to pass on their enthusiasm for simple engineering solutions along with their feeling for a man to whom they are all so indebted.

Contents

Editors: László Böszörményi, Jürg Gutknecht, Gustav Pomberger

Photos and videos Lilith

In may 2006 Jos Dreesen send me the following photos of a surviving, but then not functional Lilith. In january 2008 Jos succeeded in having this machine running again, one of the few functional remaining Lilith computers (there may be a functioning one at ETH, about ten are known to exist)!

Lilith

Lilith

Lilith

Lilith

Photos made by Jos Dreesen, 2006

Lilith

Lilith

Lilith

Lilith

Lilith

Lilith

Lilith

Lilith

Lilith

Lilith

Lilith

Lilith

Lilith

Lilith

 

Lilith
Lilith
ALU
Lilith
Backplane
Lilith
Lilith
CDP
Lilith
Lilith
DSK
Lilith
Lilith
DSP
Lilith
Lilith
IFU
Lilith
Lilith
Lilith
Lilith
M128
Lilith
Lilith
Lilith
Lilith
M64
Lilith
Lilith
Magnet
Lilith
Lilith
MCU
Lilith
POWER
Lilith
Lilith
SD120

Photos made by Jos Dreesen, 2008-2012